Error Handling
Use Exceptions Rather Than Return Codes
The problem with using return codes is that they clutter the caller. The caller must check for errors immediately after the call. Unfortunately, it’s easy to forget. For this reason it is better to throw an exception.
The code is better because two concerns that were tangled, the algorithm for device shutdown and error handling, are now separated.
Write Your Try-Catch-Finally Statement First
One of the most interesting things about exceptions is that they define a scope within your program. Your catch has to leave your program in a consistent state, no matter what happens in the try. For this reason it is good practice to start with a try-catch-finally statement when you are writing code that could throw exceptions. This helps you define what the user of that code should expect.
Use Unchecked Exceptions
With Unchecked Exceptions the signature of every method would list all of the exceptions that it could pass to its caller. These exceptions were part of the type of the method. Your code wouldn’t compile if the signature didn’t match what your code could do.
The price of checked exceptions is an Open/Closed Principle1 violation. If you throw a checked exception from a method in your code and the catch is three levels above, you must declare that exception in the signature of each method between you and the catch. This means that a change at a low level of the software can force signature changes on many higher levels.
In general application development the dependency costs outweigh the benefits.
Provide Context with Exceptions
Each exception that you throw should provide enough context to determine the source and location of an error by using informative error messages.
Define Exception Classes in Terms of a Caller’s Needs
Wrapping third-party APIs is a best practice. When you wrap a third-party API, you minimize you dependencies upon it. Wrapping also makes it easier to mock out third-party calls when you are testing your own code. One final advantage of wrapping is that you aren’t tied to a particular vendor’s API design choices.
Don’t Return Null
If you are tempted to return null from a method, consider throwing an exception or returning a SPECIAL CASE object instead. If you are calling a null-returning method from a third-party API, consider wrapping that method with a method that either throws an exception or returns a special case object. You will minimize the chance of NullPointerExceptions and your code will be cleaner.
Don’t Pass Null
You should avoid passing null in your code whenever possible. In most programming languages there is no good way to deal with a null that is passed by a caller accidentally. Because this is the case, the rational approach is to forbid passing null by default.
Conclusion
Clean code is readable, but it must also be robust. These are not conflicting goals. We can write robust clean code if we see error handling as a separate concern, something that is viewable independently of our main logic. To the degree that we are able to do that, we can reason about it independently, and we can make great strides in the maintainability of our code.