when( true ).throwIllegalArgument( "something went wrong" );

July 1, 2013 | 4 min Read

As a framework developer I have to make sure that my framework works properly - and among other things, that means it has to be used in the way that I meant it to be used. One option to achieve this is to validate the input. With input I basically mean method parameters. For example, a parameter is not allowed to be null or a list must not be empty and so on. When trying to follow this rule, you end up with code that looks like this:

if( parameter == null ) {
  throw new IllegalArgumentException( "parameter must not be null." );
}

As you can imagine, this gets really messy when you write this over and over. Luckily we all know the DRY principle and that leads us to putting the validation code into a utility class. But wait a minute. There must be a solution for a pattern that is so common, right? Right! As you may know from previous posts, I’m a big fan of Google Guava. Guava provides a nice little helper class called Preconditions. The methods of this class are used only for validation and I was really convinced that this was the way to go. The important part of the last sentence is “was”. During the last month I started to have some doubts. The first one is pretty minor but still valid. The name of this class is Preconditions. But I found myself often using the methods after I have written some functionality, so I was really using them as “PostConditions”. Alright, this is minor because you can use static imports and the “Preconditions” wording does not uglify your code. The second problem with Preconditions is the use of negative logic.

Let me explain this with an example. The Preconditions class has a method called checkArgument. This method takes a boolean parameter for validation. When this parameter is false an IllegalArgument exception is thrown. But, I think this should work exactly the other way around: when the parameter is true the exception should be thrown. A small snippet will show why:

// As it is
Preconditions.checkArgument( !list.isEmpty(), "List must not be empty" );
Preconditions.checkArgument( list != null, "List must not be null" );
Preconditions.checkArgument( array.length != 0, "Array must not be empty" );
// As it should be
Preconditions.checkArgument( list.isEmpty(), "List must not be empty" );
Preconditions.checkArgument( list == null, "List must not be null" );
Preconditions.checkArgument( array.length == 0, "Array must not be empty" );

As you can see, this example shows three calls to its Preconditions methods. When I read those methods it simply feels wrong because of the inverted logic. That is, I want an exception when the list is empty, but here I have to invert the isEmpty result. The good news is that I’m not alone with this opinion. When I talked about this problem with my colleagues they all agreed and said things like, “I always do it wrong the first time…”. So, long story short, we think we’ve created a cleaner solution.

You might be familiar with Mockito, but if not, read this blog post. With mockito you write lines such as this: when( mock.getId() ).thenReturn( "id" );. Now, why not use this pattern for validation? Looking at the snippet again, it could be transformed to something like this:

when( list.isEmpty() ).throwIllegalArgument( "List must not be empty" );
when( list == null ).throwIllegalArgument( "List must not be null" );
when( array.length == 0 ).throwIllegalArgument( "Array must not be empty" );

Much better, right :)? We named the class that contains these methods Clauses because each use defines the condition of a contract such as “we agree that this list should not be empty”. I have created a basic implementation and published it together with some tests to give you the gist. You’ll see that the implementation is pretty straight forward.

Feel free to clone and modify this class as often as you’d like. I would love to see some contributions! With our Tabris framework I’ve been using this class since last week and it still feels right ;). Let’s see what time brings. There is one thing I wanted to add. A colleague of mine came up with an idea that goes one step further. He would like to see the following method within the Clauses class:

public static  void doThrow( T type, String message, Object ... values ) throws T {
  ...
}

I really like the generic approach. The only drawback is that it needs reflection to create the exception instances. On the other hand it would allow the use of individual exception types. I simply didn’t have the time to add this method. Feel free to do so if you’d like ;).

Thinking about the future of the Clauses class I would really like to see it in Guava. What do you think? Maybe a Guava contributor is reading this and will step up… ;). Meantime, kudos go to my colleagues Frank Appel and Moritz Post for their great input!