views:

110

answers:

4

I am working on a code-base with a bunch of developers who aren't primarily Computer Science or Software Engineering (Mostly Computer Engineering)

I am looking for a good article about when exceptions should be caught and when one should try to recover from them. I found an article a while ago that I thought explained things well, but google isn't helping me find it again.

We are developing in C++. Links to articles are an acceptable form of answer, as are summaries with pointers. I'm trying to teach here, so tutorial format would be good. As would something that was written to be accessible to non-software engineers. Thanks.

+4  A: 

Herb Sutter has an excellent article that may be useful to you. It does not answer your specific question (when/how to catch) but does give a general overview and guidelines for handling exceptional conditions.

I've copied his summary here verbatim

Distinguish between errors and nonerrors. A failure is an error if and only if it violates a function's ability to meet its callees' preconditions, to establish its own postconditions, or to reestablish an invariant it shares responsibility for maintaining. Everything else is not an error.

Ensure that errors always leave your program in a valid state; this is the basic guarantee. Beware of invariant-destroying errors (including, but not limited to, leaks), which are just plain bugs.

Prefer to additionally guarantee that either the final state is either the original state (if there was an error, the operation was rolled back) or intended target state (if there was no error, the operation was committed); this is the strong guarantee.

Prefer to additionally guarantee that the operation can never fail. Although this is not possible for most functions, it is required for functions such as destructors and deallocation functions.

Finally, prefer to use exceptions instead of error codes to report errors. Use error codes only when exceptions cannot be used (when you don't control all possible calling code and can't guarantee it will be written in C++ and compiled using the same compiler and compatible compile options), and for conditions that are not errors.

Sam Miller
As always I like Sutter's style and his advices are sound. However I am afraid that "prefer to use exceptions instead of error codes" might be misinterpreted. This isn't an apology of exceptions saying that every "mishap" should be reported as an exception, it means that if you have to choose between returning an error code or throwing an exception, you should throw. I am not so sure about that myself.
Matthieu M.
Error codes have their place (don't replace everything with an exception because you can (just where it is appropriate)). For example: Within a class it is OK to use error codes between private methods as long as the error code is never exposed to the user of the class.
Martin York
A: 

Read the chapter "Exception Handling" from the Book

Thinking in C++, Volume 2  - Bruce Eckel

Dani Cricco
A: 

May be this MSDN section will help you...

SKINDER
A: 

The most simplistic advice:

If you don't know whether or not catching an exception, don't catch it and let it flow, someone will at one point.

The point about exceptions is that they are exceptional (think std::bad_alloc). Apart from some weird uses for "quick exit" of deeply nested code blocks (that I don't like much), exceptions should be used only when you happen to remark something that you have no idea how to deal with.

Let's pick examples:

file = open('littlefile.txt', open.mode.Read)

It does seem obvious, to me, that this may fail, and in a number of conditions. While reporting the cause of failure is important (for accurate diagnostic), I find that throwing an exception here is NOT good practice.

In C++ I would write such a function as:

boost::variant<FileHandle,Error> open(std::string const& name, mode_t mode);

The function may either return a file handle (great) or an error (oups). But since it's expected, better deal with it now. Also it has the great advantage of being explicit, looking at the signature means that you know what to expect (not talking about exception specifications, it's a broken feature).

In general I tend to think of these functions as find functions. When you search for something, it is expected that the search may fail, there is nothing exceptional here.

Think about the general case of an associative container:

template <typename Key, typename Value>
boost::optional<Value const&> Associative::GetItem(Key const& key) const;

Once again, thanks to Boost, I make it clear that my method may (or not) return the expected value. There is no need for a ElementNotFound exception to be thrown.

For yet another example: user input validation is expected to fail. In general, inputs are expected to be hostile / ill formed / wrong. No need for exceptions here.

On the other hand, suppose my software deal with a database and cannot possibly run without it. If the database abstraction layer loses the connection to the database and cannot establish a new one, then it makes sense to raise an exception.

I reserve exceptions for technical issues (lost connection, out of memory, etc...).

Matthieu M.