This project has moved and is read-only. For the latest updates, please go here.

General error handling review

Jul 15, 2014 at 12:44 PM
Edited Jul 15, 2014 at 12:59 PM
I've just posted a new release, with my vbWatchdog addin now enabled at startup.

Ideally I would like to review all the local error handling throughout the application, with a view to taking further advantage of vbWatchdog's features.

To start the discussion, let's look at a typical local error handler that is being used commonly throughout the codebase:
Proc_Err:
   MsgBox Err.Description, , _
        "ERROR " & Err.Number _
        & "   Update_Qry_Attributes"
 
   Resume Proc_Exit
   Resume
In the above, we are not expecting any particular error, but want to display a nice error message to the user when an error occurs. That's great, except by doing this, we are losing out on the main features of vbWatchdog (e.g. reporting callstack, variables dump etc).

I propose that for cases where no particular error is expected, like in the above example, we simply remove the local error handling. That way, vbWatchdog will pickup and report any unhandled errors that may occur, and we get all the nice reporting and error dialogs from vbWatchdog.

I appreciate that in removing the local handler we'd lose the extra 'Resume' statement that is intended for the developers use, but we can easily simulate that from the vbWatchdog error dialog if 'try again'/resume is something developers routinely want as an option when debugging.

In cases where a local error handler is really needed, we can use the ErrEx.CallGlobalErrorHandler method to pass the error back to vbWatchdog if need be.

For example, something like this:
Proc_Err:
   If Err.Number = 123 Then  ' my example, to mute a specific error code
       Resume Next   
   Else
        ' example, we didn't expect this error
        MsgBox Err.Description, , _
        "ERROR " & Err.Number
Would be re-written as:
Proc_Err:
   If Err.Number = 123 Then  ' my example, to mute a specific error code
       Resume Next   
   Else
        ' example, we didn't expect this error
        ErrEx.CallGlobalErrorHandler    ' pass the error back to vbWatchdog, as we don't know what to do with it.
These changes would cut down the codebase considerably (since most procedures won't actually need local error handling now), and I feel would be a worthwhile investment of time considering the benefits of being able to report the callstack, variables dump etc.

Any thoughts? Objections?
Jul 15, 2014 at 2:43 PM
that would be great! thanks, Wayne ~
Jul 22, 2014 at 11:28 AM
Hi Wayne

If we're using vbWatchdog (aka Rover :-)) then why not do the above with:
ErrEx.Catch 123
    Resume Next
... and then Rover takes care of the rest?

Cheers,
Graham
Jul 22, 2014 at 12:57 PM
Hi Graham,

I agree :) I was contemplating mentioning it, but thought that a progressive approach may be warranted, given that most contributors to the project probably aren't familiar with the catch-features of vbWatchdog, and so that syntax may seem somewhat alien to them.

After some further thought, and given the ErrEx.Catch feature does allow for much cleaner error handling, I propose we do use it, provided no-one has any particular objections. I'll leave this open for a week to hear any further views before taking any action.

Cheers,
Wayne.
Jul 22, 2014 at 5:24 PM
"cleaner error handling" is good! Please explain in comments for this is new to many developers ~ Thanks Wayne and Graham!
Jul 22, 2014 at 6:01 PM
Edited Jul 22, 2014 at 6:03 PM
Essentially, the ErrEx.Catch feature allows you to target specific error numbers with specific error handling, and as a side effect, all errors with non-targeted Catch blocks are considered unhandled (unless there is a general normal error handler in place, or the ErrEx.CatchAll block is used).

The vbWatchdog documentation for this feature is here:
TEXT

It's pretty cool because you can reduce code size in your error handlers, and I personally think it makes you code better because you will tend to write more tightly focused error handlers (targeting specific error codes where possible). When using ErrEx.Catch blocks, you also don't need to specify the usual 'On Error Goto' statements, as vbWatchdog handles everything for you.

So, if we wanted to catch a division-by-zero error, we might usually write this:
Public Sub Test()
    On Error Goto ErrHandler
    Debug.Print 1/0 ' Simulate division by zero error
    Exit Sub
ErrHandler:
    If Err.Number = 11 Then   ' Error 11 is Division-by-zero
        Resume Next
    Else
        MsgBox "Oops!  An unexpected error occurred..."
    End If
End Sub
But with vbWatchdog's ErrEx.Catch feature, we could simplify that to:
Public Sub Test()
    Debug.Print 1/0 ' Simulate division by zero error

ErrEx.Catch 11     ' vbWatchdog will catch all other errors, as they are unhandled.
    Resume Next
End Sub
Each ErrEx.Catch block can handle up to 4 error codes (separated by a comma), and you can have as many ErrEx.Catch blocks defined as you like. There are no control-flow statements needed (Exit Sub, etc), as vbWatchdog handles all that for you. There is an ErrEx.CatchAll block as well, which acts much like the usual 'On Error' statements, where all errors pass through to the catch-all block (but without the need for 'On Error Goto').

That's the basics. Let me know if you want any further clarification.