demko.ca

<< Back to Posts

Design Patterns: Error Handling

Aleksander Demko,

January, 2015

Background: Exceptions

There are generally three approaches to signaling error conditions from functions to callers. They are:

Exceptions have proven, among the three, to be the best and most general mechanism for handling errors. It allows code to detect and signal errors anywhere, and for the caller programmer to collapse and merge error handling code where it makes sense.

All modern programming languages support them and use them extensively. They are the most productive and clean technique of reliably handling all error paths. Error codes, despite their proponents claims, are rarely used properly:

The most common argument against exceptions tend to be for performance or legacy reasons. For example:

Error Handling Patterns

Despite their strengths, one must understand that exceptions should only be used for exceptional or unexpected errors in a function call. In many cases, it may be useful to add other techniques. When when designing a function, you must factor in the common use cases of the caller.

For example, let's say we are making an ImageArray class, and are implementing the function ImageArray.GetAtIndex(index), which returns the image at the given index. The array might only have count images, so obviously index must be less than count. When implementing such a function, I typically start at the most restrictive (but cleanest and most per formant) implementation first, and then "open it up" as new requirements or usage patterns surface. These are the patterns, with the most preferred listed first:

Nesting Errors

Non-trivial functions may call other functions during their execution. The main function should report these sub-function errors to their callers.

Multiple Patterns

Don't be afraid to use two or more patterns for the same function if the needs arise. These can be done by having multiple functions or by using switches on the same function. For example: