The appropriate use of exceptions is a topic that I have discussed numerous times in the last several months at my office. Some developers love to use exceptions for every single scenario; while other developers seem to shun exceptions like the plague.
I have learned some things that may make it clear when it does and doesn't make sense to throw exceptions. For the sake of this discussion I am talking about .NET, but the general concepts are applicable to Java and should be usable in other languages too.
Benefits of exceptions
Exceptions have a number of benefits. For one thing, exceptions are objects unto themselves, and all exceptions inherit from a common ancestor: the Exception class. This is helpful because it means that you can easily define your own exceptions and test the type of the exception through the usual class detection techniques. When you make your own exception, it is easy to add in any additional functionality or properties that you might need.
Another very useful aspect of this is that you can have a separate Catch block for different types of exceptions. A very common error handling pattern is to catch the handful of exceptions that you can regularly expect in a scenario, handle them as appropriate (maybe prompting the user for additional information or sending an email to the system administrator), and then have a "catch all" handler for the Exception class itself for the rest of the potential errors.
Another scenario that I have dealt with a few times is where some caught exceptions have detailed information in them, but there is a global exception handler that only uses the basic error text; in those cases, I catch the detailed exception and generate a new exception (or a sub-classed exception) with the needed information in the place that the generic handler expects it to be.
Alternatives to exceptions
Exceptions sound great, right? Well, in many cases they are. But exceptions come with some baggage.
The Try/Catch block imposes some performance penalties; if you need to use Try/Catch within the confines of a tight loop, it can represent a significant portion of your resource usage. Exceptions are also not useful when the call you made had an error but was able to do some work anyway; in those scenarios, you need to perform the work and report an error.
Three alternatives to exceptions include the following:
- TryXYZ: The TryXYZ pattern (such as "TryGet," "TryParse," or "TryExecute") takes a method that has a return value and uses an out parameter instead of the return value. The new return value is a Boolean value that lets the caller know if the process was successful. Instead of using Try/Catch, the caller checks the return value. This pattern will execute faster than Try/Catch, but it lacks the granularity of errors that exceptions provide, as well as the ability to provide detailed error messages or a stack trace.
- Return NULL on error: Sometimes you may find it useful to simply return a NULL value if there is an error. Like TryXYZ, this is fast, but it provides no information in the case of a failure. Unlike TryXYZ, there is no way for the caller to differentiate between an actual failure and a legitimately NULL return result. Another problem with this tactic is that it depends on the consuming programmer to read the documentation carefully (good luck with that) and perform a null check on the return result. TryXYZ makes it very clear that the return result indicates success or failure, but returning NULL does not.
- Return a result code: This is similar to the TryXYZ pattern, but instead of returning a simple Boolean, you return a value (usually an integer) that indicates a level of success or failure and can be compared to documentation for an explanation. This alternative has fallen out of use, but in many regards it is preferable to TryXYZ because it allows more granularity in the error reporting, and it also allows success to have multiple meanings. Like the other alternatives to exceptions, it is faster to execute.
There are other alternatives to exceptions out there, but these are the ones you find in common usage. For example, TechRepublic contributor Chris Eargle recently posted an article on his blog comparing TryParse to Convert in the context of numeric parsing. I think that TryXYZ and using a result code (perhaps combining the two to have TryXYZ producing a result code) is far superior to returning NULL.
Please let me know in the forums about your error handling preferences.
J.JaDisclosure of Justin's industry affiliations: Justin James has a contract with Spiceworks to write product buying guides; he has a contract with OpenAmplify, which is owned by Hapax, to write a series of blogs, tutorials, and articles; and he has a contract with OutSystems to write articles, sample code, etc.
———————————————————————————————————————————-Get weekly development tips in your inbox Keep your developer skills sharp by signing up for TechRepublic's free Web Developer newsletter, delivered each Tuesday. Automatically subscribe today!
Justin James is the Lead Architect for Conigent.