Dr. Dobb's Journal January 1998
Design by Contract
Design by contract is a technique used to help ensure the correctness of software. A software contract is a specification of the behavior of a class and its associated methods. The contract outlines the responsibilities of both the caller (client) and the method being called. Failure to meet any of the responsibilities stated in the contract results in a breach of contract, and indicates the existence of a bug somewhere in the implementation of the software. Contracts increase the reusability and robustness of software while decreasing its complexity. Correctly implemented software contracts reduce the chance that software bugs could remain unnoticed during the testing of a program.
There are three elements essential to defining a software contract: preconditions, postconditions, and invariants. Preconditions and postconditions define the responsibility of the client and method, respectively. Invariants define rules common to both the client and the methods. Defining responsibilities for classes and methods helps you to avoid writing redundant checks because methods and classes are contractually bound to fulfill their part of the contract.
A method's preconditions represent the responsibilities that a client has when making a call to that method. Preconditions specify what a portion of a program's state must be at the entry of a method. If a method's preconditions are violated, then this is a breach of contract, and the method is freed from the responsibility of meeting its postconditions. It is the responsibility of the client to meet a method's preconditions, not the responsibility of the method to verify that its preconditions have been met.
Postconditions are used to specify a method's responsibilities. As long as its preconditions are satisfied, a method is responsible for leaving the program in a state defined by its postcondition. It is the method's responsibility to ensure that this state is reached, and the client can continue executing while safely assuming that the method has performed correctly.
Unlike preconditions and postconditions, invariants are universal across an entire class. An invariant specifies both the responsibilities that a client has for using a class, and the responsibilities that the class's methods have to the client. An invariant is equivalent to supplying a common condition as both a precondition and postcondition for each public method of a class. Meeting the requirements set by an invariant is the responsibility of the client when calling a method and the responsibility of the method before returning to the client.
A software contract can be completely specified through the use of preconditions, postconditions, and invariants. Specifying contracts in this manner produces classes that are easy to use and understand. The contract serves as a guide to using a class as well as a formal specification of the behavior of the class. Contracts are therefore useful during both the design and implementation phases of a project. Design by contract produces a class whose behavior is well defined and can therefore easily be reused in the future.
-- J.E.P., M.A.S., M.N.S.
Copyright © 1998, Dr. Dobb's Journal