Had a code review today and I realized that I am an exception extremist, an exception bigot if you will.
I don’t like exceptions. I’d rather throw up than throw an exception.
I have a rule, if you can detect the situation it’s not an exception and there are no exceptions to that rule. (Okay, there is one exception I blogged about earlier, but it makes the code so much cleaner.)
Why I don’t like exceptions
Most of the time the way you find out an API throws one (at least in C#), is when your code runs in production.
Of course I also hate when I am forced to handle and exception in Java using checked exceptions.
One of the things I really don’t like about exceptions is that they break up the flow of the code. Exceptions are essentially goto statements. You can’t always know exactly where code flow will go.
I also really don’t like that when I handle an exception I have to declare my variable above the try catch block so that I can use it after the block. I understand why I do, but I just don’t like it. It makes me grumpy because now I have to try to initialize that variable to some default value that makes sense.
Exceptions also lead us to bad code that gets written like:
I don’t think I need to explain the above code more than it is already.
Exceptions also send off false alarms. I mean really, is it such a big deal that I passed you a string that has a dollar sign in it? Can you not figure out that if I pass you “$3.00” and ask you to parse it as an integer that I want 3? Give me a break. When I see exceptions I think, “something really bad has happened that is likely to cause the very universe to become unmade.” I don’t think “perhaps I left the dollar sign in my string.”
And the number one reason why I don’t like exceptions: “My inbox is full of them.” Every place I work, it is the same. Emailed uncaught exceptions. Clearly throwing exceptions is not working too well. Yeah, I know the system is throwing null pointer exceptions, and you can’t do much about that. (Except maybe, hmm I donno let's ignore method calls on null objects…)
What to do instead?
Well, there are a few lines of defense we can throw in before waving the exception flag:
- See if you can actually do something smart with the data. For example, if you are writing code to parse a string into a number, can you ignore non-numeric characters? Sometimes the answer is no, but many times you can figure out a way to work with what you got. If you can find a way to proceed forward without throwing an exception, do it.
- If you're returning back some data, return back some default or empty value. (Not null though.) This doesn’t always make sense, but it can be nicer than throwing an exception.
- Give the caller a way to check for success first. Returning a result code from your method is probably bad. But, if you let me call something first to validate my input, at least I can handle the problem there. Consider the tryParse methods in the .NET framework. They let you check to see if something will parse instead of throwing an exception if it won’t.
- If the exception didn’t originate from your code, try and handle it in your code first. Is there a way you can deal with the exception, instead of just rethrowing it or wrapping it?
- If you are not exposing an external API, try to use some sort of error collection, or error property you can check on your class to indicate a failure occurred.
If you must, (and sometimes you must)
- Don’t rethrow a system exception. The exception should match your level of abstraction. Wrap the exception (keeping the call stack intact) and then throw it.
- Don’t throw 50 million different kinds of exceptions. No one likes to catch all your many exceptions. You can always include details in the exception to say what specifically happened incorrectly.
A coworker of mine had a really good point. He said that it depends on your perspective. You might have to think as if you were someone using your API.
What is the most obvious thing to do? Would you expect a call to silently fail or to throw an exception?
It is worth thinking about from the user of your code’s perspective.
It’s pretty fair to say that I am still pretty undecided on this topic. I really don’t like exceptions, but I also don’t like calling a method in an API and then calling another method to check for error conditions. And I certainly don’t like error codes or booleans returned from methods to indicate failure or success.
What do you think?