topical media & game development
object-oriented programming
Identifying objects
subsections:
Object-oriented design aims at describing
a system in terms of objects (as the primary
components) and the interaction between them.
Motivated by the wish to arrive at stable
abstractions,
object-oriented design is often
characterized as
modeling reality,
that is the application domain.
However, many applications require, at least
partly, a
system-oriented view towards
design, since they involve system artifacts
for which there exist no clearly identifiable counterparts
in the application domain.
As an example, think of a window-based system.
Many of the items (widgets) introduced in such a
system belong to an artificial reality,
which at best is only vaguely analogous with
reality as we normally understand it.
Irrespective of whether the design is intended
as a preliminary study before the implementation
or as a
post hoc justification of the actual system,
the most important and difficult part of design
is the
identification of objects and the
characterization of their role in the system
and interaction with other objects.
As observed in
[McGregor92],
object-oriented design
is best seen as
class oriented,
that is directed towards the
static description
of (classes of) objects, rather than a description of the
dynamic interaction between actual objects.
In section
[prototypes],
we will discuss
class-less languages which are well suited for
exploratory programming.
However, from the perspective of design,
we are more interested in a (static)
abstract specification of the components
that constitute the system.
Object-oriented design -- decomposition into objects
- application/system/class oriented
Identifying objects -- responsibilities
Layers of abstraction
- components, subsystems, frameworks
slide: Object-oriented design
In comparison with a functional approach,
object-oriented design is clearly
data oriented.
However, although a data-oriented approach may
provide a first guideline in developing the system,
the primary concern in object-oriented design
should be the responsibilities
of an object rather than how it acts as a
data manager, so to speak.
For larger systems, the complexity of the design may
necessitate the introduction of additional layers
of abstraction.
Apart from objects, which must be regarded
as the basic components of a system,
we may need to isolate subsystems,
consisting of a number of related object classes.
When we have developed a subsystem that
can be used in a variety of contexts, such a
subsystem may be used as a framework.
A framework is generally not only a collection of
classes but must also be seen as an approach or
method in its own way, since it usually
imposes additional constraints
on the development.
For example, most development environments
for window-based applications provide
a framework consisting of a number
of predefined classes and functions, and guidelines
or recipes that prescribe how to use or adapt
these classes and functions.
Also, most frameworks impose a specific
control model, such as the event-driven
control model imposed by window programming environments.
Modeling heuristics
Following [Booch86], we may characterize objects as `crisp'
entities that suffer and require
actions.
From the perspective of system development,
objects must primarily be regarded as
computational entities,
embodying the means by which we may express
a computation.
Modeling a particular problem domain, then,
means defining abstractions in terms of objects,
capturing the functional characteristics
of that domain.
The question is, how do we arrive at such a model?
Objects -- crisp entities
- object = an entity that suffers and requires actions
The method:
- Identify the objects and their attributes
- Identify operations suffered and required
- Establish visibility/interface
slide: The Booch method
In [Booch86], a straightforward method of object oriented
development is proposed,
which consists of the successive identification of
objects and their attributes, followed by
a precise characterization of the interobject
visibility relations.
In [Booch91], a shift of emphasis has occurred
towards determining the semantics of an individual object
and the interaction between collections of objects.
Heuristics
- model of reality -- balance nouns (objects) and verbs (operations)
Associations
- directed action -- drives, instructs
- communication -- talks-to, tells, instructs
- ownership -- has, part-of
- resemblance -- like, is-a
- others -- works-for, married-to
slide: Heuristics for modeling
As a heuristic to arrive at the proper abstractions
of the problem domain (in terms of object classes),
[Booch86] proposes scanning the requirements document
for nouns, verbs and adjectives,
and using these as initial suggestions for respectively
objects, and operations and attributes
belonging to objects (see slide [3-heuristics]).
This technique has been adopted and augmented
by a number of other authors, among which
[WWW90] and [Rum91].
For example, [WWW90] illustrate the technique in fine
detail in several examples, including the design of an
automated teller machine and a document processing
system.
In addition to the interpretation of nouns as
possible objects, verbs as possible operations on objects,
and adjectives as possible attributes of objects,
[Rum91] suggest this technique to determine
other relations and associations between object classes
as well.
For instance, a model of control and object
interaction may be suggested by phrases
indicating directed action or communication.
Similarly, structural issues, such as whether
an object owns another object or whether
inheritance should be used, may be decided
on the basis of resemblance or
subordination relations.
Example -- ATM (1)
The example of an automated teller machine
discussed in [WWW90] nicely illustrates a number of
the notions that we have thus far looked at only
in a very abstract way.
A teller machine is a device, presumably familiar to everyone,
that allows you to get money from
your account at any time of the day.
Obviously, there are a number of constraints
that such a machine must satisfy.
For instance, other people should not be allowed
to withdraw money from your account.
Another reasonable constraint is that a
user cannot overdraw more than a designated
amount of money.
Moreover, each transaction must be correctly
reflected by the state of the user's account.
Candidate classes
ATM
- account -- represents the customer's account in the banks database
- atm -- performs financial services for a customer
- cardreader -- reads and validates a customer's bankcard
- cashdispenser -- gives cash to the customer
- screen -- presents text and visual information
- keypad -- the keys a customer can press
- pin -- the authorization code
- transaction -- performs financial services and updates the database
slide: The ATM example (1)
An initial decomposition into objects based
on these requirements is shown in slide [3-atm-1].
In [WWW90], a fully detailed account is given of how
one may arrive at such a decomposition by carefully
reading (and re-reading) the requirements document.
What we are interested in here, however,
is how we may establish that we have not overlooked
anything when proposing a design, and how we may
verify that our design correctly reflects the requirements.
This particular example nicely illustrates the need
for an analysis of the use cases.
To develop a proper interface, we must precisely
know what a user is expected to do
(for instance, insert a bank card, key in a PIN code)
and how the system must respond (what messages must
be displayed, how to react to a wrong PIN code, etc.).
Another decision that must be made is when the
account will be changed as the result of a transaction.
Also, we must decide what to do when a user overdraws.
A very important issue that we will look at in more
detail in the next sections is how the collection
of objects suggested above will interact.
What means do we have to describe the cooperation
between the objects, and how do we show that the
proposed system meets all the requirements listed above?
Moreover, can we verify that the system satisfies
all the constraints mentioned in the requirements document?
Validation
However, before examining these questions
and trying out different scenarios, we may as well
try to eliminate the spurious classes that came up
in our initial attempt.
In [Rum91], a number of reasons are summarized that
may be grounds on which to reject a candidate class.
See slide [3-eliminating].
Eliminating spurious classes
- vague -- system, security-provision, record-keeping
- attribute -- account-data, receipt, cash
- redundant -- user
- irrelevant -- cost
- implementation -- transaction-log, access, communication
Good classes
slide: Eliminating spurious classes
For example, the notion underlying the candidate class
may be too vague to be represented by a class,
such as the notion of system or record-keeping.
Another reason for rejecting a suggested class
may be that the notion represents not so much a class,
but rather a possible attribute of a class.
Further, a proposed class may either be redundant,
for example the class user, or simply
irrelevant, as is the class cost.
And finally,
a class may be too implementation oriented,
such as the class transaction-log
or classes that represent the actual communication
or access to the account.
Looking back, our choice of candidate classes seems
to have been quite fortunate,
but generally this will not be the case,
and we may use the checklist above to prune
the list of candidate classes.
An interesting architectural issue is, how may we
provide for future extensions of the system?
How easily can we reuse the design and the code for
a system supporting different kinds of accounts,
or different input or output devices?
And how can we establish that the objects, as
identified, interact as desired?
Assigning responsibilities
Design is to a large extent a matter of creative thinking.
Heuristics such as performing a linguistic scan
on the requirements document for finding objects
(nouns), methods (verbs) and attributes (adjectives)
may be helpful, but will hopelessly fail
when not applied with good taste and judgement.
Not surprisingly, one of the classical techniques
of creative writing, namely the shoe-box method,
has reappeared in the guise of an object-oriented
development method.
The shoe-box method consists of writing fragments
and ideas on note cards and storing them in a (shoe) box,
so that they may later be retrieved and manipulated
to find a suitable ordering for the
presentation of the material.
To find a proper decomposition into objects,
the method creates for each potential
(object) class a so-called CRC card,
which lists the Class name, the Responsibilities
and the possible Collaborators of the proposed class.
In a number of iterations, a collection of cards
will result that more or less reflects the
structure of the intended system.
According to the authors (see Beck and Cunningham, 1989), the method
effectively supports the early stages of design,
especially when working in small groups.
An intrinsic part of the method consists
of what the authors call dynamic simulation.
To test whether a given collection of cards
adequately characterizes the functionality of the intended
system, the cards may be used to simulate
the behavior of the system.
When working in a group, the cards may be distributed
among the members of the group, who participate
in the simulation game according to their cards.
See slide [3-crc].
Object-oriented thinking
CRC
- Immerse the reader in the {\em object-ness} of the material
- Give up global knowledge of control
- Rely on the local knowledge of objects
OO design with CRC cards
- Class, Responsibility, Collaborators
slide: The CRC method
A number of authors have adopted this method,
or developed a very similar method,
for identifying objects and characterizing
their functionality in an abstract way.
It is doubtful, however, whether the method has
any significance beyond the early stages of analysis and design.
Without any more formal means to verify whether the
responsibilities listed adequately characterize
the intended functionality of the system,
the method amounts to not much more than brainstorming.
Clearly, the method needs to be complemented
by more formal means to establish whether the (implicit)
protocols of interaction between the objects
satisfy the behavioral requirements
of the system.
Nevertheless, the elegant simplicity of the method
is appealing, and the card format lends itself to
easy incorporation in an on-line documentation system.
Moreover, since the method imposes no strict order,
and has relatively little overhead, it is indeed
a good way to get an initial idea of
what objects the system will comprise.
Example -- ATM (2)
Actually, the ATM example is an interesting example
for comparing the various approaches,
since it is used by many authors to illustrate
their methods.
In [WWW90] the example is used for spelling out
all the steps that must be taken.
In [Rum91] it is extensively described
to illustrate the various
modeling techniques employed by the method.
And in [BC89] the CRC cards method is illustrated
by sketching the design of an automated teller machine.
The approaches presented in [BC89] and [WWW90]
are actually very closely related.
Both may be characterized as responsibility-driven,
in that they concentrate on responsibilities
and collaboration relations
to model the interaction between objects.
However, the method described in [WWW90]
is much more detailed, and to some extent includes
means to formally characterize the behavior of an object
and its interaction with other objects.
To this end it employs an informal notion of
contracts as originally introduced in [Meyer88].
In section [ATM-1]
a number of candidate
classes have been suggested for our ATM.
Now, with the use of CRC cards, we will delineate
the functionality of (a number of) these classes
more precisely.
Also we will establish how the various object classes
must collaborate to perform their duties.
At the highest level of the design, we may distinguish between
two groups of classes:
the classes representing the banking model
(comprising the class account and the class transaction),
and the classes that model the interaction with the user
(comprising the class card-reader and the class
cash-dispenser).
At a lower level, we also need a class modeling
the database that provides persistent
storage for the user's account
and the information needed for authorization.
For each of these classes we will use a CRC card
to indicate their responsibilities and the classes
with which they need to collaborate.
The banking model, depicted in slide [3-atm-2a],
consists of the classes account
and transaction.
The class account keeps a record of the actual balance
of the account and must allow a user to deposit
or withdraw money.
However, for safety reasons, these operations are
never carried out directly, but are performed
by an intermediary transaction object.
The responsibilities of the transaction class
may be summarized as: the validation of user requests
and the execution of money transfers.
The responsibility for maintaining audit information is also
assigned to the transaction class.
To act as required, a transaction object
needs to communicate with a number of other objects.
It must acquire information from both the card-reader
and the database to check, for example,
whether the user has entered the right PIN code.
To validate a request, it must check whether the
account will be overdrawn or not.
To pay the requested money, it must instruct the
cash-dispenser to do so.
And it must contact the database to log the appropriate
audit information.
In contrast, an account only needs to respond
to the requests it receives from a transaction.
Apart from that, it must participate in committing the
transaction to the bank's database.
Note that the CRC method is non-specific about how
the collaborations are actually realized;
it is unclear which object will take the initiative.
To model these aspects we will need a more precise
notion of control
that tells us how the potential behavior
(or responsibility) of an object is activated.
The second group of classes may be called
interaction classes,
since these are meant to communicate with
entities in the outside world, outside from
the perspective of the system.
Also the bank's database may be considered
as belonging to the outside world,
since it stores the information concerning the
account and the authorization of customers
in a system-independent manner.
See slide [3-atm-2b].
Both the card-reader and the cash-dispenser
rely on a class called event,
which is needed to model the actions of the user.
For example, when a user inserts a bankcard,
we expect a transaction to start.
For this to happen, we must presuppose an underlying system
that dispatches the event to the card-reader,
which in turn notifies the teller machine
that a new transaction is to take place.
The flow of control between a transaction object
and the cash-dispenser is far more straightforward,
since a transaction object only needs to
issue the appropriate instruction.
However, the actual interaction between the
cash-dispenser and the underlying hardware,
that turns out the money, may be quite intricate.
The database may either respond directly to the request
coming from the account or transaction object
or it may respond to events
by taking the initiative to call the appropriate methods
of the account and transaction objects.
Whether the database may be accessed directly
or will only react to
events is actually dependent on the
control model we assume when developing the system model.
Object roles and interaction
Objects rarely live in isolation.
In a system of some complexity,
a number of different kinds of object
classes may usually be distinguished.
Each kind of class may be regarded as playing
a specific role in the system.
For example, when considering our ATM,
classes such as card-reader and cash-dispenser
are of a completely different kind, and play a completely
different role, than the classes
account and database for instance, or the classes
event and transaction.
Often it will take some
experimentation to decide how control must
be distributed among the objects comprising the system.
Although
the framework chosen for the development of the system
may partly determine the control model,
there will usually be ample choice left for the designer of
the system to define the interactions between objects.
Object roles
- actor -- operates (suffers no operations)
- server -- suffers operations
- agent -- suffers and operates ( actor & server)
slide: Object roles
An important function of the design document
is to elucidate the role of each object class
in the system, and to point out
how the objects cooperate to complete the task.
In [Booch86], a distinction is made between objects
that suffer no operations (actors),
objects that only suffer operations (servers)
and objects that both suffer and require operations
(agents).
Such a characterization in terms of initiative
may give a first indication of
the role an object plays in the system.
For example, the account class in our ATM example
is best characterized as a server class,
whereas the transaction class may be regarded,
in the terminology of [Booch86], as an actor
class, since it actively controls the computation.
In many cases, the software control model
adopted will also influence the way in which individual
objects are supposed to behave.
See slide [3-roles].
With respect to a global view of
the system, it is necessary to ensure that each object class
is completely defined,
that is to establish that each class provides a
sufficiently complete
method interface.
In [Booch86], a characterization is given of the
kinds of methods that may occur in an interface.
These include methods to create or destroy an
object, methods to modify the state of an object and methods
that only provide information on the state of
an object, or parts thereof.
Before being able to make final decisions
with respect to the functionality of a class, however,
it is generally necessary to get a clear
overall picture of the system first.
This requires what [Booch86] characterizes
as round trip gestalt design, which in other
words expresses the need to
analyze a little,
design a little,
implement a little,
test a little ...
(The notion of gestalt comes from
perception psychology, where it means a global
perceptual configuration emerging from the background.)
(C) Æliens
04/09/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.