views:

1107

answers:

12

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?

+2  A: 

Exceptions are expensive in processing time, so they should only be thrown when something happens that really shouldn't happen in your app.

Sometimes you can predict what kind of things might happen and code to recover from them, in which case it is appropriate to throw and catch an exception, log and recover, then continue. Otherwise they should just be used to handle the unexpected and exit gracefully, while capturing as much information as possible to help with debugging.

I'm a .NET developer, and for catch and throw, my approach is:

  1. Only try/catch in public methods (in general; obviously if you are trapping for a specific error you would check for it there)
  2. Only log in the UI layer right before suppressing the error and redirecting to an error page/form.
Guy Starbuck
How are the exceptions more expensive than a normal return from a method?
Daniel
Well, I'm going with .NET again, but when an exception is thrown there is a lot of processing that happens (unwinding the call stack, putting together the exception object) that doesn't happen in a normal return.
Guy Starbuck
Except in the most deeply performance-oriented situations, though, performance is NOT a good way to choose one way of handling errors or the other. If you're already in managed code, it's unlikely to be a showstopping issue.
Dustman
A: 

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.

Rob Wells
I mean using exceptions - creating, throwing and handling. A programmer can create his own exceptions in most languages. They are not all predefined.
Daniel
A: 

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.

Charlie
+13  A: 
Martin York
Good stuff. A little more abstract and formal than I'd like if I asked the question, but it got my vote.
Dustman
@Martin York: +1 good content; i'd go +2 if you included 'please do not catch any exceptions, please'.
sixlettervariables
You could make it more clear what those guarantees are.
iny
@iny: What do you mean? There is nothing explicit in the language that defines guarantees. This is all about how you write/document your code.
Martin York
A: 

hi there,

this article from bea(now oracle) is a good exposition on how to go about it : http://www.oracle.com/technology/pub/articles/dev2arch/2006/11/effective-exceptions.html. It kinda assumes Java but you should be able to use it for other environments as well.

anjanb
+3  A: 

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.

Dustman
+1  A: 

The context this answer is given in is the Java language.

For normal errors that may pop up, we handle those directly (such as returning immediately if something is null, empty, etc). We only use an actual exception for exceptional situations.

However, we do not throw checked exceptions, ever. We subclass RuntimeException for our own specific exceptions, catching them where applicable directly, and as for exceptions that are thrown by other libraries, the JDK API, etc, we do try/catch internally and either log the exception (if something happened that really shouldn't have and you have no way of recovering like a file not found exception for a batch job) or we wrap the exception in a RuntimeException and then throw it. On the outside of the code, we rely on an exception handler to eventually catch that RuntimeException, be that the JVM or the web container.

The reason this is done is that it avoids creating forced try/catch blocks everywhere where you might have four instances of calling a method but only one can actually handle the exception. This seems to be the rule, not the (no pun intended...ouch) exception, so if that fourth one can handle it, it can still catch it and examine the root cause of the exception to get the actual exception that occurred (without worrying about the RuntimeException wrapper).

MetroidFan2002
Agree with you MetroidFan2002. This reminds me article by Gunjan Doshi "Best Practices for Exception Handling" dated back 2003. http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html
Yurii Soldak
A: 

As a C++ developer, my own policy is not to throw exceptions from what I consider to be public apis to my classes/modules (in fact, a requirement with COM). However, I use exceptions extensively in private class implementation. For example, working with ATL:

HRESULT Foo()
{
    HRESULT hr = S_OK;
    try {
        // Avoid a whole lot of nested ifs and return code
        // checking - internal stuff just throws.
        DoStuff();
        DoMoreStuff(); // etc.
    } catch ( CAtlException& e ) {
        hr = e;
    }
    return hr;
}

void DoSomething()
{
    // If something goes wrong, AtlThrow( E_FAILED or E_WHATEVER ); 
}
Harold Ekstrom
+2  A: 
  1. Never throw exceptions from destructors.

  2. Maintain some basic level of exception guarantees about the state of the object.

  3. 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.

  4. Do not throw exceptions if you can help it. It slows everything down.

  5. Do not just catch(...) and do nothing. Catch exceptions you know about or specific exceptions. At the very least log what happened.

  6. When in the exception world use RAII coz nothing is safe anymore.

  7. Shipping code should not have suppressed exceptions at least wrt memory.

  8. When throwing exceptions package as much information as is possible along with it so that the upper layers have enough information to debug them.

  9. Know about flags that can cause libraries like STL to throw exceptions instead of exhibiting unknown behaviour.(eg invalid iterators / vector subscript overflow)

  10. Catch references instead of copies of the exception object?

  11. Take special care about reference counted objects like COM and warp them in reference counted pointers when working with code that could throw exceptions.

  12. If a code throws an exception more than 2% of the time consider making it an error code for performance sake.

  13. Consider not throwing exceptions from undecorated dll exports / C interfaces because some compilers optimize by assuming C code to not throw exceptions

  14. IF all that you do for handling exception is something akin to below then dont use exception handling at all. You do not require it.

main { try { all code.... } catch(...) {} }

+1  A: 

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

  • Creating or connecting to any kind of connection (remote, local).
    • Occurs in: Databases, Remoting
    • Reasons: Non-existent, Already in Use or Unavailable, Insufficient/Invalid Credentials
  • Opening, Reading or Writing to any kind of resource
    • Occurs in: File I/O, Database
    • Reasons: Locked, Unavailable, Insufficient/Invalid credentials

Integrity of Data

  • There could be many cases where the integrity of the data matters
    • What it references, what it contains...
    • Look for resources on the methods or code that requires a set of criteria for the data to be clean and in a valid format.
    • Example: Trying to parse a string with the value 'bleh' to a number.

Validity of Data

  • Is this the correct data provided? (It's in the right format, but it might not be the correct set of parameters for a given situation)
    • Occurs in: Database Queries, Transactions, Web Services
    • Example: Submitting a row to a database and violating a constraint

Obviously there are other cases, but these are usually the ones I try to abide by where its needed.

nyxtom
+1  A: 

I believe that the best way to use exceptions depends on which computer language you are using. For instance Java has a much more solid implementation of exceptions than C++.

If you are using C++, I recommend that you at least try to read what Bjarne Stroustrup (the inventor of C++) has to say about exception safety. Refer to appendix E of his book "The C++ programming language".

He spends 34 pages trying to explain how to work with exceptions in a safe way. If you do understand his advice then that should be all that you need to know.

A: 

My policy on exception handling can be found at:

http://henko.net/imperfection/exception-handling-policy-throwing-exception/.

(Hope it's not against the rules to promote a web site, but it is a bit too much information to paste here.)

henko