There is a lot of relativity involved in working with exceptions. Beyond low level APIs where exceptions cover errors raised from hardware and the OS there is a shady area where the programmer decides what constitutes an exception and what is a normal condition.
How do you decide when to use exceptions? Do you have a consistent policy regarding exceptions?
I think there's usually a good way to determine exceptions based on access to resources, integrity of data and the validity of data.
Access Exceptions
Integrity of Data
Validity of Data
Obviously there are other cases, but these are usually the ones I try to abide by where its needed.
This blog entry from Eric Lippert, a Senior Software Design Engineer at Microsoft, sums up an excellent and brief set of exception strategy guidelines.
In short:
Fatal: Terrible errors that indicate your process is totally unrecoverable. Clean up whatever resources you can, but don't catch them. If you're writing code that has the ability to detect such a situation, by all means, throw. Example : Out of memory exception.
Boneheaded: Relatively simple errors that indicate your process can't operate on whatever data it's being handed, but would continue on normally if whatever situation caused the error is simply ignored. These are better known as bugs. Don't throw or catch them, but instead prevent them from happening, usually by passing errors or other meaningful indicators of failure that can be handled by your methods. Example: Null argument exception.
Vexing: Relatively simple errors that code you don't own is throwing at you. You must catch all of these and deal with them, usually in the same way as you would deal with a Boneheaded exception of your own. Please don't throw them right back out again. Example: Format exception from C#'s Int32.Parse() method
Exogenous: Relatively straightforward errors that look a lot like Vexing (from other people's code) or even Boneheaded (from your code) situations, but must be thrown because reality dictates that the code that's throwing them really has no idea how to recover, but the caller probably will. Go ahead and throw these, but when your code receives them from elsewhere, catch them and deal with them. Example: File not found exception.
Of the four, the exogenous ones are the ones that you have to think about most to get right. An exception indicating a file is not found is appropriate to throw for an IO library method, in that the method almost certainly will not know what to do should the file not be found, especially given that the situation can occur at any time and that there is no way to detect whether or not the situation is transient. Throwing such an exception would not be appropriate for application-level code, though, because that application can get information from the user on how to proceed.
Others may have to correct/clarify this, but there's a strategy called (I believe) "contract-driven development", where you explicitly document in your public interface what the expected preconditions are for each method, and the guaranteed post-conditions. Then, when implementing the method, any error which prevents you from meeting the post-conditions in the contract should result in a thrown exception. Failure to meet preconditions is considered a program error and should cause the program to abort.
I'm not sure if contract-driven development speaks to the question of catching exceptions, but in general you should only catch exceptions that you expect and can reasonably recover from. For instance, most code cannot meaningfully recover from an Out Of Memory exception, so there is no point in catching it. On the other hand, if you are trying to open a file for writing, you can (and should) handle the case that the file is exclusively locked by another process, or the case that the file has been deleted (even if you checked its existence before trying to open it).
As noted by another commenter, you should also avoid using exceptions to handle expected conditions that can be expected and avoided. For instance, in the .NET framework, int.TryParse is preferable to int.Parse with a try/catch, especially when used in a loop or such.
Exceptions should not be used as a method of passing information internally between methods inside your object, locally you should use error codes and defensive programming.
Exceptions are designed to pass control from a point where an error is detected to a place (higher up the stack) where the error can be handled, presumably because the local code does not have enough context to correct the problem and something higher up the stack will have more context and thus be able to better organize a recovery.
When considering exceptions (in C++ at least) you should consider the exception guarantees that your API makes. The minimum level of guarantee should be the Basic guarantee though you should strive (where appropriate) to provide the strong guarantee. In cases where you use no external dependencies from a articular API you may even try to provide the no throw guarantee.
N.B.Do not confuse exception guarantees with exception specifications.
Exception Guarantees:
No Guarantee:
Basic Guarantee:
Strong Guarantee: (aka Transactional Guarantee)
No Throw Guarantee:
Aren't exceptions raised by the language environment in accordance with the spec. of the language being used if indeed it does have the concept of exceptions? I'm thinking of "divide by zero" in Java, or CONSTRAINT_ERROR in Ada vs. nothing at all in C.
How can a programmer "decide" to use exceptions after selecting a programming language that has exceptions defined within its makeup?
Edit: Or rather than "using" exceptions, do you mean when to have a cohesive and consistent policy about "handling" exceptions?
Edit2: You might like to check out the free chapter from Steven Dewhurst's book "C++ Gotchas", specifically Gotcha 64 and Gotcha 65. Though it is focused on C++, the lessons involved are useful in other languages.
Never throw exceptions from destructors.
Maintain some basic level of exception guarantees about the state of the object.
Do not use exceptions to communicate errors which can be done using an error code unless it is a truly exception error and you might want the upper layers to know about it.
Do not throw exceptions if you can help it. It slows everything down.
Do not just
catch(...)
and do nothing. Catch exceptions you know about or specific exceptions. At the very least log what happened.When in the exception world use RAII because nothing is safe anymore.
Shipping code should not have suppressed exceptions at least with regards to memory.
When throwing exceptions package as much information as is possible along with it so that the upper layers have enough information to debug them.
Know about flags that can cause libraries like STL to throw exceptions instead of exhibiting unknown behaviour (e.g. invalid iterators / vector subscript overflow).
Catch references instead of copies of the exception object?
Take special care about reference counted objects like COM and warp them in reference counted pointers when working with code that could throw exceptions.
If a code throws an exception more than 2% of the time consider making it an error code for performance's sake.
Consider not throwing exceptions from undecorated dll exports / C interfaces because some compilers optimize by assuming C code to not throw exceptions.
If all that you do for handling exceptions is something akin to below, then don't use exception handling at all. You do not need it.