Design by Contract

Design by contract (DBC) is a method originally proposed by Betrand Meyer [97] for the design of object-oriented and component-oriented systems. The main characteristic of DBC is that classes define their behavior and interplay by contracts. A contract in this context consists essentially of a class invariant and pre- and post-conditions for all methods of the class interface. While Eiffel, the language preferred by Meyer, explicitly supports contracts, we have to find other ways in Java. There are both commercial Java expansions (e.g., JContract [URL:JContract] and JWAM-Contract [URL: JWAM]) and several free Java expansions (e.g., [URL:IContract]) available for DBC users.[10] One interesting alternative is the use of the contract parts for the construction or expansion of our unit tests:

We can learn primarily from the pre-conditions which test we will not have to write: no test with null as in parameter and no test for nextGermanWord(), if we have not previously tested hasNextTranslation(). And the following lines could be produced from the post-condition:


We could insert the two assert lines in our test cases after each call of nextTranslation(). On the other hand, it would not make much sense because subsequent asserts would normally implicitly cover both conditions. This is typical because DBC conditions are not allowed to execute operations that change the state of an object and they are therefore often relatively weak in terms of their specificity. A design paradigm thought to be an antipole of DBC is defensive programming. This paradigm assumes that the pre-conditions of a function or method call are tested by the method itself and that a violation of the precondition leads to a defined error behavior. Fault-tolerant systems normally use this paradigm. The major drawbacks are higher development cost, increased runtime, and a potential veiling of coding errors.

Defensive coding is implicitly assumed in many specifications: developers are expected to respond to wrong input values by an understandable error message instead of an undefined behavior. In contrast to DBC, negative tests for pre-conditions are both meaningful and essential for adequate testing in this case (see , , Error Cases and Exceptions). The general rule here is that defensively developed classes require more isolated unit tests, whereas a contract-based design demands interaction tests [McGregor01, p. 224]. We can see that DBC contracts can serve as inspiration for our unit tests, provided that the contracts were formulated. Method-centered test cases can normally be translated directly into pre- and post-conditions, and vice versa. The big (unanswered) question is therefore, At what point in our test-first development cycle is it meaningful to explicitly specify the contracts? A DBC contract might play its most successful role as an unaware source of ideas during the test-first development, when the developer often has pre-conditions, post-conditions, and invariants in mind without explicitly formulating them. But the actual contracts represent the unit tests themselves.

Explicit contracts are advantageous in any event when they already exist—for example, during subsequent creation of unit tests for existing software (see also , )—and when it is a matter of defining and documenting interfaces for external development teams. If we also use an appropriate DBC expansion, we can reduce the number of unit tests to be written by those that test the contract verified elsewhere. [10]The assert command available since JDK 1.4 is useful only to a very limited extent, because it does not support subtypes and invariants for DBC.