Friday, May 14, 2010

Exception Meaning

In object-oriented programming languages, there is a special type of abstraction called an exception. Depending on which language you're using, exception instances can be raised or thrown and caught or excepted. The terminology used is somewhat irrelevant as the general concept remains the same; exceptional behavior has taken place and needs to be dealt with.

Most languages provide a set of standard exceptions that are always available. These exceptions typically build on a base exception class. For instance, in Python, all standard exceptions inherit the base Exception class. This means that developers can also write their own exception types. So if a standard set of exceptions already exists, why bother writing new exceptions?

Exceptional behavior in programs don't just randomly happen. As always, there is a cause and effect. If your program is behaving exactly as it was intended, there is a reason it is doing so. Imagine you have a Python program that only raised Exception exceptions. You could pass some data indicating why the exception occurred to the exception instance. This way the handler could figure out what went wrong.

What if the handler doesn't know what to do with the exception? That is, it doesn't know how to handle the error. The exception handling behavior has been invoked for no good reason. Consider looking up a dictionary key that doesn't exist. In this case, you'd get a KeyError exception. This type of exception has real value because it knows exactly what went wrong. The normal behavior provided a key and expected a value in return. The correct exceptional behavior can now execute because it knows exactly what went wrong.

If the normal behavior doesn't define an exception handler for actions that might raise an exception, any exceptions that are raised will propagate outward in the call stack. So, if we have one function that calls a second function, and that second function raises an exception, the first function will receive the exception if unhandled by the second function. Say the second, nested function raises a KeyError exception. The first, outer function better be prepared to handle KeyError exceptions.

The problem here is that KeyError exceptions may not have any meaning in the first function. If the second function has a responsibility to do a dictionary lookup, it should take on the responsibility of handling KeyError exceptions. The second function could raise a custom exception in the event of a KeyError exception that has some meaning in the context of the first function. It is useful to provide a smaller set of possible exception types as the context grows outward as this gives exceptional behavior more meaning.