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