exceptions considered harmful

I like simple rules of thumb that will help developers create better, more adaptable designs. So here’s another: Never throw an exception. And if someone throws one at you, catch it immediately and don’t pass it on.

Why? Aren’t exceptions one of the mainstays of modern programming? Joel Spolsky outlines the basic arguments against throwing exceptions:

“…I consider exceptions to be no better than “goto’s”, considered harmful since the 1960s, in that they create an abrupt jump from one point of code to another. In fact they are significantly worse than goto’s…”

But then he goes on to give advice that I consider questionable at best, by suggesting that you catch exceptions quickly and convert them into return codes. I agree that they should be caught at the earliest possible moment, but I disagree with converting them into return codes. Because although that certainly makes the mechanism visible to the reader of the code, it still represents strong coupling where there should be none. The caller – or someone further back along the call stack – has to know about, and take action in response to, someone else’s problem. It seems to me that such coupling violates the pragmatic programmers’ tell don’t ask principle.

So what can we do when someone throws an exception at us? To avoid strong coupling between parts of the system we shouldn’t inform the caller that we had a problem. Instead, the object that catches the exception should set its own state such that it will answer future messages in the light of the problem that occurred. (In particular, the NullObject or SpecialCase pattern is useful here.)

For example, suppose we have a system that uses an external search engine, displaying the results on a GUI. And suppose that the API to the search engine throws an exception if the engine cannot be contacted – for example if the network connection is not available. If this occurs, we wish the GUI to display an error message instead of the search results. The above argument states that we shouldn’t put a try-catch block in the GUI, with the catch part containing the code to display the error. Instead, the SearchResult object returned by the engine could be special, having internal state that accords with the failure. Further, the tell-don’t-ask rule tells us we still shouldn’t query the SearchResult‘s state in order to discover what to display. Instead the GUI could tell the object to display itself. Then a normal SearchResult object would display a table of results, while a special SearchResult object would display an appropriate error message.

Finally, note that the above also has implications for hexagonal architectures. The only code in our system that is permitted to throw exceptions is now the APIs we use. And the adapters that connect us to those APIs must catch any exceptions immediately, before they can propagate up into the inner hexagon where the domain and applicationm objects live. The presence of try-catch blocks is therefore yet another difference in code style between the inner and outer hexagons.

Advertisements

4 thoughts on “exceptions considered harmful

  1. I just stumbled onto your blog recently, and find it extremely interesting.
    I can’t agree on the exceptions issue, for several reasons. First is because the context of the exception matters. Two cases of interest are:

    internal code paths
    component boundaries (APIs, roughly)

    Internal code paths littered with exception-handling logic are deadly to maintainability, and annoying to boot. If you have a chain of private methods, having each one catch and handle exceptions, or provide null-object semantics, is a waste of time. Until you reach the component boundary, there’s no harm, and quite a bit of good, in throwing the exceptions.
    At the component boundary, it’s not always feasible to provide a NullObject equivalent. Doing so implies that the return type must account for every potential use, by a GUI or invoking service, and that’s the tail wagging the dog. In your example, “telling an object to display itself” is quite involved. Now any object which can ever (in any way) be “displayed” (which implies any form of output at all) must provide not only that display logic, but also corresponding null-object display logic, which can be very different indeed (e.g. a message in a special buffer or area of the screen, rather than the table of results).
    Again, this implies a very nasty chain; much nastier than just catching exceptions at user boundaries, or at worst throwing abstraction-level exceptions as appropriate (e.g. “throw new UserInformationNotAvailble()” rather than an LDAP or SQL or whatever Exception).

  2. Pingback: 2005 silk and spinach top ten « silk and spinach

  3. Hmmm. The fact that this looks like the tail wagging the dog is just an implication of dependency inversion, and “telling an object to display itself” can be handled with a strategy. Yes? No?

    (I didn’t work it through in code to see where it led…)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s