I recently ran across a post by my colleague Chad Stewart, Lead Dev Support Engineer at BioWare Austin: Try/catch control flow
First of all, you ought to know that exceptions are deliberately named. That is to say, they are reserved for exceptional cases.
this.SomeRiskyOperation(someParam, someLocal, -1);
This is sad because it is a big fallacy. Exceptions as a concept have been around since well before modern programming languages, and they are for not at all exceptional cases in those modern languages (.NET and java are one implementation type, python would be another many are familiar with). An ‘exception’ merely states that the invoked code could not execute normally. It has nothing to do with being exceptional, or infrequent, or anything like that- it just indicates that code could not execute normally and cannot return a meaningful result.
If you think about something like a divide-by-zero exception- this is an issue of ambiguity. What would you get if you divided a number by 0? No one can say. So what would you get if you tried to Frob and Sprocket but the Sprocket was null and there’s nothing to Frob? Well, no one can say either- which is why null should be an invalid argument to Frob and Frob should throw an exception. Likewise if the Frob method can only work on Sprockets that have been Blurmed. If the Sprocket hasn’t been Blurmed, what’s Frob to do (unless its behavior in the case of a null or non-Blurmed Sprocket is clear)?
Similarly in the ‘not exceptional’ vein, python programmers have the ‘easier to ask for forgiveness than permission’ principle. Rather than pre-validate everything, they try/except their way forward. That is clearly a form of program flow, it is if/else by another name.
It’s sad that people don’t understand exceptions. A large part of that is because exceptions are still thought of as exceptional. Exceptions are not exceptional. Not in modern managed languages they’re not, at least. You need to understand how they work, how they are used, what they are for. They are as important to program flow as any other language construct, they are just more complex. There are best practices and ways to write robust code, there are also bad practices and it is easy to write bad code. It is just more difficult to write good robust code when considering exceptions, because it is fundamentally more difficult (I’ll talk about exception handling and gotos in a future post, I promise).
Which is good, because most of the time, you don’t have to worry about exceptions (except if you use them like python programmers). Which is good, because most of the time there’s nothing you can do about the exception. Instead of worrying about exceptions, worry about writing good code, that is immutable, transactional, modular, testable, clear, explicit, etc. I guarantee if you write better code, your exception handling experience will be better. And exceptions reciprocate: code that enforces contract and behavior through exceptions will be more modular, testable, clear, and explicit.
So, back to Chad’s example code. The problem with that code had nothing to do with exceptions. Rewrite that code without exceptions and it doesn’t get any better. It may get faster, but the speed issue isn’t exceptions’ fault either- that is still just faulty code. You can write slow code without exceptions (and I’ll bet your code spends infinitely more time in blocking IO than it does in exception handling). The problem with that code is that it was shitty code. It was shitty because it wasn’t correct for its domain, which was inside of a tight loop. There’s honestly nothing so conceptually wrong with that code from the sample- if SomeRiskyOperation is free of side effects, and the containing method has a clear true/false contract. But I don’t have enough context to judge. I am just saying that that code which looks horrible may very well be fine. It is just an example of the exception bogeyman, that uncomfortable programmers use to terrorize younger programmers that will listen, and it is a huge lie.
This isn’t the last you’ll hear from me about exceptions.