Error handling in mathematical functions

What is good practice for handling errors in math functions? I create a library (module) of specialized functions, and my main goal - to facilitate the debugging of the code that calls these functions - is not to create a brilliant convenient error handling system.

The following is a simple example in VBA, but I'm interested in hearing other languages. I'm not quite sure where I should return the error message / status / flag. What is an additional argument?

Function AddArrays(arr1, arr2) Dim i As Long Dim result As Variant ' Some error trapping code here, eg ' - Are input arrays of same size? ' - Are input arrays numeric? (can't add strings, objects...) ' - Etc. ' If no errors found, do the actual work... ReDim result(LBound(arr1) To UBound(arr1)) For i = LBound(arr1) To UBound(arr1) result(i) = arr1(i) + arr2(i) Next i AddArrays = result End Function 

or something like the following. The function returns the boolean flag "success" (as in the example below, which returns False if the input arrays are not numeric, etc.), or an error number / message of some other type.

 Function AddArrays(arr1, arr2, result) As Boolean ' same code as above AddArrays = booSuccess End Function 

However, I'm not too crazy, as it destroys the pretty and readable syntax of the call, i.e. can no longer speak c = AddArrays(a,b) .

I am open to suggestions!

+3
math vba error-handling
Dec 13 '10 at 14:45
source share
3 answers

Obviously, error handling in general is a big topic, and that best practice is highly dependent on the capabilities of the language you work with and how the program you code is suitable for other routines. Therefore, I will limit my answer to VBA (used in Excel) and subroutines such as libraries of the type that you describe.

Exceptions to Error Codes in Library Programs

In this case, I would not use a return code. VBA supports an exception handling form, which, although not as powerful as the more standard form found in C ++ / Java / ??. NET is pretty similar. Therefore, the recommendations of these languages ​​are generally applied. You use exceptions to indicate calling procedures that the called routine cannot do this work for any reason. You handle exceptions at the lowest level, where you can do something meaningful in this failure.

Bjarne Stroustrup provides a very good explanation of why exceptions are better than error codes for this kind of situation in this book. (The book is about C ++, but the principles for handling C ++ exceptions and handling VBA errors are the same.)

http://www2.research.att.com/~bs/3rd.html

Here is a good passage from Section 8.3:

When a program consists of separate modules, and especially when these modules are developed separately by the library, error handling should be divided into two separate parts: [1] Reporting errors that cannot be resolved locally [2] processing errors found elsewhere libraries can detect runtime errors, but there is no idea what to do with them. The library user can know how to deal with such errors, but cannot detect them - otherwise they will be processed in the user code, and not to the left, to find the library.

Sections 14.1 and 14.9 also discuss exceptions and error codes in the context of the library. (There is a copy of the book on the Internet at archive.org.)

There is probably a lot more about this in stackoverflow. I just found this, for example:

Exception vs. Error Code vs. assert

(There may be errors associated with proper resource management that need to be cleared when using exceptions, but they really don't apply here.)

Exceptions in VBA

This is how an exception is thrown in VBA (although VBA terminology "causes an error"):

 Function AddArrays(arr1, arr2) Dim i As Long Dim result As Variant ' Some error finding code here, eg ' - Are input arrays of same size? ' - Are input arrays numeric? (can't add strings, objects...) ' - Etc. 'Assume errorsFound is a variable you populated above... If errorsFound Then Call Err.Raise(SOME_BAD_INPUT_CONSTANT) 'See help about the VBA Err object. (SOME_BAD_INPUT_CONSTANT is something you would have defined.) End If ' If no errors found, do the actual work... ReDim result(LBound(arr1) To UBound(arr1)) For i = LBound(arr1) To UBound(arr1) result(i) = arr1(i) + arr2(i) Next i AddArrays = result End Function 

If this procedure does not catch the error, VBA will provide other routines above it in the call stack chance (see the following: VBA "Bubble Up" error ). Here's how the caller can do this:

 Public Function addExcelArrays(a1, a2) On Error Goto EH addExcelArrays = AddArrays(a1, a2) Exit Function EH: 'ERR_VBA_TYPE_MISMATCH isn't defined by VBA, but it value is 13... If Err.Number = SOME_BAD_INPUT_CONSTANT Or Err.Number = ERR_VBA_TYPE_MISMATCH Then 'We expected this might happen every so often... addExcelArrays = CVErr(xlErrValue) Else 'We don't know what happened... Call debugAlertUnexpectedError() 'This is something you would have defined End If End Function 

What it means to do something meaningful depends on the context of your application. In the case of an example of the above, he decides that some errors should be handled by returning the error value that Excel can put in the cell of the worksheet, while others require an unpleasant warning. (Here, where the VBA case in Excel is not actually a bad concrete example, since many applications distinguish between internal and external procedures and between the exceptions that you expect to be able to handle and the error conditions that you just want to know about but for which you have no answer.)

Do not forget the statement

