There is a subtle difference between what Robert C. Martin recommends in Clean Code and what Andrew Hunt / David Thomas recommend in The Pragmatic Programmer. Martin encourages you to always use exceptions if the normal program flow is interrupted to avoid if statements (or even worse: forgotten if statements and mixed result types) while Hunt/Thomas say this can cause harm (“it’s a kind of cascading goto”) and should only be used if something truly unexpected happens (tip 34). From my point of view, Robert C. Martin is right (his approach works for me; my code does not look like goto was used) and The Pragmatic Programmer is outdated in this regard. Interestingly enough, I’ve never noticed anyone debating about these differences although both books are pretty popular.
1) Robert C. Martin: Prefer Exceptions to Returning Error Codes
Returning error codes from command functions is a subtle violation of command query separation. It promotes commands being used as expressions in the predicates of if statements: if (deletePage(page) == E_OK)
This does not suffer from verb/adjective confusion but does lead to deeply nested structures. When you return an error code, you create the problem that the caller must deal with the error immediately.
The problem with [if statements] is that they clutter the caller. The caller must check for errors immediately after the call. Unfortunately, it’s easy to forget. For this reason it is better to throw an exception when you encounter an error. The calling code is cleaner. Its logic is not obscured by error handling.
2) Andrew Hunt: Exceptions, like any other technique, can cause more harm than good if not used properly.
We believe that exceptions should rarely be used as part of a program’s normal flow; exceptions should be reserved for unexpected events. Assume that an uncaught exception will terminate your program and ask yourself, “Will this code still run if I remove all the exception handlers?” If the answer is “no,” then maybe exceptions are being used in nonexceptional circumstances.
Why do we suggest this approach to exceptions? Well, an exception represents an immediate, nonlocal transfer of control—it’s a kind of cascading goto. Programs that use exceptions as part of their normal processing suffer from all the readability and maintainability problems of classic spaghetti code. These programs break encapsulation: routines and their callers are more tightly coupled via exception handling.