Moving Forward

Homepage of Andrew Robinson

Stages of Exception Handling Maturity

with 6 comments

Exceptions always seemed weird to me. Why would I want to catch an exception, when with proper coding they shouldn’t occur in the first place? I felt at first like exceptions were designed into the language for someone else to use, and even when I did want to make use of them I found them awkward and cumbersome.

After resisting exceptions for a while, I started to come around. It started to become clear that even if code is perfect (which it rarely is) there is still a pile of network and system related errors that can occur. While one way to handle these errors is to add return codes to all functions that happen to touch the outside world, a perhaps cleaner way is to throw an exception. All of the sudden exceptions became cool.

Knowing that exceptions have a time and place in a program, I started designing all kinds of complex exception handling machinery. My code was destine to handle all exceptions with grace and ease, and easily recover. An exception handler would in turn try another body of code that could throw an exception, which would enter a wait state before retrying and catching another exception and so on. It was quite a mess, and the more I developed these techniques, the more I became acutely aware that this wasn’t really the right way to do things either. Applications simply can’t be able to recover from every possible scenario.

A few years and a couple of paradigm shifts later I’m finally starting to see what the point of catching an exception is, why they are useful, and what to do when one occurs. The bottom line is the point of an exception is to limit damage when something unexpected happens in your code, get back to a known state if possible, or abort if not. Exceptions do not make your code bullet-proof, however they do a great job of mending wounds and keeping the system up, despite unexpected occurrences. Nowadays my exceptions follow a pretty rigid two-phase pattern, restoring state and restoring flow control, and this works reasonably well.

Restoring State

The most immediate goal of an exception is to return the application to a known state. This involves performing any necessary maintenance on modified data structures, managing any unmanaged resources that need to be released, and deleting any temporary files that had happened to be created during the execution of the routine.

I’ve been doing a lot of server work lately, and this usually consists of another try block to close any open database connections, and an iteration through a list of temporary files. As certain methods execute in my program that use intermediate files they keep a list of created temporary files, and my error handling routine iterates through this list and deletes any files still in existence.

In other cases I end up deleting items from a HasMap structure, where the value of the entry points to an incompletely initialized object. Either way, after this part of the exception routine is done, the application should be in a state identical to before it entered the try block.

Restoring Flow Control

After restoring the application’s state, the next problem is where to transfer flow control to. I’ve found that exceptions usually break down into two pretty clean categories.

Temporary exceptions occur when servers go down, or network requests fail. They are often transient, and upon retrying might succeed. For these kinds of exceptions I usually implement some sort of retry loop, with a fixed number of retries allotted based on the timing requirements of the function I’m in.

Permanent exceptions involve events that are not likely to ‘fix themselves’ if given time. File permissions issues, logic errors, and most other non-IO exceptions fall into this category. When I encounter this kind of exception the show is basically over. If the exception occurs in a reasonably compartmentalized task, as is often the case, the entire program doesn’t need to cease execution, we after all did restore it to a known state, but we do need to abort the current task and present a failure message to the user.

When a temporary exception times out after a certain number of retries it too becomes a permanent exception.

Exception Hierarchy

In this model it’s actually really reasonable to throw in a hierarchical approach to exceptions as well. It’s common in the Java world to catch an exception, only to throw another one. For example a class named MagicMoneyWorker might throw MagicMoneyWorkerException exceptions as a result of network timeouts when performing remote procedure calls. It has wrapped the more low-level exception with a high level one.

The reasons for doing this fit well with the object oriented approach to programming. The MagicMoneyWorker class probably knows best how to handle a network timeout. It knows how to preserve it’s inner state, and recover, and probably even has some retry and reconnect logic built in to it. By the time it’s done handling the exception, if an error occurs, it’s a permanent exception and it means that the task at hand failed. This needs to be handled now by the caller function.

