Having worked with exceptions in Java and .NET AND after reading a lot of articles about how/when/why catching exceptions, I finally came up with the following steps that I go through in my head whenever I see a potential exception happening, or an exception I must catch (Java)... even if it never happens (sigh...). And it seem to be working, at least for me:
- Is there anything useful I can do with that exception, (except logging) ? If the answer is yes, write the workaround code, and if the workaround may throw exceptions, go to 2:
- Wrap the exception around a runtime exception, throw it, go to 3.
- In the higher-level class where a possible database/process transaction has been initiated, catch the exception, rollback the transaction, rethrow the exception.
- At the top-level class (which may be the one where the transaction has been initiated), log the exception using a logging framework such as slf4j (coupled with log4j for example), or log4net. If possible, directly email the exception to a distribution list that is composed of developers of the application.
- If there is a GUI, display an error message indicating in the most user-friendly way what caused the problem; do not display the exception/stacktrace, the user doesn't care and doesn't need to know it was a NullPointerException.
I should also add the step 0, where I am purposely throwing what I call a "business" exception (a new exception that I create by extending the "Exception" class) when some complex treatment cannot be executed because of data errors, BUT that are known to happen as they have been identified as exception cases during the analysis.
Except for the logging part, I fully agree with the points written by "mikera"; I will just add that the exception should be logged once only.
Also, the steps I listed may be different if what you are writing is an API/Framework. There, throwing well designed exceptions is mandatory to help developers understand their mistakes.
As for testing the exceptions, using mock objects you should be able to test nearly everything, be it exception-al or not, provided that your classes respect the "one class to do one thing" best practice. I also personally make sure to mark the most important but hidden methods as "protected" instead of "private" so that I can test them without too much hassle. Apart from that, testing exceptions is simple, just provoke the exception and "expect" an exception to occur by catching it. If you don't get an exception, then you have a unit test case error.