Contracts


introduction teaching contracts patterns events examples foundations conclusions references
The notion of contracts has originally been introduced in  [Meyer88] as a means to characterize the functionality of object classes employing (subset of) first order logic. A contract consists of the specification of a pre- and post-condition for each method of a class, and an invariant specifying the constraints that must be satisfied by (the state of) each object instance. Contracts may play an important role in object-oriented software development, from a design perspective (as a method of specifying system functionality) as well as from an implementation perspective (as a means to check for runtime consistency).

Problems

The least difficult part in teaching the notion of contracts (that is to students with some training in logic or formal methods) is to explain the relation between the two formalisms involved, the 'logical' part and the 'programming' part. Much more difficult is to get students to understand the notion of 'contract refinement' as involved in characterizing the functionality of classes derived by (strict) inheritance from a given class (with an associated contract).

Background

The notion of contracts may be related to a number of different areas in the study of object-oriented software development, including abstract data types, client/server models and responsability driven design.

From the perspective of design, contracts may be regarded as a formalization of an object model consisting of a collection of (informal) class descriptions, as for example obtained by applying one of the methods described in  [CRC,Booch,Wirfs]. Using contracts, the functionality of the object class and invariant characteristics of each instance may be specified unambiguously, without writing one line of code. Although perhaps not the method of choice for the majority of software developers, specification by contract is an adequate means to capture both functional dependencies between objects as well as intra-object dynamics. With reference to the literature on abstract data types and program correctness, teaching 'contracts' is simply a matter of presenting a doctrine, or (put more mildly) a style of software development with solid theoretical foundations.

When thinking about contracts in the context of derivation by inheritance, however, many students get confused. Technically, the pre-condition of a related method may not be stronger in the 'refined' contract, and for the post-condition may not be weaker. In addition, the object invariance may not be weaker in the 'refined' contract. In particular, the contra-invariance involved in the possible weakening of pre-conditions appears to be difficult to understand. For example, when asked (in an oral examination) to characterize contract refinement, students are often unsure what to do with the object invariance, and for method pre- and post-conditions many choose either for weakening them both or strengthening them both.

Basic metaphor

To understand what is involved in specifying a contract and its subsequent refinement, we need a metaphor from daily life to guide the intuition. Such a metaphor is easy to find, take for example an agreement we may make with a vendor of computing equipment. Once we (as clients) satisfy the requirement of paying a certain amount of money, the vendor (as a supplier of services) will be obliged to deliver the goods we desire.

Extending the metaphor to 'contract refinement' we may employ the notion of competition, and not the notion of 'subcontracting' as  [Meyer88] mistakingly believes. When employing (strict) inheritance, the derived class must embody a better contract. Taking objects as suppliers of services, this means more and better services at a better price. In daily life a better price means less money, at least from the perspective of the client. A better contract may be understood as offering a competitive deal. Clearly, a vendor offering the same goods for a higher price will not only not attract clients, but will be out of competition in no time. In other words, a better contract simply means less (or equal) requirements for the client and more (or equal) obligations for the object supplying the service.

Realization

Apart from being an invaluable concept guiding the design of (object-oriented) systems, contracts also facilitate the validation of actual programs, since both object invariants and method pre- and post-conditions can be tested runtime by incorporating appropriate program statements. The Eiffel language, as an example, provides syntactic and runtime support to incorporate such statements directly. However, by employing a simple programming idiom contract-related runtime checks may be easily incorporated in programs written in a language such as C++ as well. See section Examples.

Comments

The notion of contracts as explained here is strictly confined to the interaction between an object (regarded as a provider of services) and a client of that object. It does not capture the situation where multiple parties are involved, each playing their role in a complex interaction pattern. See section Theory.
introduction teaching contracts patterns events examples foundations conclusions references