Wrapping exceptions in this manor allows you to keep the primitive exceptions hidden, and preserves the level of abstraction you’re operating with. If you’re writing a function that deals with MagicMoneyWorkers on a high level, you don’t want to have to dive into the bowels of the implementation. It makes much more sense for an exception with a matched level of abstraction to be thrown, and for your function to act on this exception.

Simply my Personal Approach

I doubt this approach will work well for all systems or applications, but I’ve found it works reasonably well for my development lately. Throughout my computer science education there hasn’t been much focus on how to handle exceptions. I think they are considered more of an engineering problem, because the code we deal with is so algorithmic in nature, and brushed under the rug as something you’ll pick up over time. Developing a personal framework for how to handle an exception, and giving a rigid procedure, purpose, and ordering to the process has tremendously helped hone my skills in developing real world applications. If you don’t have a clear idea of how to deal with exceptions in your own projects, I would definitely recommend spending some time to mediate on them and figure out what the goals of catching an exception are for you.

Written by Andrew Robinson

May 1st, 2012 at 6:42 pm

Posted in Java

6 Responses to 'Stages of Exception Handling Maturity'

Subscribe to comments with RSS or TrackBack to 'Stages of Exception Handling Maturity'.

  1. Eric Roch

    8 May 12 at 5:30 pm

  2. I’m curious, what language are you deving in? Do you make use of finally blocks much? Also, have you thought much about the problem that sometimes it’s hard to know what exceptions a piece of code (particularly external libraries) can throw so that you can catch specifically those errors?

    Otherwise, this advice sounds very much in line with my own thoughts on on exception handling over at:

    http://www.russellallen.info/post/2011/03/11/C-net-Exception-Handling-Best-Practice-As-Easy-as-1-2-3.aspx

    Russell Allen

    2 Jul 12 at 7:25 pm

  3. I love finally blocks! Lately I’ve been doing a lot of C# development, however I’ve worked in almost all of the major languages.

    External libraries (hopefully) document what exceptions they throw. If not, yeah, that sucks. The real kosher way to do it in the case of .Net would be to run the library in an isolated app domain if possible.

    Andrew Robinson

    3 Jul 12 at 4:08 am

  4. Przęsła ogrodzeniowe są najlepszym rozwiązaniem gdy chodzi o montarz systemu grodzeń, jest efektywny zarówno
    na terenie prywatnych posesji, ale również przy zwyczajnym ogrodzeniu domu oraz lasów.

    Montażsiatki leśnej zapewnia opiekę przez wandalami, którzy niszczą cudzą własność dla przyjemności.

    Główną cechą chzakterystyczną jest mnogość zastosowań.
    Zaletą takiego rozwiąznia, jest też jego wydajność oraz .
    Polecam.

  5. Zaślubiny już wkrótce więc przyszedł pora aby odszukać ten cudny i prześliczny
    pierścionek zaręczynowy. W dzisiejszych czasach wybór pierścionka zaręczynowego zależy od upodobań
    przyszłego narzeczonego oraz od zdolności finansowych. Oferta punktów jubilerskich jest bardzo zróżnicowana.
    Jaki pierścionek zaręczynowy kupić? Obyczaj mówi o złotym, każdy o tym wie.
    Jeżeli przyszła żona nie lubi pretensjonalnych pierścionków można zdecydować się
    na srebro, które równie uroczo i bogato wygląda. Biżuteria może też
    być wykonana z dwóch kruszców np. białego i żółtego złota
    lub żółtego złota i srebra co w połączeniu z topazem i szafirami zauroczy naszą przyszłą żonę.
    Fajnym pomysłem na poszukiwanie pierścionka jest sklep internetowy.
    Takie wyjście z sytuacji jest pragmatyczne, dlatego, że możemy komfortowego obejrzenia
    i porównania wyrobów.

  6. Obesity is very common nowadays because these Pure Green Coffee Bean
    Extract 800 Mg are also acting as an appetite suppressant and stops the hunger pangs.
    However, once for sale, several ingredients
    made from ephedrine alkaloids still appear in diet pills
    nowadays is definitely Zotrim.

Leave a Reply