Model-based specification
State and operations
}{
Specifying state and operations
}
Z
-
-
Change and invariance
-
-
Verification
slide: Model-based specification
Several development methods,
including Responsibility Driven Design and Fusion (see section [Fusion]),
allow for the specification of
user interactions in a semi-formal
way by means of pre- and post-conditions.
These approaches have been inspired
by model-based specification methods
such as VDM and Z, which offer a formal
framework for specifying the requirements
of a system.
Model-based specification methods derive
their name from the opportunity to
specify a mathematical model
capturing the relevant features of the
system.
Operations, which may correspond
to user actions, can then be specified
in a purely logical way.
In the following, an outline of
the specification language Z will be given.
More importantly, the specification
of a simple library system will be discussed,
illustrating how we may specify
user actions in an abstract way.
(The use of the Z specification language
is in this respect only of subsidiary
importance.)
In the subsequent section, we will look
at the realization of the library
employing an abstract system of objects
and events corresponding to the user
actions, which reflects the characterization
given in the formal specification.
The specification language Z is based on classical
(two-valued) logic and set theory.
It has been used in a number of industrial projects
(Hayes, 1992) and to specify the architecture of
complex intelligent systems (Craig, 1991).
The central compositional unit of specification in Z
is the schema.
A schema may be used to specify both states and operations
in a logical way.
The logic employed in Z is a typed logic.
The specification of a schema consists of
a number of declarations followed by constraints
specifying conditions on the variables introduced
in the declarations.
Declarations may include other schemas, as
in the example specification of the operation op.
The schema itself is a compound schema
that results from the logical conjunction of the schema
state and its primed version ,
which denotes state after applying op.
Both schema inclusion and schema conjunction are
examples of the powerful schema calculus supported by Z,
which enables the user to specify complex systems
in Z.
Moreover, schemas may be decorated to
specify the effects of an operation.
Invariance may be specified
as in , which expresses that the
state before applying the operation
is the same as the state (denoted by )
after applying the operation.
Because schemas are specified in a logical manner,
both pre- and post-conditions are implicitly
specified by the constraints included in the schema.
Hence, to verify that an operation op is legal
for a state it is merely required to verify
that the conditions specified for state hold,
and that, together with the pre-conditions
(which are implicitly specified by the schema for op),
they imply the logical formula characterizing op.
See slide [10-model].
State
slide: The specification of a $Counter$ in Z
An important property of Z
is that it allows for a graphical
layout of schemas, as illustrated
in the specification of a Counter
given in slide [z-ctr].
The state of a Counter is given by
the Counter schema declaring an integer
variable n, which is constrained
by the condition .
The operations Incr and Decr are specified
by defining the
state following the operation by,
respectively, and
.
Both operations require the declaration
to indicate that the
state specified by Counter will
be modified.
In addition, the operation Decr requires
as a pre-condition that ,
needed to prevent the
violation of the invariant, which
would happen whenever n became less
than zero.
An alternative specification of the
Counter is given in slide [z-ctr-2].
Counter
Z
-
-
-
-
Bounded counter
-
-
slide: An alternative specification of the $Counter$
To emphasize that we may regard
the Counter as an object, the operations
have been prefixed by Counter in a
C++-like manner.
This is only a syntactic device, however,
carrying no formal meaning.
In addition, both the operations
Incr and Decr declare
an integer variable which acts,
by convention, as an input parameter.
Similarly, the integer variable
declared for the operation value
acts, again by convention, as an output
parameter.
Since Z allows the inclusion of
other schemas in the declaration part
of a schema, we may easily mimic
inheritance as illustrated
in the specification of
, which is a Counter
with a maximum given by
an integer constant Max.
Similarly, we may specify the operations
for the by including
the corresponding operations
specified for the Counter, adding conditions
if required.
From a schema we may easily extract the
pre-conditions for an operation by removing from
the conditions the parts involving
a primed variable.
Clearly, the post-condition is then
characterized by the conditions thus eliminated.
For example, the pre-condition of the
operation is , whereas
the post-condition is
which corresponds to the implementation requirement
that the new value of the Counter
is the old value plus the value of the
argument .
In a similar way, the pre-condition
for applying the operation
is .
Note, however, that this pre-condition
is stronger than the original
pre-condition , hence to conform
with the rules for refinement
we must specify what happens when
as well.
This is left as an exercise for the reader.
Clearly, although Z lacks a notion
of objects or classes, it may conveniently
be employed to specify the behavior
of an object.
In [Stepney], a number of studies are collected which propose
extending Z with a formal notion of classes and inheritance.
The reader interested in these extensions is in particular
invited to study Object-Z, OOZE and Z++.
As an historical aside, we may note that Z has been of significant
influence in the development of Eiffel (see Meyer, 1992b).
Although the two approaches are quite divergent,
they obviously still share a common interest in correctness.
In contrast to Eiffel, which offers only
a semi-formal way in which to specify the behavior
of object classes, Z allows for
a precise formal specification of
the requirements a system must meet.
To have the specification reflect
the object structure of the system
more closely, one of the extensions
of Z mentioned above may be used.
An example of using (plain) Z
to specify the functionality
of a library system is given below.
The specification of a library
Imagine that you must develop
a program to manage a library,
that is keep a record of the books
that have been borrowed.
State
slide: The specification of a Library
Before developing a detailed object
model,
you may well reflect on
what user services the library must
provide.
These services include the borrowing
of a book, returning a book and asking
whether a person has borrowed any books,
and if so which books.
These operations are specified
by the schemas Borrow, Return
and Has in slide [z-lib-2].
(Don't be frightened of the mathematical notation
in which these operations are specified.
The notation is only of secondary importance
and will be explained as we go along.)
Operations
slide: The Library operations
Since we are only interested in the abstract
relations between people and books, we may
assume Book and Person to be primitive types.
The specification given in slide [z-lib-1]
specifies an abstract state,
which is actually a partial function
delivering the person that borrowed
the book if the function is defined for
the book.
The function is partial to allow for the situation where
a book has not been borrowed,
but still lies on the shelves.
The invariant of the library system
states that the domain of
the function borrowed must be a subset
of the books available in the library.
Given the specification of the state, and some
mathematical intuition,
the specification of the operations
is quite straightforward.
When a Borrow action occurs, which
has as input a book and a person ,
the function
is defined by extending borrowed
with the association between and ,
which is expressed as
the mapping .
As a pre-condition for Borrow, we have that borrowed
must not be defined for , otherwise
some person would already have borrowed
the book .
The Return action may be considered
as the reverse of the Borrow action.
Its pre-condition states that borrowed
must be defined for
and the result of the operation
is that the association between
and is removed from
.
Finally, the operation Has
allows us to query what books are in
the possession of a person .
The specification of Has employs
the mathematical features of Z
in a nice way.
The output, which is stored in
the output parameter ,
consists of all the books related
to the person .
The set of books related to is obtained
by taking the relational image of the inversion
of borrowed for the singleton set
consisting of , that is,
each book x for which
an association is in borrowed
is included in the set .
Again, it is not the notation that is important
here, but the fact that the specification defines
all top-level user interactions.