Yesterday a co-worker sent me an email about an error that was reported to them. “Have you seen this error before? If you have, can you tell me what it means?” This is a huge pet peeve of mine. Too many developers view exception handling as nothing more than an anti-crash mechanism. When an exception occurs, it gets logged and ignored. If the application’s not working, somebody might look at the log and see a repeated error message in the form of an exception.ToString(). That exception gets reported and travels electronically through the ranks until it makes its way back to the developer: “Oh, that exception?” the developer replies, “That just means the certificate is missing.”
Oh, that’s it? Thanks for the info, but I’ve got news for you: you failed. If you can say “That exception means…” then that’s what the application should’ve reported to begin with. Further, an explanation like this should only be forgivable if it’s followed by “I’ll update the application to say that.” Accepting “<insert exception here> means <actual problem>” as a solution should be unacceptable to all parties involved.
The good news for developers is that this isn’t a hard problem to solve: you just have to not suck at exception handling. The even-better news is that it’s not hard to be a good exception handler, you just have to think about what you’re doing and follow a few easy steps.
Reduce exception handling
My smelly-sense definitely goes off when I see code that has exception handling in every single function. This obviously depends on the code–maybe it’s necessary–but you should try to only include exception handling where it’s needed. If you can’t think of anything that can go wrong, don’t cover it up when the unthinkable occurs.
Of course, if you can think of things that might cause exceptions…
Catch specific exception types
This is where you look at your code and think of everything that might go wrong. If you’re writing a file, what happens if you don’t have permissions or the directory is missing? If you’re calling a web service, what happens if the service isn’t available? What happens if you access that database with invalid credentials? Each of these problems produces a specific exception type that can be caught and handled in its own special way. If you know where an exception could occur but don’t know the specific exception type, test to find out.
It would be rude in all of these scenarios to simply pretend that everything is okay and move on. Instead, do the courteous thing…
Provide meaningful messages
Don’t just tell people what happened, tell them what it means or what they can do about it! Should they restart the application? Do they need to contact an administrator? Is it connection problem? Is this going to resolve itself?
I mean, don’t get me wrong: System.ServiceModel.Security.SecurityNegotiationException “SOAP security negotiation with http://localhost/someservice.svc for target http://localhost/someservice.svc failed. See inner exception for more details” is a terrific error, but you’re not doing anybody any favors by showing it in a message box or writing it to a log. Doing something like that is just begging to be bothered for interpretation later. Instead, provide a meaningful message: “A security negotiation exception occurred. Verify that the certificate exists and has appropriate permissions.”
Remember that updating these messages is an important maintenance step. If a new cause for an exception is identified, be sure to add relevant information to your messages to make them as helpful as possible!
Don’t eat exceptions
One of the worst things you can do is to “eat” exceptions. I’m talking about adding try { … } catch (Exception) { } around all your code where the catch logic does nothing or quietly logs some details without indicating any problems to the rest of the application. I’m not suggesting that you let any and all unaccounted for errors crash your application, but allowing exceptions to fail as loudly as possible will lead to a more robust end product. The squeaky wheel gets the oil, you know? If you follow the guidance above, a new exception that was previously unaccounted for will result in code that specifically handles the newly identified scenario and provide meaningful information. The next time the exception occurs, there should be no mystery around what caused it or what should be done as a result.
Test everything*
*Everything that you can think of. The end goal of most applications is (or should be) to create a positive user experience. To that end, when you’re adding exception handling for specific scenarios and providing meaningful messages, you should verify how it will present to the user. If it’s something the user needs to address, make sure they receive clear information about what they should do. If the user needs to contact somebody, such as an administrator, make sure they know what to tell them. If something happened that the user doesn’t need to worry about, maybe you want to make sure that they can’t tell it even happened. Whatever it is that you’re trying to do, test it and make sure it works how a user should expect it to.
Like this:
Like Loading...