a little madness

A man needs a little madness, or else he never dares cut the rope and be free -Nikos Kazantzakis

Zutubi

Checked Exceptions: Failed Experiment?

Checked exceptions is one of those Java features that tends to work up a lively discussion. So forgive me for rehashing an old debate, but I am dismayed to see continued rejection of them as a failed feature, and even more so to see proposals to remove them from the language (not that I ever think this will happen).

In the Beginning…

Most would agree that mistakes were made in the way checked exceptions were used in the early Java years. Some libraries even go so far as doing something about it. However, an argument against the feature itself this does not make. Like anything new, people just needed time in the trenches to learn how to get the most out of checked exceptions. A key point here is that checked exceptions are available but not compulsory. This leads to a reasonable conclusion, as made in Effective Java:

Use checked exceptions for recoverable conditions and runtime exceptions for programming errors

The key point here is recoverable. If you can and should handle the exception, and usually close to the source, then a checked exception is exactly what you need. This will encourage proper handling of an error case – and make it impossible to not realise the case exists. For unrecoverable problems, handling is unlikely to be close to the source, and handling (if any) is likely to be more generic. In this case an unchecked exception is used, to avoid maintenance problems and the leakage of implementation details.

Continued Criticism

None of the above is new, and to me it is not contraversial. But the continued attacks on checked exceptions indicate that some still disagree. Let’s take a look at some common arguments against checked exceptions that still get airtime:

Exception Swallowing/Rethrowing

Some argue that the proliferation of code that either swallows checked exceptions (catches them without handling them) or just rethrows them all (“throws Exception”) is evidence that the feature is flawed. To me this argument carries no weight. If we look at why exception handling is abused in this way, it boils down to two possibilities:

  1. The programmer is too lazy to consider error handling properly, so just swallows or rethrows everything. A bad programmer doesn’t imply a bad feature.
  2. The programmer is frustrated by a poorly-designed API that throws checked exceptions when it shouldn’t. In this case the feature is an innocent tool in the hands of a bad API designer. Granted it took some time to discover when checked exceptions were appropriate, so many older APIs got it wrong. However, this is no reason to throw out the feature now.

You need well-designed APIs and good programmers to get quality software, whether you are using checked exceptions or not.

Maintenance Nightmare

A common complaint is how changes to the exception specification for a method bubbles outwards, creating a maintenance nightmare. There are two responses to this:

  1. The exceptions thrown by your method are part of the public API. Just because this is inconvenient (and when is error handling ever convenient?) doesn’t make it false! If you want to change an API, then there will be maintenance issues – full stop.
  2. If checked exceptions are kept to cases that are recoverable, and usually close to the point when they are raised, the specification will not bubble far.

Switching every last exception to unchecked won’t make maintenance problems go away, it will just make it easier to ignore them – to your own detriment.

Try/Catch Clutter

Some argue that all the try/catch blocks that checked exceptions force on us clutter up the code. Is the alternative, however, to elide the error handling? If you need to handle an error, the code needs to go somewhere. In an exception-based language, that is a try-catch block, whether your exception is checked or not. At least the exception mechanism lets you take the error handling code out of line from your actual functionality. You could argue that the Java’s exception handling syntax and abstraction capabilities make error handling more repetitive than it should be – and I would agree with you. This is orthogonal to the checked vs unchecked issue, though.

Testing Is Better

Some would argue that instead of the complier enforcing exception handling in a rigid way, it would be better to rely on tests catching problems at runtime. This is analogous to the debate re: static vs dynamic typing, and is admittedly not a clear cut issue. My response to this is that earlier and more reliable feedback (i.e. from the compiler) is clearly beneficial. Measuring the relative cost of maintaining exception specifications versus maintaining tests is more difficult. In cases where an exception almost certainly needs to be recovered from (i.e. the only case where a checked exception should be used), however, I would argue that the testing would be at least as expensive, and less reliable.

Conclusion

I am yet to hear an argument against checked exceptions that I find convincing. To me, they are a valuable language feature that, when used correctly, makes programs more robust. As such, it is nonsense to suggest throwing them out. Instead, the focus should be on encouraging their appropriate use.

Liked this post? Share it!

