The Bad Practices of Exception Handling
Exception handling has truly been a blessing to us software developers. Without it, dealing with special conditions and writing robust programs was a lot more painful. But, like any powerful tool, badly used it could cause more harm than good. This article name the top three on my Exception handling bad practices list, all of which I’ve been practicing in the past but now stay away from.
Swallowing Exceptions
Have you ever come across code like this?
try
{
DoSomeNonCriticalStuff();
}
catch (Exception e)
{
// Ignore errors
}
DoStuffThatMustBeDoneDispiteAnyErrorsAbove();
Of all the bad exception handling practices, this is the worst since its effect is the complete opposite of the programmer’s intention. The reasoning goes something like this: Catching exceptions where they don’t hurt makes my program more robust since it’ll continue working even when conditions aren’t perfect.
The reasoning could have been valid if it wasn’t for Fatal exceptions; Here described by Eric Lippert.
Fatal exceptions are not your fault, you cannot prevent them, and you cannot sensibly clean up from them. They almost always happen because the process is deeply diseased and is about to be put out of its misery. Out of memory, thread aborted, and so on. There is absolutely no point in catching these because nothing your puny user code can do will fix the problem. Just let your “finally” blocks run and hope for the best.
Catching and ignoring these fatal exceptions makes your program less robust since it will try to carry on as if nothing happened in the worst of conditions, most likely making things worse. Not very Fail fastish.
So, am I saying that ignoring exceptions is bad and should always be avoided? No, the bad practice is catching and ignoring general exceptions. Specific exceptions on the other hand is quite OK.
try
{
DoSomeNonCriticalStuff();
}
catch (FileNotFoundException e)
{
// So we couldn't find the settings file, big deal!
}
Bad example, I know, but you get the point.
Throwing Exception
Here’s another bad practice I come across every now and then.
throw new Exception("No connection!");
The problem is that in order to handle Exception we have to catch Exception, and if we catch Exception we have to be prepared to handle every other type of Exception, including the Fatal exceptions that we discussed in the previous section.
So, if you feel the need to throw an exception, make sure it’s specific.
throw new NoConnectionException();
If the idea of defining lots of specific exceptions puts you off, then the very least thing you should do is to define your own application exception to use instead of the basic Exception. This is nothing I recommend though, since general exceptions, like ApplicationException, violate the Be specific rule of the Three rules for Effective Exception Handling. It’ll make you depend heavily on the message property to separate different errors, so don’t go there.
Overusing exceptions
Exceptions is a language construct to handle exceptional circumstances, situations where a piece of code discovers an error but don’t have the context necessary to handle it. It should not be used to handle valid program states. The reasons are:
- Performance. Throwing an exception with all that’s involved, like building a stack trace, will cost you a second or so.
- Annoyance. Debugging code where exceptions are a part of the normal execution flow can be frustrating.
Eric Lippert calls those exceptions Vexing exceptions, which I concider a great name given the second argument. Make sure you’ll check out his article (link at the beginning of this article).
…
Those were the three misuses of exception handling I concider worst. What’s on your list?
Cheers
I’ve learned the hard way that if you don’t define the specific exceptions that can occur in your method it can become a real pain to debug. Esp. if the method is wrapped in a dll that and you are calling it. Much better to take the time and pain to go ahead and add all the exceptions. It will save you time in the end.
@George
I second that! 🙂
@George
Just be sure not to overuse them. What I keep in mind when handling exceptions is you handle them to give users an idea about why something happened. Exceptions are primarily for users not us developers. Think of the users first then you as the developer.
For web development I pretty much has stopped using exception handling entirely. Custom error page pretty much handles everything, I just have an ovveride method that records the error and lets it continue regardless of its location in the application. You wouldn’t believe how much code bloat it destroys.
@Bob Santos
Great tip Bob. I haven’t thought of it that way myself but it makes perfect sence.
@Al Katawazi
I guess that’s the extreme implementation of catching late, the third rule of Effective exception handling. 🙂
At least with the case of Java (and I suspect other popular languages), fatal exceptions tend not to actually be Exceptions. For example, OutOfMemoryError is an Error, which itself is a Throwable. You won’t be able to catch an Error by just catching Exception. Also, Error’s are not checked exceptions, so the compiler will never force you to deal with such fatal exceptions.
Personally, I feel catching a general Exception is fine (if you handle it properly and not just swallow it), but catching Throwable or Error should be considered a big risk.
Also, your comment “Throwing an exception with all that’s involved, like building a stack trace, will cost you a second or so” I think is incorrect. Yes, exceptions are costly (to throw), but they will NOT cost you a second or so. Do some performance tests if you don’t believe me. The key point about considering performance with exceptions I believe is to avoid using them when it is the common workflow. If you are using an exception to regularly break out of a loop, or indicate a common situation in your code… that is when you might start hitting performance costs because of them. Reserve them for truly exceptional conditions and you should be fine.
Otherwise, good post!
‘eating’ exceptions is always bad. It destroys the entire stack trace and make the software maintenance, a nightmare.
@Mike Stone
Thank you for your comment Mike.
In the case of Java you’re probably right (it has been a long time since I had the pleasure of working in that great language), but in the case of C# fatal exceptions inherits from the Exception base class (via SystemException in between). That’s why I think catching Exception is a bad idea, except of course at your program’s entry points to implement your own unexcpected exception handling strategy.
And, of course, “a second or so” was an exageration, but not impossible in some cases. It depends on the situation, the depth of the stack trace etc. Anyway, that’s not the biggie for me.
@Veera
I agree – obviously 🙂
Lol, your last two posts are quite the “ah the world” and subsequent “oh the world”.
Greetings I recently finished reading through your blog as well as I’m very impressed. I truly do have a couple questions for you personally however. Think you’re thinking about doing a follow-up submitting about this? Will you be gonna keep bringing up-to-date also?