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.

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • digg
  • DZone
  • Ma.gnolia
  • Reddit
  • Simpy
  • Slashdot
  • StumbleUpon
  • Technorati

6 Responses to “Checked Exceptions: Failed Experiment?”

  1. 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. 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. 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. 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. 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. 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…).

Leave a Reply