Programming with Contracts in Java
by Ernest Friedman-Hill

Recently I read Christopher Diggins' article "Programming with Contracts in C++" in the March 2005 Dr. Dobb's Journal, and it got me thinking about Programming with Contracts (PwC), a concept first explicitly articulated by Bertrand Meyer in the Eiffel programming language. In PwC, you not only code the logic for a method, but assertions about the method's preconditions (what must be true for the method to be called) and postconditions (what must be true after the method is called.)

What's the difference between PwC and the perhaps more common term Design by Contract? In practice, not much. In theory, DbC is a pure design activity, but of course, contracts are useless unless they are executed. Once they are executed, you're programming, and hence doing PwC. Six of one, a half-dozen of the other.

In PwC, the assertions can execute every time a method is executed, although typically they're turned on only during testing. This executable contract provides fine-grained assurances about an application that unit testing alone can't. Postconditions can test the effect of calling a method, which is quite like what you get from unit testing, but preconditions test how a method is called by an application, and thus they give you the benefits of very fine-grained and thorough application testing.

In Eiffel, pre- and postconditions are added directly to the code. It's a powerful technique. The downside is that code with a lot of conditions is very cluttered. It's very similar to adding assertions to C or Java source: a few assertions provide useful information about the code, but thorough contract descriptions make it hard to see the implementation for the trees.

There are PwC tools for Java; perhaps the first was the now-defunct iContract. With iContract, you defined your pre- and postconditions using special Javadoc tags, directly in a class source.

A current Java PwC framework, jContractor, lets you define your contracts in separate classes, and doesn't use a special expression language, but instead uses a number of special naming conventions to connect pre- and postconditions to the methods they apply to. Furthermore, jContractor uses bytecode instrumentation, which affects your build process. I was hoping for something simpler.

Diggins' approach to PwC in C++ interested me because it's interface based. For Diggins, a contract is a class that can act as a wrapper for the class it describes. Each method in the contract class simply implements one method in the interface of interest by asserting preconditions, forwarding the call to the implementation object, then asserting postconditions. The nice feature of this is that the contract can be arbitrarily complex without complicating the described class's implementation. Furthermore, this lets you write a single contract for an interface, and apply it to all implementations of that interface. Best of all, it requires no special tools, special syntax, or special rules -- and you can start using it right now.

A Tutorial Example

Let's say you have an Account interface that represents a financial account:

            
public interface Account {
    String getCustomerName();
    void debit(double amount);
    // More ...
}

Furthermore, let's say you imagine that while there will be many implementations of this interface, they're all going to have to follow certain rules. For example, getCustomerName() should always return a non-null, non-zero-length String, and debit() should be called with a positive argument less than or equal to the current balance.

You can write a contact for Account that looks, in part, like this:

            
public class AccountContract implements Account {
    private Account m_impl;

    public AccountContract(Account impl) {
        m_impl = impl;
    }

    public String getCustomerName() {
        String result = m_impl.getCustomerName();
        assert result != null : "Customer name is null";
        assert result.length() > 0 : "Customer name is empty";
        return result;
    }

    public void debit(double amount) {
        double balance = getBalance();
        assert amount > 0 : "Debit amount nonpositive";
        assert amount <= balance : "Debit amount would overdraw";
        m_impl.debit(amount);
        assert getBalance() == balance - amount : "Computed balance incorrect";
    }

    // More ...
}

I've used standard Java assertions to implement the pre- and postcondition checks. An alternative would be to use unchecked exceptions. The advantage of using assertions is that they can be turned off easily via a runtime configuration switch. Another alternative would be to use checked exceptions -- i.e., to require that the interface methods declare an exception that they can throw when conditions are not met, and then throw them from the contract class. Although this latter solution is rather heavyweight, it could be appropriate in certain situations, such as in testing EJBs or JDBC drivers or any other category of classes in which all methods are already defined to throw a specific exception type.

The centerpiece of each method of the contract is a call to the corresponding method of the m_impl object. Note how I'm always careful to call the implementation method once and only once; you must make sure that the meaning of the code won't change if assertions are turned off.

Now you can test any implementation of Account by "wrapping" an instance inside an AccountContract, and using the AccountContract as if it were an instance of the class under test. Because all our assertions are in AccountContract, the AccountImpl class is very simple:

            
public class AccountImpl implements Account  {
    private String m_name;
    private String m_acctNumber;
    private double m_balance;

    public AccountImpl(String name, String acctNumber) {
        m_name = name;
        m_acctNumber = acctNumber;
    }

    public String getCustomerName() {
        return m_name;
    }

    public void debit(double amount) {
        m_balance -= amount;
    }

    // More ...
}

Practicalities

You can use a factory to hide this process of creating the contract object:

            
public class AccountFactory {
    public static Account get(String name, String acctNumber) {
        Account acct = new AccountImpl(name, acctNumber);
        if (Account.class.desiredAssertionStatus())
            return new AccountContract(acct);
        else
            return acct;
    }
}

The java.lang.Class.desiredAssertionStatus() method (introduced in JDK 1.4 as part of the assertions facility) basically just returns true if assertions are enabled. It's a convenient way to select the appropriate behavior for our factory.

In this case, the implementation class has no default constructor. In practice, you may want to insist that all your implementation class do have one and have a standard initialization method the factory can call. This would make it easier to configure the factory at runtime, or to construct different implementation classes using an Abstract Factory pattern.

Observations

This form of PwC is useful whenever an interface is going to be implemented multiple times, especially if those implementations are going to be done by multiple people or teams, or if they will evolve over time. It's slightly less useful if an interface will be implemented only once, as then the implementor most likely understands the contract well already. Still, PwC could be used even then to check that the class was being used correctly by implementing preconditions.

PwC obviously has a significant impact. For the very simple class being tested here, it's obvious that there is more code in the pre- and postcondition checks than there is in the AccountImpl class itself. PwC, like the assertions I've used here, is generally used only during development and testing, and turned off during production. Java's assertion facility makes it easy to turn assertions on or off at runtime for an entire application or even for individual packages or classes, making assertions an especially convenient way to implement PwC.

Contracts check both problems with the behavior of a class and problems with how a class is used. For this reason, they provide some of the benefits of both unit and application tests. Using contracts doesn't excuse you from writing unit tests, but it does provide excellent integrity checks during application testing that otherwise wouldn't be done.

All the code for this article is available here.