Dealing with java Exceptions

The following snippet is much too prevalent in production code:


public Result foo() {
try {
// make a call that may throw IOException
// return valid Result object ....
}
catch (IOException e) {
// log error
}

return null;
}


In this code, fictitious programmer Jane decided to be extra helpful by catching the possible IOException and hiding it from the caller. If all goes well, then a valid Result object is returned; if there’s a problem, then a null value is returned, indicating an error.

Jane’s not being as helpful as she thinks because now the caller, indeed every caller, has to remember to check the value of the returned Result object to determine if the method call was successful. If Jane would declare that her method threw IOException, then the caller would have to handle the problem themselves.

The big difference is that if foo() declares that it may throw an IOException, then the caller is forced to handle the problem instead of having to remember to handle it. There are already far too many things to remember; adding a throws clause makes everyone’s job easier.

Here’s another potential problem:

public void bar() {
try {
// do some work
}
catch (Throwable e) {
// log error
}
}

In this case, Jane has caught every possible Error or Exception that might be thrown. This code is so helpful that it’s dangerous. Why catch an Error when there’s nothing you can do about it?

Imagine that an OutOfMemoryError occurs in the bar() method. How will Jane recover from that? She won’t. The point of catching an Exception is normally to do something about it. A java.lang.Error usually means there’s nothing you can do about it, so at least limit yourself to catching Exception.

The worst case scenario looks like this:

public void foo() {
try {
// do some work
}
catch (Throwable e) {
// suppress error
}
}

Jane has decided to catch all errors and hide them from the caller, the application administrator, everybody. Now if an error occurs in the foo method, nothing will happen and nothing will be logged. The application doesn’t work and no one knows why. If you’ve ever had to debug an application that used this form of application trickery, you know how painful it can be. Code that suppresses errors eventually leads to lost hours of work for everyone.

These three examples aren’t the only ways that Exceptions can be misused, but they seem to be the ones that are most problematic for programmers. In the end, handling exceptions is a matter of style, and there are exceptions to every rule. But make sure that when you’re catching an exception you know why. A rule of thumb to use when deciding which exceptions to catch is: If you can’t do something about an error, then don’t catch it.

You should catch exceptions that you can do something about; you shouldn’t catch exceptions on which you can have no effect.

Many programmers still use the following idiom:

try {
}
catch () {
}

What goes in the catch clause? The answer depends on your programming religion. Many people will say that you should catch as much as possible by catching Throwable; some will say that you should limit yourself to catching only Exception; and then there are programmers who would have you catch as little as possible and let something higher up the call stack handle most errors. This tip recommends the third approach.

Catching Throwable in a deeply nested method isn’t normally a good thing to do. If you’re expecting trouble and can do something about it, then, by all means, catch everything.

This entry was posted in Web Site Stuff. Bookmark the permalink.