Joel recently linked to a new critique of exceptions by Raymond Chen, closely mirroring Joel’s own old one. I’d like to suggest that the problems they describe are attributable to abuse of exceptions, not to exceptions themselves. Yes, some constructs are more subject to abuse than others, or even encourage it. My favorite example of this is the observation that many problems with Microsoft Windows are actually problems with Windows drivers, but the early Windows architectures forced programmers to do things in the kernel that should be done in user space, leading to many people writing kernel code who simply didn’t have the skills to do it properly. Therefore, Microsoft might not have been directly responsible for the problems but did share some culpability because of their awful OS-design decisions. So it might be with exceptions, but I don’t think so. I think most of the problems Joel and Raymond describe go away if people follow some simple rules:

  • Every exception must represent a unique state, either by using unique exceptions or by associating unique information with an exception when it is thrown (as with Python exceptions).
  • Code should only catch exceptions that lead to known and unambiguous states
  • Information about exceptions should be part of a module’s contract. If a module’s upper contract with its caller says that it will only throw certain exceptions representing certain states, it’s responsible for ensuring that other exceptions from modules it calls don’t “leak” through to its caller.

If that last rule means that exceptions from lower modules have to be converted into other exceptions, or into error return values, so be it. Exceptions and other phenomena occurring in those lower modules should not be allowed to change the effective interface to the upper module. If you have to deal with a module that’s profligate with its exceptions and can’t be fixed (e.g. because it came from a third party and it’s too late to find an alternative), that might even mean you have to use a catch-all exception handler, even though those are generally evil. The sad fact is that such a module is going to be a problem no matter how you slice it, so you might as well try to contain the problem.