A lot of developers don’t see what’s so bad about using exceptions to control program flow.
I have weighed in on this question, and my general opinion is that the main problem—from a practical standpoint—is one of performance. Yes, it’s an implementation detail and varies by programming language/framework; but I would wager that 9 times out of 10, writing code that is not unlikely to throw an exception (what Eric Lippert calls a “boneheaded exception”) and catching that exception is less efficient than dealing with the problem beforehand—nipping it in the bud, if you will—sans exception.
But this blog is titled “The Philosopher Developer,” after all; so now I’m going to offer my philosophical explanation. And, as has become customary for my blog posts, I will do so in the form of an analogy.
- You: the developer
- Servant: the computer, running your software
- Your Instructions: your software (obviously)
- The Store: the operating environment
You have a servant whom you use to accomplish various small tasks for you—running errands, performing simple work around the house, etc. (Sounds nice, doesn’t it?)
One day you decide you want something cold to drink, but there’s nothing in your fridge. So you give your servant some cash and send him to the grocery store with these instructions: “Buy me a Coke.”
Now, let’s say your servant is extremely literal and incapable of making his own decisions. He can only follow instructions. You realize this, and so in your mind you think: If the store doesn’t have any Coke, maybe I’d be fine with a Pepsi instead. As a last resort, I could even go for some orange juice. (This is of course supposing you know for a fact that the store will always have orange juice.) Your plan is, if your servant can’t find a Coke, he will have a panic attack and come back to you very distressed. Then you will let him know your alternate choice.
This is what it’s like to throw and catch exceptions: you’re accounting for disastrous scenarios without letting your servant “in” on the details of your backup plan. Consider the energy your servant has wasted going to the store, trying to execute your instructions, failing, and then coming back to you to report on his failure, when all along you knew exactly what you wanted to do if he were unsuccessful. You have anticipated the disaster and deliberately allowed it to happen as a means of controlling your servant’s workflow.
The alternative, obviously, would have been to let your servant know of your 2nd and 3rd choices in advance. This would have allowed him to make only one trip to the grocery store, where he could have looked for Coke, Pepsi, and orange juice—in that order—without any panic attacks or distress, and most importantly without needing to return to you empty-handed. The disaster (the exception) thus could have been prevented altogether.
When you think of it this way, it really is just the sensible thing to do all-around to try and avoid exceptions when it’s possible to do so.