The Use
Case Approach
Massimo Marino - LBNL/ICS
Today we see use cases, a concept first formalized by Ivar Jacobson in
the 1987 OOPSLA conference [ACM, 1987], [Jacobson, 1987], being incorporated
into several object-oriented methods, e.g., Objectory [Jacobson et al.,
1992], Fusion [Coleman et al., 1994], the Booch method [Booch, 1994], the
so called Unified Method [Booch and Rumbaugh, 1995], Syntropy [Cook and
Daniels, 1994], and many others.
Use cases, or mechanisms in Booch, are a way to express the objectives
of the software system. In [Jacobson et al., 1995] use cases are defined
as "... a sequence of transactions in a system whose task is to yield a
measurable value...".
We like to define use cases as the behavioral chunks of the system
to be.
A valid approach is to examine system requirements with the intention
to identify candidate objects and establish interactions and interrelationships
among them. In the context of such an approach, we adopt use cases as a
conceptual description of the requirements.
We identify three primary motivations for use case creation:
-
gaining an understanding of the problem
-
capturing an understanding of the proposed solution
-
identifying candidate objects
Each use case is a description of the system in terms of how the user will
see it, and in terms of the delivered measurable values to the user [Jacobson,
1992], as well as a system mechanism, "a structure whereby objects collaborate
to provide some behavior that satisfy a requirement of the problem" [Booch,
1994].
Use cases, as they are most commonly described and used, are rather
functional in nature. This, by itself, is not really a problem. Many software
practitioners have a good deal of experience in functional decomposition
approaches to system building. Use cases present them with an opportunity
to continue their functional view of software development. However, we must
be careful: use cases, and in this respect they substantially differ from
functions, are not to be treated in isolation. In the ultimate end, they
describe one of the possible object collaborations within the system. In
most cases the same object participates in several use cases. That is,
to have a chance of accurately design any given object, we have to account
for all its appearances in the invented use cases.
While functions can be treated and developed in isolation by different
teams, and then integrated- the (in)famous big bang integration
of traditional development techniques -, use cases must be seen and managed
in their globality. In this respect we are less prone to this functional
creepism with an architecture-driven process [Booch, 1996]:
-
Specify the system's desired behavior through a collection of scenarios
-
Create, then validate, an architecture that exploits the common patterns
found in these scenarios
-
Evolve that architecture, making mid-course corrections as necessary to
adapt to new requirements as they are uncovered
Booch refers to these activities as the analysis, design and
evolution of the object-oriented life cycle. The key point here,
easily missed, is the "common patterns". The architecture, or set of categories
of related classes, is the one that supports the entire set of explicited
use cases, and the others to arise in the future.
A sure recipe for failure from the OO point of view is:
-
Determine the main (highest level of detail) functional capabilities of
the system to be
-
Write a high-level use case for each high-level functional capability.
-
Assign each high-level use case to a separate team for further elaboration
(partitioning the tasks)
-
Eventually, based on progressively more detail being added to the use cases,
each team would implement their particular partition of the system.
-
Integrate the efforts of each team into the final product.
This procedure suffers from a functional decomposition "front end" and
an object-oriented "back end", from missing the system architecture, and
from a delayed integration. We end up with a lot of duplication of effort
due to the lack of a dedicated activity to identify those objects that
are common to two or more partitions, and with scattered parts of many
same objects across more than one functional partition. It is easy to find
each part of the system having a different implementation of the same object:
this results in a significant amount of re-design and re-coding.
We should avoid the temptation to use this functional view of the system
as a basis for the creation of an object-oriented architecture for that
same system. Objects and functions do not map directly to each other, and
the architecture of an object-oriented system is significantly different
from the architecture of a functionally decomposed system. Recall the primary
motivations for use case creation mentioned before, and that all the foreseen
use cases contribute, in parallel, to the invention of the supporting architecture.
Object Interaction Diagrams
In many notations use cases are represented by interaction diagrams, schematically
shown in the figure, where the sequence of message flows progresses over
the objects participating in the use case. In the diagram time flows from
top to bottom and the event passing is supposed to take no time.
In [Jacobson et al., 1992] interaction diagrams are said to make evident
the decentralization of the responsibility in the object collaboration.
The following pictures clearly show the extreme structures of the use case:
the so called fork diagram and stair diagram.
A fork diagram arises in the presence of a central control. Pathological
combinations of functional architectures and object-oriented ones are often
encouraged by some of today's most popular methods, e.g., Objectory's so
called "control objects", Booch's "manager objects", Meyer's "command objects"
[Meyer,1988], and the countless examples of classes that encapsulate functions
only, i.e., the "stateless classes". The controller carries great
responsibility and often becomes more and more complex during the software
life cycle. The intelligence of this partition of the system is
highly localized in the controller who also requires a lot of visibility:
it has to know the presence of many other objects that alone are not able
of 'intelligent' behavior. Indeed the resemblance with a main function
and the related subroutines is striking.
If most of the system diagrams look like fork diagram, as in this extreme
case, an alarm bell should ring.
This is especially true if the "called" objects (again the resemblance
with subroutines...) are visible to the whole system, perform only under
external control, and lack of mutual collaborations. Most probably the
designers disguised data and/or function repositories or were just rewriting
a functional/data architecture, maybe a legacy FORTRAN solution to their
problem.
The fork diagram is absolutely valid if the use case describes the behavior
of a composite object. In this case the composite delegates its mandates
to the private components, and no other object will be responsible for
those parts. The use case shows then one of the modus operandi of
the composite object and constitutes a detailed description of its internal
mechanisms.
Some claim that there is nothing wrong with fork diagrams: they make
explicit the situation where the developing team keeps the door opened
to changes in the order of the operations managed by controller objects.
Personally we saw fork diagrams mainly coming out at the beginning of our
OO activities and fading away with the experience. In general it is not
easy to introduce changes in the system operations with controller-based
use cases, and becomes hard if the controlled objects are shared by many
controllers. On the other hand the sequence of the operations is under
total control of the manager object, but we do not look into object-oriented
techniques to achieve this, do we?
If they cannot be said to be a sure proof of bad design, fork diagrams
certainly make it easier to develop functional structures and should be
carefully validated and justified.
The other extreme is represented by the stair diagram. It clearly shows
the delegation of responsibility. Each object knows only few of the other
participating objects and we have no 'Do This - Do That' controller. The
use case initiator object role is limited to triggering the delegation
cascade. Each object has its own task and knows which other object can
help to fulfill it. Some subparts of these collaborations could easily find
their place in other use cases as well and constitute collaboration chunks
to achieve more complex behaviors. Here the responsibility is evenly distributed
among the objects and there is no need of a distributed visibility of all
participants.
The message here is not to avoid fork diagrams at all costs and strive
for stair ones only. The important thing is to be able to recognize the
structures, know what they do imply, and what they cost. In practice the
structures are a mixture of the two extremes where some object has more
"control" than other less independent objects. The lack of a controller
and the decentralization of responsibility is beneficial to the flexibility
of the architecture, and the localisation of the information. It also allows
to reuse some collaboration patterns of the system in different contexts.
Bibliography
[ACM, 1987] Association for Computing Machinery, OOPSLA'87 Conference
Proceedings, special issue of SIGPLAN Notices, Vol. 22, No. 12, December
1987.
[Booch, 1994] G. Booch, "Object-Oriented Analysis and Design - With
Applications", Second Edition, Benjamin/Cummings, Menlo Park, California,
1994.
[Booch, 1996] G. Booch, "Object Solutions - Managing the Object-Oriented
Project", Addison-Wesley, Menlo Park, California, 1996.
[Booch and Rumbaugh, 1995] G. Booch and J. Rumbaugh, "Unified Method:
User Guide, Version 0.8", Rational Software Corporation, Santa Clara,
California, 1995.
[Coleman et al., 1994] D. Coleman, P. Arnold, S. Bodoff, C. Dollin,
H. Gilchrist, F. Hayes, and P. Jeremaes, "Object-Oriented Development:
The Fusion
Method", Prentice Hall, Englewood Cliffs, New Jersey, 1994.
[Cook and Daniels, 1994] S. Cook and J. Daniels, "Designing Object Systems
- Object Oriented Modelling With Syntropy", Prentice Hall, Englewood
Cliffs, New Jersey, 1994.
[Jacobson, 1987] I. Jacobson, "Object-Oriented Development In an Industrial
Environment", OOPSLA'87 Conference Proceedings, special issue of
SIGPLAN Notices, Vol. 22, No. 12, December 1987, pp. 183-191.
[Jacobson et al., 1992] I. Jacobson, M. Christerson, P. Jonsson, and
G. Övergaard, "Object-Oriented Software Engineering: A Use Case Driven
Approach", Addison-Wesley, Reading, Massachusetts, 1992.
[Jacobson et al., 1995] I. Jacobson, M. Ericsson, and A. Jacobson, "The
Object Advantage: Business Process Reengineering With Object Technology",
Addison-Wesley, Reading, Massachusetts, 1995.
[Meyer, 1988] B. Meyer, "Object-Oriented Software Construction", Prentice
Hall, Englewood Cliffs, New Jersey, 1988.
[Meyers, 1992] S. Meyers, "Effective C++ - 50 Specific Ways to Improve
your Programs and Designs", Addison-Wesley, Reading, Massachusetts, 1992.
Massimo Marino
|