Since you mentioned debugging, the role of statements is also worth noting. If you expect AddArrays to be called only by routines that have actually created their own arrays or otherwise verified, they use arrays, you can do this:

 Function AddArrays(arr1, arr2) Dim i As Long Dim result As Variant Debug.Assert IsArray(arr1) Debug.Assert IsArray(arr2) 'rest of code... End Function 

A fantastic discussion about the difference between statements and exceptions here:

Debug.Assert vs Exception Throwing

I gave an example here:

Is affirmation evil?

Some VBA Recommendations on Shared Array Processing Procedures

Finally, as a VBA note, there are VBA variants and arrays with lots of errors that should be avoided when trying to write generic library routines. Arrays can have more than one dimension, their elements can be objects or other arrays, their start and end indices can be any, etc. Here is an example (untested and not trying to be exhaustive) that takes into account some of them:

 'NOTE: This has not been tested and isn't necessarily exhaustive! It just 'an example! Function addArrays(arr1, arr2) 'Note use of some other library functions you might have... '* isVect(v) returns True only if v is an array of one and only one ' dimension '* lengthOfArr(v) returns the size of an array in the first dimension '* check(condition, errNum) raises an error with Err.Number = errNum if ' condition is False 'Assert stuff that you assume your caller (which is part of your 'application) has already done - ie you assume the caller created 'the inputs, or has already dealt with grossly-malformed inputs Debug.Assert isVect(arr1) Debug.Assert isVect(arr2) Debug.Assert lengthOfArr(arr1) = lengthOfArr(arr2) Debug.Assert lengthOfArr(arr1) > 0 'Account for VBA array index flexibility hell... ReDim result(1 To lengthOfArr(arr1)) As Double Dim indResult As Long Dim ind1 As Long ind1 = LBound(arr1) Dim ind2 As Long ind2 = LBound(arr2) Dim v1 Dim v2 For indResult = 1 To lengthOfArr(arr1) 'Note implicit coercion of ranges to values. Note that VBA will raise 'an error if an object with no default property is assigned to a 'variant. v1 = arr1(ind1) v2 = arr2(ind2) 'Raise errors if we have any non-numbers. (Don't count a string 'with numeric text as a number). Call check(IsNumeric(v1) And VarType(v1) <> vbString, xlErrValue) Call check(IsNumeric(v2) And VarType(v2) <> vbString, xlErrValue) 'Now we don't expect this to raise errors. result(indResult) = v1 + v2 ind1 = ind1 + 1 ind2 = ind2 + 1 Next indResult addArrays = result End Function 
+8
Dec 13 '10 at 18:52
source share

PowerUser first gave you a good answer - this is an extension on that.

The trick I just learned is a "double resume", thus:

 Function Foobar (Arg1, Arg2) On Error goto EH Do stuff FuncExit: Exit Function EH: msgbox "Error" & Err.Description Resume FuncExit Resume End Function 

What happens here is that when you run the finished code, your code calls MsgBox when an error occurs, then runs the Exit Function statement and continues its path (just like deleting the bottom with End Function ). However, when you debug and you get this MsgBox, you instead execute the manual Ctrl-Break, then set the next statement (Ctrl-F9) to the frivolous Resume and press F8 a step - it returns directly to the line, which throws an error. You don’t even need to accept additional Resume expressions, as they will never be executed without manual intervention.

In the last example, in another place where I want to argue (softly) with PowerUser. I find it best to avoid unnecessary GoTo expressions. A better approach is If intvar<=2 then err.raise SomeCustomNumber . Make sure you are using a number that is not yet in use. For more information, search for "VB custom error".

+3
Dec 13 '10 at 18:21
source share

There are many ways to catch errors, some better than others. It depends on the nature of the error and how you want to handle it.

1st: In your examples, you do not handle basic compilation and runtime errors (see code below).

 Function Foobar (Arg1, Arg2) On Error goto EH Do stuff Exit Function EH: msgbox "Error" & Err.Description End Function 

2nd: Using the above example framework, you can add all the if-then logical error capture statements you want and feed it to step EH. You can even add a few EH steps if your function is complex enough. Setting this method allows you to find the specific function in which your logical error occurred.

3rd: In your last example, terminating this function as a boolean is not the best method. If you were able to add 2 arrays, then this function should return the resulting array. If not, this should cause an error like msgbox.

4th: I recently started doing a little trick, which can be very useful in some situations. In the VBA editor, go to Tools-> Options-> General-> Break in all errors . This is very useful if you already have an error handling code, but you want to go to the exact line where the error occurred, and you do not want to delete completely good code.

Example: suppose you want to catch an error that will not normally depend on VBA, i.e. an integer variable should always have a value> 2. Somewhere in your code, say If intvar<=2 then goto EH . Then in step EH add If intvar<=2 then msgbox "Intvar=" & Intvar .

+2
Dec 13 2018-10-12
source share



All Articles