pátek 3. prosince 2010

Java: A Simple Assert Class for Design By Contract Checks

Very often, the programmer are lazy to include design by contract checks into the code. That means argument checking in the beginning of the method, checking of a wrong state in the method body, etc. The Java assert construct cannot be used for this purpose, since it is switched off by default (one has tu run java -ea to switch on the Java asserts). To simplify the design by contract checks, I have made three simple static methods:

/**
 * A static class for simple run-time checks. The methods from this class may (and should) be used to check arguments
 * and code for design-by-contract.
 * <p>
 * These are the methods for lazy programmers. If you like to write more complicated messages (and God bless you for
 * that), use the classic {@code if (...) throw ... } way.
 * <p>
 * It is not possible to switch off these checks, do not use them for any memory or CPU consuming operations.
 * 
 * @author xmedeko
 * 
 */
public class Assert {

 /**
  * Check, that the condition is {@code true}.
  * <p>
  * Usage:
  * 
  * <pre>
  * Assert.state(i &lt;= maxIter, &quot;iteration number exceeded&quot;);
  * </pre>
  * 
  * @param check
  * @param message
  *            An error message.
  */
 public static void state(boolean check, String message) {
  if (check)
   return;
  throw new IllegalStateException(message);
 }

 /**
  * Check, that the object is not null. 
  * <p>
  * Usage:
  * 
  * <pre>
  * Assert.notNull(entity, &quot;entity&quot;);
  * </pre>
  * 
  * 
  * @param o
  * @param message
  *            An error message.
  */
 public static void notNull(Object o, String message) {
  if (o != null)
   return;
  throw new NullPointerException(message);
 }

 /**
  * Check, that the argument fullfills the given condition.
  * <p>
  * Usage:
  * 
  * <pre>
  * Assert.argument(from &gt; 0, &quot;from has to be greater then zero&quot;);
  * </pre>
  * 
  * @param check
  * @param message
  *            An error message.
  */
 public static void argument(boolean check, String message) {
  if (check)
   return;
  throw new IllegalArgumentException(message);
 }

 /** No instances. */
 private Assert() {
  throw new UnsupportedOperationException();
 }

}

Note, to check argument for not null value, do not use
Assert.argument(obj != null, "obj is null");
but use instead:
Assert.argument(obj != null, "obj");

Also, do not put any String concatenation or other operation into the argument. These are the methods for lazy programmers. If you like to write more complicated messages (and God bless you for that), use the classic if (...) throw ... way.

Update 29.3.2011: I have just found out that Spring frameworks has org.springframework.util.Assert class, too.
Update 30.7.2012: Google Guava has a very similar solution in the class Preconditions.

Žádné komentáře: