iContract: Design by Contract in Java

iContract allows you to explicitly specify your class contracts; no more guesswork as to what your classes promise

1 2 Page 2
Page 2 of 2
  • You invoke iContract, a command line tool written in Java, by starting the class com.reliablesystems.iContract.Tool.
  • The argument -minv,pre,post specifies that we want to instrument our code with invariants and preconditions as well as postconditions.
  • The -b"javac -classpath %CLASSPATH%;src" option specifies the command to use to compile Java classes before iContract instruments them. iContract needs to do that because it uses Java reflection to extract some of the properties of your Java classes. So in order to do its job, it first needs a compiled version of the uninstrumented Java class.
  • The -c"javac -classpath %CLASSPATH%;instr" option specifies the Java compiler command to compile the instrumented Java files.
  • The -n"javac -classpath %CLASSPATH%;_contract_db;instr" option specifies the Java compiler to compile the repository classes. iContract uses a set of Java classes as a repository to resolve inheritance and interface implementation relationships.
  • The option -oinstr/@p/@f.@e specifies the location of the instrumented Java files.

As you can see, iContract commands can be quite involved, so it's best to create a small build script for every project.

After you execute that command, we will have two versions of the compiled class files of our sample project. The src directory will contain the uninstrumented class, while the instr directory will contain the instrumented version.

We can now run our example, then see the assertions in action. Let's run the uninstrumented version first:

$ java -cp ./src StackTest
Exception in thread "main" java.util.NoSuchElementException
        at java.util.LinkedList.getLast(LinkedList.java:107)
        at StackImpl.top(StackImpl.java:24)
        at StackImpl.pop(StackImpl.java:17)
        at StackTest.main(StackTest.java:14)

As you can see, something went terribly wrong! Let's see if the instrumented code can shed some light.

$ java -cp ./instr StackTest
Exception in thread "main" java.lang.RuntimeException:
java.lang.RuntimeException: src/StackImpl.java:22: error:
precondition violated (StackImpl::top()): (/*declared in Stack::top()*/ (!isEmpty()))
        at StackImpl.top(StackImpl.java:210)
        at StackImpl.pop(StackImpl.java:124)
        at StackTest.main(StackTest.java:15)

Well, that's better, isn't it? We now know exactly what went wrong. The precondition !isEmpty() of the StackImpl.top() method was violated. We were calling top() on an empty Stack.

Conclusion

I hope that you feel our little journey into DBC in Java was worthwhile. You should have a good idea of how useful iContract as a tool is to your development efforts.

Please be aware that iContract is still in beta (and has been for some time). Some bugs in the tool are laid out on the iContract Webpage.

You'll want to check out a number of iContract supporting tools:

  • iDoclet integrates iContract assertions into the Javadoc documentation
  • iDarwin builds on top of iContract to add constraints at the architectural level of software projects
Oliver Enseling is the principal Java consultant of Martian Software. Programming has been his passion since he was sixteen. He is a Sun certified Java developer and works on distributed systems development in Minnesota's Twin Cities area.

Learn more about this topic

1 2 Page 2
Page 2 of 2