A few reasons not to use Exceptions
In real life, exceptions prove the rule. In programming, exceptions disprove
the rule. But anyways, this page is not about the kind of exceptions that we
make from rules, but the ones that we (should not) throw across the stack.
- An oft-heard claim is that it's easy to forget to check for error return
codes. But it's easy to forget to catch exceptions and clean up the stack
properly, as well!
- In C++, that's allegedly your fault - you should use RAII so the stack gets
cleaned up automatically. Well, except that makes your program totally
unreadable because execution threads are flying all over the code base - in the
best OOP manner. In destructors you typically don't have enough context to clean
up nicely. If you do, that might mean objects are too isolated to be doing
anything useful in an acceptable amount of code.
- So back to forgetting to check error codes. Yes, it's easy to forget, at
least if you're writing quick dirty things. For these I value Python's
exceptions as well, simply because I know the program will bail out on the first
error, which is what you expect from small dirty programs. In longer programs
it's better not to hide complexity. If introducing complexity is inconvenient
even on a syntactical level, you are constantly reminded to improve your
architecture, to reduce the complexity. Having to check many return codes is a
code smell. You should try keeping your state in a more global place (resource
managers) and remembering at least the last error there. Example: OpenGL
- The creator of a function that throws exceptions is in the business of
second-guessing what's an actual error for the caller. This is typically
not possible due to missing context. While functions designed for return codes
often make these classifications too (for example, by returning negative numbers
for errors), it's much easier for the caller to override this decision when the
set of possible outcomes is not arbitrarily partitioned in two by differing
syntax and semantics, as is the case with exceptions. A good example would be
Python's list.index() function which returns the index of a
searched-for item in a list, or throws an exception if the item was not found.
There are so many situations where a missing item is totally possible and
expected as an outcome, and getting a return code of -1 would be much
nicer to deal with than an exception.
- Exceptions are yet another way to indicate/handle errors, which means two
handling code paths are needed in many places. A good programmer knows to strive
for conformity whenever possible - exceptions are out.
- The context out of which errors arise is typically not known at the
high-level places where exceptions are catched. There is no proper way to deal
with exceptions in these places, besides ignoring them or letting the program
quit. Yes, it's nice that exceptions give you stack traces, but those are not
exclusive to exceptions, and often don't provide sufficient context even for
humans to debug the problem.