Guard conditions in Java

So, my impetus for writing this post is the ‘require’ method in scala. It works a bit like the failed ‘assert’ that came to Java a while ago but never really took off. The ‘require’ in scala is used to write guard conditions, similar to assertions you may make in JUnit tests – here is an example:

object Shuffler {
  
  def shuffle(deck:Deck) = {
    require(deck.isNotEmpty, "deck cannot be empty")
    // code omitted...
  }

}

In Java I’ve seen the following:

public void shuffle(Deck deck) {
  // guard condition
  if (deck.isEmpty()) {  
    throw new IllegalArgumentException("Cannot shuffle an empty deck");
  }
  // code omitted...
}

and also

public void shuffle(Deck deck) {
  // guard condition
  if (deck.isNotEmpty()) {  
    // code omitted...
  } else {
    throw new IllegalArgumentException("Cannot shuffle an empty deck");
  }
}

This style of code can quickly create multiple nested ifs and make the code less readable. An old adage said “no more than one return point in a method” but this rule has not stood the test of time. As Kent Beck writes, this “was to prevent the confusion possible when jumping into and out of many locations in the same routine. It made good sense when applied to FORTRAN or assembly language programs written with lots of global data where even understanding which statements were executed was hard work … with small methods and mostly local data, it is needlessly conservative.”

Option 1: Roll-your-own Guard Condition

We fail fast – error if the condition we cannot handle is true. Note – now our happy path code (omitted) is not inside an if or else. We can write multiple guard conditions but can recongnise the guard conditions for what they are above the actual part of the method that affects change.

public void shuffle(Deck deck) {
  // guard condition
  if (deck.isEmpty()) {  
    throw new IllegalArgumentException("Cannot shuffle an empty deck");
  } 
  // code omitted...
}

Option 2: External Libaries

I think we can improve on this using a static method similar to the Assert class we use in JUnit, and classes to do this already exist. Our options include Validate (commons lang), Assert (Spring framework) and Preconditions (google-guava).

Here is an example using Preconditions:

import com.google.common.base.Preconditions;

public void shuffle(Deck deck) {
  // guard condition
  Preconditions.checkArgument(deck.isNotEmpty(), "Cannot shuffle an empty deck");
  
  // code omitted...
}

This is much simpler and easier to read for me. I believe that, as a rule of thumb, the code doing the primary purpose of a function should generally be equal to the amount of code doing the following tasks: Logging, Auditing, Error Handling, Guard Conditions.

A good comparison of the options is available here: http://www.sw-engineering-candies.com/blog-1/comparison-of-ways-to-check-preconditions-in-java

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s