Error Handling Strategy Question

I am asking this question more as input/feedback on error handling strategies than as a purely technical question.

As I try to enhance the robustness of my code, one of the factors I am considering is the error handling.

In particular, I am considering adding a seperate error handling section for each function.  Is this overkill?

As I write every "subprocedure" as a function (returning 0 on success, error number otherwise) I can see the problem with program flow: every successive step needs to check the preceeding steps' (or functions) return values.  And my main function consists of a bunch of statements similar to...

If Not intErrorValue Then intErrorValue = intPerformNextFunction(blah1, blah2, blah3)

Would I be best to provide only specialized error handling where needed, and let the majority of error fall into a centralized error handling procedure?  This would seem to relieve me of constantly checking my interal error values and the overhead of creating the error handling (no matter how simple) for each function.

I suppose that centralized error handling is the way to go.  Perhaps this would be best viewed as being similar to flying a plane... turn the autopilot on, and leave it alone unless you really need to.

Who is Participating?
TimCotteeConnect With a Mentor Head of Software ServicesCommented:
Given your scenario, and assuming you are using VB6 and not .Net then you could actually use centralized error handling. However the meaning of this is not necessarily what it appears, in VB6 if you have an error handler at one level of an application then any procedures/functions called from that (that do not have their own explicit error handling) will immediately return execution to that error handler in the procedure above *WITHOUT* returning an error message necessarily. So an error handler in Sub Main for example would indeed handle all errors by preventing an error dialog but would not provide appropriate "handling" of an error in any procedure. This might in your scenario actually give you false results, consider this scenario:

If Not intErrorValue Then intErrorValue = intPerformNextFunction1(blah1, blah2, blah3)
If Not intErrorValue Then intErrorValue = intPerformNextFunction2(blah1, blah2, blah3)

Private Function intNextFunction1(blah1,blah2,blah3) As Integer
  Dim intResult As Integer
  intResult = 5467893/0
  'some more code
  If WeHadAnError Then
    intNextFunction1 = MyErrorValue
  End If
End Sub

The line intResult will generate an error which will not be handled in that function, immediately return to the calling procedure and because the return value has not been set it will still be 0 and therefore you will see the function as completing with success even though it patently did not do so!

Generally speaking though it is a real PIA to do it, I favour properly tailored error handling in every function/sub so that you can implement recovery strategies if necessary, by all means have a single line which records these errors with a centralised procedure but in the long run centralised error handling can be more of a pain than a benefit.
Alon HirschSoftware Development ManagerCommented:

Error handling should be built into each sub / function in order to correctly handle the errors.
If you have a central error handling routine, the sub / function where the error is raised is abandoned in order to call the error handling code.
If you include error handling in each sub / function then you are able to recover where possible or at least take the appropriate action WHERE and WHEN the error occurs.
It also makes it simpler to debug and trace where errors are occurring.

Just to endorse the above comments. I ALWAYS use a specific error handler in ALL routines (Subs or Funcs) unless there's a good programming reason NOT to do so.

Alon's comment about error tracing is crucial - particularly when the program has been issued. If your handler indicates the module/form/routine when an error occurs you can go straight to the correct place in the project, minimising downtime etc etc.

You can still use "Erl" (on VB5 anyway) to further refine the place where the error happened - although there's a purist argument that says that routines should be that big anyway to need this.

I personally use Functions declared as BOOLEAN and I let the Error Handler do the talking. This is in my working environment, you may require a different strategy in yours:

Function X() As Boolean
   On Error Goto X_Err
   X = False
   X = True
   Exit Function

   FatalError Err.Number, Err.Description, "in X", _
      "in Form ...", "..any other info"
   ' FatalError logs, shuts down and never comes back here
End Function

Overkill? Nope.
Alon HirschSoftware Development ManagerCommented:
My subs / functions resemble PNJ's - it works for me and it works well.

We also use DevPartner's Failsafe utility. It adds error handling to each sub / function for you and can also add line numbers.
You can customise haw the errors are handled at run time : for Beta software - enable full / most detail; for more stable software - less vigorous etc. When an error occurs, you can see the complete call stack, form name, module name, sub name, parameters passed to the sub, other processes running etc.
The user can actually type in what they were doing and this all gets saved to a file.
This file can also be emailed automatically to you if need be (MAPI not SMTP).

Definately what I recommend.

mjs082969Author Commented:
Thanks for the feedback guys!  
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.