Failing Fast With Guava’s Preconditions

One of the many Good Programmer’s mantras is to always have your input data checked against invalid values. So we decorate our public interfaces with assertions or intricate if-then-else constructs checking all possible combinations of the input data, throwing around Exceptions and assembling meaningful error messages. … Or we skip erecting this line of defense altogether when the next release date comes frighteningly close.

To fail fast and early during program execution is a good thing so as we get notice about a bug as close to the place where it originated as possible. A bug that only materializes late in some remote corner of my code base which is totally unrelated to the bug’s original place of birth is a lot harder to track down and eliminate than a bug that directly calls attention to itself with a noisy Exception directly when it first appeared.

So we should continue (or begin?) adding sanity checks for input parameters to our public methods. Yet oftentimes these tend to grow and clutter our ‘real’ code, and sometimes these checks even consume more lines-of-code space than the actual productive code they are protecting from harm. Such constructs make it easy to detect errors early on. But they make it even harder to undistractedly read through a piece of code.

Here is where Google’s general utility library Guava (formerly known as Google Collections) enters the scene. Besides bringing a whole bunch of utility goodness to the public, it also offers one particulary useful class to the interested programmer helping her alleviate the above mentioned problems with sanity checks:

com.google.common.base.Preconditions

This class provides a collection of static utility functions which you can use to write your parameter checks in a very concise way. They remove all the clutter as all conditional logic and Exception throwing is neatly tucked away in their method bodies.

For example, the following code

if (divisor == 0) {
    throw new IllegalArgumentException("Divisor must not be zero!");
}

can be compacted with Preconditions as below

import static com.google.common.base.Preconditions.*;
...
checkArgument(divisor != 0, "Divisor must not be zero!");

Writing sanity checks with Preconditions thus becomes very similar to writing JUnit assertions. Note that similar to JUnit’s assertTrue() method, with these check*()-functions you declare what you are expecting to be true, while the original if-condition will check for the negative of this expectation.

Null checks with Preconditions can even be used for invocation chaining as each null check function returns the instance of the checked object if it is non-null. So instead of writing

if (text == null) {
    throw new NullPointerException("The given String is null.");
}
if (text.length() > 20) {
    throw new IllegalArgumentException("The given text is too long: " + text);
}

you can write the following

checkArgument(checkNotNull(text).length() <= 20, "The given text is too long: %s", text); [/sourcecode] which has the same effect. For the most common types of Exceptions which are generally used for sanity checks, class Preconditions provides a function throwing that particular Exception when the predefined condition is not met. So, checkArgument() throws IllegalArgumentException, checkState() throws IllegalStateExceptions, checkNotNull() throws NullPointerExceptions, and checkElementIndex() and checkPositionIndex() throw IndexOutOfBoundsExceptions. So as a conclusion, using the checks offered by Guava's Preconditions class will help you keep your sanity checks as compact as possible and makes writing them a breeze.

To assert or not to assert

Then there are the well-known assert statements introduced by Java 1.4. They share the same properties as Guava’s Preconditions in that they make for a more compact code without too much clutter. So why not use them all over the place?

Assertions have been added to the Java language to provide a means to check particular internal preconditions that have to be fulfilled in a system. By that, they are very similar to the above mentioned sanity checks, yet they serve a slightly different purpose. Assertions are meant to support the software development process until to the point a piece of software is finished and can go into production. Assertions are usually inactive by default and have to be explicitly enabled during development time with Java’s -ea command line switch. Given that, using assertions for checking input parameter values of public interfaces is a bad idea. When not explicitly switched on, users of a library will not be informed of having used invalid parameter values when the underlying sanity checks are implemented using assertions. This will effectively render all your checks useless for the users of your code when they forget to enable Java’s assertion feature.

So, when should we use assertions and when should we write sanity checks with Preconditions? There is a general rule of thumb that can be applied for answering this question. Java’s assert keyword should only be used in places where there is no ‘user data’ to be checked. User data in this respect means data that is fed in by users of your public interfaces. As soon as you have to handle data that is passed in by callers of your public or protected methods, you should not use assert. If on the other hand you are working with purely private data (such as internal counters or index pointers) you should use assertions.

To boil it down, assert is for private purpose only. Exceptions may be made if you have public and protected interfaces that are unlikely to be used by external users, such as classes providing internal implementations. But note that even your team members working on the same code base as you count as external users in this context. They too want to be informed about an incorrect usage of your interfaces without having to remember enabling the assertion feature.

Short URL for this post: http://wp.me/p4nxik-Uz
Roland Krüger

About Roland Krüger

Software Engineer at Orientation in Objects GmbH. Find me on Google+, follow me on Twitter.
This entry was posted in Java and Quality, Java Basics and tagged , , , . Bookmark the permalink.

One Response to Failing Fast With Guava’s Preconditions

  1. Assertions are better overall actually because it can be disabled. Those precondition checks should really be done while you are developing to make sure your internal calls are stable. You should have checks in the user input to prevent invalid input from getting into the lower levels of the system.

Leave a Reply