Friday, 11 March 2011

Exception Strategy: Runtime or Checked

Half the battle in trying to build a good application is in designing a coherent way of managing exceptions and dealing with errors. You may think that this is obvious, but I’ve worked on projects where it hasn’t been done and one of the worst side effects of not highlighting errors is to invisibly loose them making your system both buggy and difficult to fix.

Java complicates the matter by offering you two types of exception: checked and unchecked (better known as RuntimeExceptions) and it’s also where some Java controversy arises. If you read Oracle’s (was Sun) link on this, you’ll see that checked exceptions are supposed to be the norm, whereas run-time exceptions should be reserved to indicate programming errors.

I’m on the side that tends to disagree with this idea and tend to think of checked exceptions as something that should be removed from the language in a non-intrusive way: a failed experiment if you like...

Some of the problems with checked exceptions are:

  • Complex code: checked exceptions mean that you need to generate additional, unnecessary code.
  • Wrapping of exceptions required in every layer: using checked exceptions means that every method in the stack trace either has declare and re-throw the checked exception, or catch and convert it to something it can handle - which goes back to the point above.
  • Fragile interfaces. Good interfaces portray a specification in an abstract way underlining the point that it, the interface, is not connected to the implementation. Using checked exceptions in interfaces means that you’re bending the contract somewhat in that the interface is hinting about the implementation.

Having been very negative about checked exceptions, I do feel that they can be useful as a kind of extended return value from a method where you want to force the caller to take notice. All of which means that I favour RuntimeExceptions to cover 99% of all errors and exceptions.

Having chosen which kind of exception to use and why, you also need a consistent way of handling any exceptions that may occur and to me that means adding some kind of catch-all exception trap. An exception trap is that single point in your code where you deal with any exceptions thrown by your application. How you deal with exceptions depends upon your application: a web-app will probably re-direct the user to an error page, whilst an MDB that uses container managed transactions will call setRollbackOnly().

In summary then: favour java.lang.RuntimeException derived classes and ensure that you implement an exception trap.

No comments: