Behavioral refinement
\oopindex{refinement}
Designing an object oriented system requires to identify the
objects needed to model the problem domain
and to assess their responsibilities and (possible) cooperation
with other objects.
See [WWW90] and also section \ref{dig:oom}.
From this perspective
objects may be regarded as entities that provide a service in response to a message.
The services an object is willing to provide are listed in the external
method interface of (the class of) an object.
The set of services provided by an object is called
a contract in [Meyer88].
A contract specifies the obligations of both the client and the
server, that is
when the client complies to the restrictions imposed by the server
the server has the obligation to deliver the service.
Inheritance has been characterized as a means to specialize concepts or classes
of objects.
Viewing an object as an entity that provides a service, the question
arises of what it means to specialize or refine a service.
And a fortiori, what it means to refine a contract.
The intuitive answer to this question, for a service, is
that refinement means to provide a better service,
a service that imposes less restrictions on the client and (yet)
delivers better results.
And for a contract, taken as a set of services, a better contract means
a contract that comprises more services and with regard to
the services already available,
the individual services must be at least as good or better.
Perhaps somewhat surprisingly, these seemingly vague notions
may be given a precise formal underpinning.
In the following we will sketch the formal interpretation
of the notions of refining a service and a contract (that is a set of services).
We will start with a syntactic characterization of refinement,
by showing how the subtype relation introduced previously
may be regarded as characterizing the refinement of a service.
Recall that to define the subtype relation between objects we took
objects as records consisting of attributes and functions,
and we characterized the subtype relation componentwise by
defining a subtype relation for attributes and functions.
Attributes
Each of the components of an object may be regarded as providing a service.
An attribute may be regarded as providing the service
of giving information about the state of an object.
The type of the attribute tells what kind of information the
attribute may provide.
Taken as a service, an attribute (type) is improved upon by
another attribute (type) if the latter gives more precise information
concerning the state of the object.
Hence the service refinement relation between attribute (types)
is exactly the subtype relation between simple types,
that we have characterized as the subset relation.
As an example, the attribute gives less information
than the attribute .
Applied to people, the latter simply tells more.
Functions
The service provided by a function may be characterized by the input/output
behavior of the function.
Syntactically, the domain type (the types of the parameters of the function)
specifies the restrictions imposed on the client -- the user of the function;
and the result type of the function specifies the restrictions to which the function
delivering the service must conform.
Viewing a function as a service, a function is a better
function then a function f if the result delivered by is better
than the result delivered by f and if the restrictions imposed on the client
by are less severe than the restrictions imposed by f.
It is easy to see, this interpretation agrees with the subtyping rule
for functions that states that
if and .
As an example consider the functions
[D
D]
We have that since the domain of allows more freedom than
the domain of f ( because )
and the result of is more carefully delineated than the result of f
(because ).
It is left to the reader to think of a daily life interpretation for these functions.
Objects
In a similar fashion, we may interpret the subtype relation between
objects (taken as records) as a refinement relation between sets of services.
Namely, a set of services may be improved by adding new services
or by refining one or more of the already available services.
Having a purely syntactic notion of refinement however is not sufficient to
characterize the behavior of objects in an adequate way,
as the following example will show.
Suppose that we have defined a class Person with an attribute age
and a function , and that we derive a class Retiree by restricting
the range of the attribute age.
[D
D]
According to our rules, the class Retiree refines the class Person.
However, when we apply with argument 40 to a Retiree
we no longer have a Retiree
since we are violating the restrictions imposed by the attribute age
of a Retiree.
Now we could redefine Retiree as
[D
D]
but then we no longer have that since
[D]
because .
A solution to this problem is to introduce a function such as
that allows to increment the age of a given person,
be it a Person or a Retiree.
Contracts
The example shows that the design of a hierarchy of classes
is not altogether a trivial matter.
Moreover, it shows that syntactic criteria
are insufficient to decide on whether a hierarchy of classes
provides the right abstraction.
Type checking alone does not preclude such errors.
The detection of a violation such as that exemplified
by the function will occur only at run-time.
In order to characterize the contract offered by an object in a more
formal way [Meyer88] proposes to use assertions to
specify the behavioral characteristics of a method.
The use of an assertion language to specify the pre- and post-conditions of a method
provides a powerful means to lay down the restrictions to which the client of
a method must conform and to characterize
the obligations for the provider of the service (when these restrictions are met).
In the actual development of systems, the use of pre- and post-conditions
is of help in locating the source of errors.
When a violated pre-condition is encountered the error must
be looked for in the code of the client.
Contrarily, the violation of a post-condition hints at a bug in the supplier.
Now, to establish what it means to refine a contract,
recall that refining a service means to give better service
while alleviating the restrictions imposed on the client.
In accordance with the pattern established for the refinement of a function,
to improve a method -- of which the behavior is (partially) described
by assertions -- means to accept weaker pre-conditions and to
guarantee stronger post-conditions.
Refining a contract thus consists of adding new services
or improving upon existing ones.
See also [HHG90] for contracts specifying behavioral compositions of objects.