12 Responses to “Checked Exceptions: Failed Experiment?”

  1. March 12th, 2008 at 5:15 am

    Jose says:

    C# doesn’t have checked exceptions. While that seems convenient while you’re writing code, the problems become evident later when you realize that you should’ve caught certain exceptions. The documentation is often not very good about this.

  2. March 12th, 2008 at 5:18 am

    Jason says:

    Hi Jose,

    Thanks for your comment. You raise a great point about documentation: even with a lot of effort, the docs will still get it wrong. The only way to get them write is to have them verified automatically – which you get for free with a checked exception.

  3. March 12th, 2008 at 5:43 am

    Squirrel Sewer says:

    I think you are fighting the good fight: good error handling is the cornerstone of a maintainable system. I don’t agree w/ the Effective Java quote, tho.

    “Use checked exceptions for recoverable conditions…”
    What percentage of the Exceptions in your code relate to a recoverable conditions? I maintain a large webapp, and my personal answer is “very few, maybe none”. I want to handle errors, I really do.

    “and runtime exceptions for programming errors”
    Runtime Exceptions have a very big problem – they produce awful stack traces. Checked exceptions, used properly, get caught and wrapped at every level of the call stack, and end up providing all kinds of juicy data when you are reading over the stack. Why should programming errors have awful stack traces? They’re way more common than recoverable problems, and just as import to diagnose.

    I don’t have any great solutions, just wanted to point out I rarely see opportunities for meaningful recovery, and that I hate stack traces caused by RuntimeExceptions slipping up to the top of the call stack w/ no chaining.

  4. March 13th, 2008 at 8:55 am

    peter lawrey says:

    Checked Exception have there place. When designing an API I rause checked exceptions when I expect the caller to handle them. I err on the side of not creating too many variations of checked exceptions so the caller can catch them fairly genericly but still hold enough information to do something about it.
    Generally, I would say the callee should try to handle recoverable exceptions however there is often a human involved and notifying them that an operation has failed is important.
    Developers typically start by just trying to get something which works, getting something which robustly handles error conditions (assuming you know all possible error conditions) is much harder.
    For those who like rapid prototyping I can understand that checked exceptions are annoying, in which case something like groovy or ruby might be a better choice. (I don’t know how their exceptions work…)

  5. March 13th, 2008 at 8:59 am

    peter lawrey says:

    Given that methods deprecated in Java 1 are still there today do make removing checked exceptions rather unlikely.
    You could have all your method “throws Exception” and ignore them completely if you want to treat them as fatal or ignored at random.
    I am not one of them. ?

  6. March 19th, 2008 at 1:36 am

    Hugo says:

    Hi Squirrel
    about the awful stack traces due to runtime exceptions: you might like have a look at http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.UncaughtExceptionHandler.html
    and Thread.setDefaultUncaughtExceptionHandler(….)

    These provide a way to handle runtime exceptions in a custom way (file logging, dialog, etc…).

  7. June 1st, 2010 at 7:26 am

    Chris says:

    >> You need well-designed APIs and good programmers to get quality software, whether you are using checked exceptions or not.

    The above argument works against the need for checked exceptions as well. Afterall, you need good programmers and good APIs thus there is no need for language level things like checked exceptions to protect you from bad designs and programmers.

    This argument holds no weight in the real world where no API is perfect and no programmer is either.

  8. June 3rd, 2010 at 2:51 am

    Beavis says:

    OK, here are my examples, that immediately come to mind. There are a lot more of these, that I know I have to deal with on a continuous basis: exceptions that are _practically_ impossible.

    try {
    MessageDigest md = MessageDigest.getInstance(“MD5”);
    }
    catch (NoSuchAlgorithmException nsae) { throw new RuntimeException(nsae); }

    Here, I’ve _explicitly_ specified my message digest, and since I’m not planning on distributing this, but only running it on our public webserver, I’m never going to be running it where the security manager _doesn’t_ have MD5 sum. Yet, no, _maybe_ somehow mysteriously MD5 will be missing, so I guess I better catch that… But, that’s not as bad as this next one.

    try {
    URL u = new URL(“http://www.yahoo.com/”);
    }
    catch (MalformedURLException mue) { throw new RuntimeException(mue); }

    That URL is _static_. Maybe I’m retrieving a feed from somewhere, I don’t know. But, the URL is _unchanging_, and is _not_ dependent on any user input. _WHY_ must I catch “malformed url exception”?? What am I to do with it? I guess I’m protecting myself if the URL spec changes in the future?

    I’m with Squirrel up there. For the most part, if an exception is thrown, I really can’t do anything about it, and all that the mandatory checked exceptions get me, is code bloat/cruft.

  9. January 18th, 2011 at 8:38 am

    Joshua says:

    The first time I had to throw a checked exception through an interface that didn’t allow it I understood *why* checked exceptions were broken.

    The fact is simple in that it is too primitive a tool that cannot cope with higher-level algorithms.

  10. September 12th, 2011 at 7:57 am

    oopexpert says:

    try {
    URL u = new URL(“http://www.yahoo.com/”);
    }
    catch (MalformedURLException mue) { throw new RuntimeException(mue); }

    This example refers to the API of java.net. As the API-Designer does not know in which context you will use the API this checked exception make sense. In your this case it is a constant in other cases the input comes from a user. As a user input it is an recoverable state. The user can be informed that the entered URL is incorrect and he must enter a correct one.

    The API abstracts fully about low level exceptions. They may be raised like a broken connection but they are not visible to the caller because he would not be able to recover from this. So they are RuntimeExceptions.

    I think this is a proper view on checked exception and I agree, that not every programmer is able to see the different semantics and at last the correct conclusion. Sometimes it is a kind of tricky…

  11. July 23rd, 2013 at 8:35 am

    Patrick Calahan says:

    Five years later and the battle on this still rages on. Few things make me more stabby than the so-called “case” against checked exceptions. I’m glad I found your post.

    One thing that I’ve found can streamline the debate a little bit is to remove the discussion about “recoverability.” It really doesn’t matter whether the caller can be expected to recover or not. If I’m an API, I don’t want to know or care anything about the recovery capabilities of my caller.

    What I do want to do is be able to tell my caller that there are some things that can go wrong even if they follow my API contract perfectly. That’s what a checked exception expresses.

  12. October 11th, 2014 at 9:56 pm

    Winston says:

    I agree in general with the article (and your conclusion), but I’d say that there is more than one issue at stake here:
    1. Checked exceptions.
    2. Java’s *implementation* of them.
    3. The proliferation of “generic” checked exceptions.

    Taking each point in turn:
    1. I agree that checked exceptions are a darn good idea. However, I’d say that they’re rather like someone’s quote about democracy: it’s not that they don’t work; they have never seriously been tried.

    2. IMO, Java’s implementation is flawed because it makes checked exceptions part of the class *hierarchy*. I think it would have been much better to make it a nested MARKER interface (ie, ‘Exception.Checked’). That way, ANY Exception could be made “checked” simply by implementing the ‘Checked’ marker.

    3. I think we all know which ones these are: IOException and SQLException, because most of the time they are NOT recoverable. A particular subclass (eg, FileNotFoundException) *might* be, but unless it’s declared explicitly, I think it’s reasonable to assume that the programmer had no intention of recovering from it.

    My 2 cents.

    Winston

Leave a Reply