Over the last three years, use cases
have become well established as one of the fundamental techniques of
object-oriented analysis. Although initially introduced by Ivar Jacobson
to the object community at the 1987 OOPSLA conference [1],
it was the publication of his book Object-Oriented Software
Engineering: A Use Case Driven Approach[2] in 1992
that marked the true beginning of use cases´ meteoric rise in popularity.
Possibly in reaction to the previous structured methods, early
object-oriented development methods overemphasized static architecture and
partially ignored dynamic behavior issues during requirements analysis,
especially above the individual class level where state modeling provides
an important technique for dynamic behavior specification. Use cases
provide a great many benefits in addition to correcting this overemphasis,
and most major object-oriented development methods (including my own) have
jumped on the band wagon and added use cases during the last few years. In
the resulting hoopla and hype, however, there has been little discussion
of the limitations and potential pitfalls associated with use cases. This
column is an attempt to provide a more balanced presentation and to
caution against the uncritical acceptance of use cases as the latest
patent medicine for all software ailments.
Has created a Smalltalk compiler
for the Java Virtual Machine. This compiler allows Smalltalk to run on any
JVM. The compiler currently produces 100% Java class files fully compatible
with the Sun Java Virtual Machine specification. This allows Smalltalk and
Java code to interact seamlessly and allows Smalltalk programs to run
anywhere Java runs! Click to learn more
Definitions
The term use case was introduced by Ivar Jacobson et al.
[1] and has been defined in several publications [2, 3, 4].
A use case is a description of a cohesive set of possible dialogs (i.e.,
series of interactions--see Note 1) that an
individual actor initiates with a system. An actor is a role played by a
user (i.e., an external entity that interacts directly with the system).
See Figure 1. A use case is thus a general way of using some part of the
functionality of a system.
Figure 1: The Primary Use Case Notations
A use case is not a single scenario but
rather a 'class' that specifies a set of related usage scenarios, each of
which captures a specific course of interactions that take place between
one or more actors and the system. Therefore, the description of an
individual use case typically can be divided into a basic course
and zero or more alternative courses. The basic course of a use
case is the most common or important sequence of transactions that satisfy
the use case. The basic course is therefore always developed first. The
alternative courses are variants of the basic course and are often used to
identify error handling. Within reason, the more alternative courses
identified and described, the more complete the description of the use
case and the more robust the resulting system.
As a user-centered analysis technique, the
purpose of a use case is to yield a result of measurable value to an actor
in response to the initial request of that actor. A use case may involve
multiple actors, but only a single actor initiates the use case. Because
actors are beyond the scope of the system, use-case modeling ignores
direct interactions between actors.
A use case may either be an abstract use
case or a concrete use case. An abstract use case will not be
instantiated on their own, but is only meaningful when used to describe
functionality that is common between other use cases. On the other hand, a
concrete use case can be instantiated to create a specific
scenario.
According to Ivar Jacobson, use cases are
related by two main associations: extends and uses. The extends
association specifies how one use case description inserts itself
into, and thus extends, a second use case description that is completely
independent and unknowing of the first use case. Depending on some
condition, the second use case may either be performed with or without the
extending use case. Extends can therefore be viewed as a kind of
'inheritance' between use cases in which the original use case definition
is extended by the extending use case definition to form a new 'combined'
use case. On the other hand, the uses association can be viewed as
a kind of 'delegation' or 'aggregation' that captures how one or more use
case descriptions incorporate the common description of another use case.
These two associations are closely related and easy to confuse. One clue
as to which is which is that if A extends B, then the extended B
'contains' A, whereas if A uses B, then A 'calls' B. The actual
distinction between these two associations is unclear, and Rumbaugh
[4] has thankfully combined them into a single adds
association from the main concrete use case to the abstract use cases
that it uses.
Clearly, use cases are functional
abstractions and are thus large operations, the implementation of which
thread through multiple objects and classes. However, a use case need not
have anything to do with objects. As pointed out by Jacobson
[5], " … it should be clear that use-case modeling is a
technique that is quite independent of object modeling. Use-case modeling
can be applied to any methodologyóstructured or object-oriented. It is a
discipline of its own, orthogonal to object modeling."
An Example
The requirements for Door Master, a
security system for controlling entry of employees through a secured door,
are documented in a previous ROAD column [6]. Except
for those requirements concerned with initialization, the functional
requirements for Door Master are captured in the following nine use cases:
Enter the Disabled Door.
Employees and security guards enter freely through the door when Door
Master is disabled.
Enter the Secured Door. Employees
and security guards enter through the door by (1) entering the entry
code on the numeric keypad, (2) entering through the door, and (3)
closing the door behind them.
Change the Entry Code. Security
guards change the entry code by (1) pressing the change entry code
button on the control panel, (2) providing authorization by entering the
security code on the numeric keypad, (3) entering the new entry code on
the numeric keypad, and (4) verifying the new entry code by reentering
it on the numeric keypad.
Change the Security Code.
Security guards change the security code by (1) pressing the change
security code button on the control panel, (2) providing authorization
by entering the old security code on the numeric keypad, (3) entering
the new security code on the numeric keypad, and (4) verifying the new
security code by reentering it on the numeric keypad.
Enable the Door Master. Security
guards enable Door Master by (1) pressing the enable button on the
control panel and (2) providing authorization by entering the security
code on the numeric keypad. Door master then (3) turns off the disabled
light, (4) turns on the enabled light, and (5) locks the door.
Disable the Door Master. Security
guards disable Door Master by (1) pressing the disable button on the
control panel and (2) providing authorization by entering the security
code on the numeric keypad. Door master then (3) turns off the enabled
light, (4) turns on the disabled light, and (5) unlocks the door.
The following two abstract use cases are
common to, and are therefore used by, five of the concrete use cases:
Enter the Entry Code. Employees
and security guards enter the entry code by pressing five keys on the
numeric keypad followed by the enter key. Door master beeps after each
key and verifies the entry code.
Enter the Security Code.
Employees and security guards enter the entry code by pressing seven
keys on the numeric keypad followed by the enter key. Door master beeps
after each key and verifies the entry code.
The following abstract use case extends
the Enable the Door Master and Enter the Secured Door use
cases:
Raise the Alarm. The alarm is
raised if the door is left open too long or if the door is not shut when
Door Master is enabled. The security guards disable the alarm by
entering the security code.
Figure 2: An example Use Case Model
The Benefits of Use Cases
Use cases have become extremely popular
since the publication of Object-Oriented Software Engineering: A Use
Case Driven Approach in 1992. They have been added to numerous
object-oriented development methods (e.g., Booch, Firesmith, Rumbaugh)
because they offer many important advantages, including the following:
As a user-centered technique, use cases
help ensure that the correct system is developed by capturing the
requirements from the user's point of view.
Use cases are a powerful technique for
the elicitation and documentation of blackbox functional
requirements.
Because they are written in natural
language, use cases are easy to understand and provide an excellent way
for communicating with customers and users. Although computer-aided
software engineering (CASE) tools are useful for drawing the
corresponding interaction diagrams, use cases themselves require
remarkably little tool support.
Use cases can help manage the complexity
of large projects by decomposing the problem into major functions (i.e.,
use cases) and by specifying applications from the users' perspective.
Because they typically involve the
collaboration of multiple objects and classes, use cases help provide
the rationale for the messages that glue the objects and classes
together. Use cases also provide an alternative to the overemphasis
of traditional object-oriented development methods on such static
architecture issues as inheritance and the identification of objects and
classes.
Use cases have emphasized the use of
lower-level scenarios, thereby indirectly supporting Booch's important
concept of mechanisms, a kind of pattern that captures how "objects
collaborate to provide some behavior that satisfies a requirement of the
problem." [7]
Use cases provide a good basis for the
verification of the higher-level models (via role playing) and for the
validation of the functional requirements (via acceptance testing)
see Note 2.
Use cases provide an objective means of
project tracking in which earned value can be defined in terms of use
cases implemented, tested, and delivered.
Use cases can form the foundation on
which to specify end-to-end timing requirements for real-time
applications.
The Dangers of Misusing Use Cases
Because of their many important advantages
and extreme popularity, use cases have become a fundamental part of object
technology and have been incorporated in one form or another into most
major object-oriented development methods. In the rush to jump onto the
use case bandwagon, use cases have been perceived by some as either a
panacea or as an end in-and-of themselves. Unfortunately, this has often
led to the uncritical acceptance of use cases without any examination of
their numerous limitations and ample opportunities they offer for misuse.
The following provides an overview of the major risks associated with use
cases:
Use cases are not
object-oriented. Each use case captures a major functional abstraction
that can cause the numerous problems with functional decomposition that
object technology was to avoid. These problems include:
The functional nature of use cases
naturally leads to the functional decomposition of a system in terms
of concrete and abstract use cases that are related by extends and
uses associations. Each individual use case involves different
features of multiple objects and classes, and each individual object
or class is often involved in the implementation of multiple use
cases. Therefore, any decomposition based on use cases scatters the
features of the objects and classes among the individual use cases. On
large projects, different use cases are often assigned to different
teams of developers or to different builds and releases. Because the
use cases do not map one-to-one to the objects and classes, these
teams can easily design and code multiple, redundant, partial variants
of the same classes, producing a corresponding decrease in
productivity, reuse, and maintainability. This scattering of objects
to use cases leads to the Humpty Dumpty effect, in which all the kings
designers and all the king's coders are unlikely to put the objects
and classes back together again without a massive expenditure of time
and effort.
The use case model and the object
model belong to different paradigms (i.e., functional and
object-oriented) and therefore use different concepts, terminology,
techniques, and notations. The simple structure of the use case model
does not clearly map to the network structure of the object model with
its collaborating objects and classes. The requirements trace from the
use cases to the objects and classes is also not one-to-one. These
mappings are informal and somewhat arbitrary, providing little
guidance to the designer as to the identification of objects, classes,
and their interactions. The situation is clearly reminiscent of the
large semantic gap that existed between the data flow diagrams
(network) of structured analysis and the structure charts (hierarchy)
of structured design. The use of the single object paradigm was
supposed to avoid this problem.
Another potential problem with use
case modeling is knowing when to stop. When one is building a
non-trivial application, there are often a great number of use cases
that can produce an essentially infinite number of usage scenarios,
especially with today's graphical user interfaces and event driven
systems. How many use cases are required to adequately specify a
non-trivial, real-world application? As object technology is applied
to ever increasingly complex projects, the simple examples and
techniques of the text books often have trouble scaling up. The use of
concurrency and distributed architectures often means that the order
of the interactions between the system and its environment is
potentially infinite. Too few use cases result in an inadequate
specification, while too many use cases leads to functional
decomposition and the scattering of objects and classes to the four
winds. Often, systems and software engineers must often limit their
analysis to the most obvious or important scenarios and hope that
their analysis generalizes to all use cases.
Although use cases are functional
abstractions, use case modeling typically does not yet apply all of
the traditional techniques that are useful for analyzing and designing
functional abstractions. Most current techniques do not easily handle
the existence of branches and loops in the logic of a use case.
Interaction diagrams are primarily oriented towards a simple, linear
sequence of interactions between the actors and the major classes of
the system. The use of abstract use cases and either extends or
uses associations to solve this problem only exacerbates the
functional decomposition problem. Some approach similar to that of the
basis paths of structured testing would clearly help determine the
adequacy of the use case model, but such an approach is as yet not
available to the typical developer. Most techniques do not address the
issues of concurrency and the different types of messages that result.
As illustrated in [4, 6], the
concepts of preconditions, postconditions, invariants, and triggers
should also be added to better analyze and specify use cases.
Being created at the highest level of
abstraction before objects and classes have been identified, use cases
ignore the encapsulation of attributes and operations into objects.
Use cases therefore typically ignore issues of state modeling that
clearly impact the applicability of some use cases. Any required
ordering of use cases is ignored, and should be captured using some
variation of Firesmith's scenario lifecycle [6] or
Fusion's event lifecycle [8]. The basic ideas and
techniques of use cases should also be applied to Booch mechanisms
[7] and integration testing, but adequate
extensions have yet to be published.
Another major problem with use case
modeling is the lack of formality in the definitions of the terms use
case, actor, extends, and uses. Similarly, the specification of
individual use cases in natural languages such as English provides ample
room for miscommunication and misunderstandings. Use cases provide a
much less formal specification of their instances (i.e., individual
usage scenarios) than do classes of objects. Whereas the inheritance
relationship between classes of objects is well-defined and has been
automated by compilers, the 'inheritance' and 'delegation' relationships
provided by extends and uses associations are much less well defined.
While everything may seem clear that the highest level of abstraction,
the translation of use cases into design and code at lower levels of
abstraction is based on informal human understanding of what must be
done. This also causes problems when it comes to using use cases for the
specification of acceptance tests, because the criteria for passing
those tests may not be adequately defined.
Another major problem corresponds to the
archetypical subsystem architecture that can result from blindly using
use cases. Several examples in books and papers have consisted of a
single functional control object representing the logic of an individual
use case and several dumb entity objects controlled by the controller
object. They also may included an interface object for each actor
involved with the use case. Such an architecture typically exhibits poor
encapsulation, excessive coupling, and an inadequate distribution of the
intelligence of the application among the classes. Such architectures
are less maintainable than more object-oriented architectures.
Use cases are defined in terms of
interactions between one or more actors and the system to be developed.
However, all systems do not have actors and systems may include
signification functionality that is not a reaction to an actor's input.
Embedded systems may perform major control functions without significant
user input. Concurrent objects and classes need not passively wait for
incoming messages to react. They may instead proactively make decisions
based on results derived from polling terminators. Traditional use case
modeling seems less appropriate for such applications.
Finally, the use of use cases as the
foundation of incremental development and project tracking has its
limitations. Basing increments on functional use cases threatens to
cause the same problems with basing builds on major system functions.
Instead of building complete classes, developers will tend to create
partial variants that require more iteration from build to build than is
necessary. In turn, this will unnecessarily increase the maintenance
costs of inheritance hierarchies. Basing earned value on the number of
use cases implemented may be misleading because all use cases may not be
of equal value to the user and because of the previously mentioned
problems due to functional decomposition and the scattering of partial
variant objects and classes among use cases.
CONCLUSION
What then should developers do? Use cases
clearly offer many important benefits and are powerful weapons that
probably should be in the arsenal of all software analysts, designers, and
testers. Unfortunately however, they are functional rather than
object-oriented and can significantly compromise the benefits of object
technology if blindly added at to the object-oriented development process.
Fortunately, the risks associated with use case modeling can be mitigated
through knowledge, training, and avoiding an over enthusiastic acceptance.
Use cases should be only one of several ways of capturing user
requirements. The model of objects, classes, and their semantic
relationships should be consistent with, but not totally driven by, the
use cases. Designers should beware of and minimize scattering the features
of a use case's objects and classes, and they should exercise great care
to avoid the creation of partial, redundant variants of classes,
especially on large projects involving multiple builds and releases. The
architectural guidelines of Rebecca Wirfs-Brock [9]
should be followed to avoid creating excessive functional controller
objects that dictate the behavior of dumb entity objects. Most
importantly, use cases should not be used as an excuse to revert back to
the bad old days of functional decomposition and functionally decomposed
requirements specifications.
Notes
Note 1--A use case typically involves
branching or looping and may depend on the state of the system and any
parameters of the interactions between actors and the system.
Note 2--Because a use case (class) is not
as specific as a usage scenario (instance), use cases may lack sufficient
formality and detail to supply adequate criteria for the passing of
acceptance tests.
BIBLIOGRAPHY
[1] Ivar Jacobson, Object-Oriented
Development in an Industrial Environment, Proceedings of OOPSLA´87,
SIGPLAN Notices, Vol. 22, No. 12, pages 183-191, 1987.
[2] Ivar Jacobson, Magnus Christerson,
Patrik Jonsson, and Gunnar Övergaard, Object-Oriented Software
Engineering: A Use Case Driven Approach, Addison-Wesley, Wokingham,
England, 1992.
[3] Ivar Jacobson, Maria Ericsson, and
Agneta Jacobson, The Object Advantage: Business Process Re-engineering
with Object Technology, Addison-Wesley, Wokingham, England, 1995.
[4] James Rumbaugh, "Getting Started: Using
Use Cases to Capture Requirements," Journal of Object-Oriented
Programming (JOOP), SIGS Publications, Vol. 7, No. 5, New York, New
York, September 1994, pages 8-12.
[5] Ivar Jacobson, "Basic Use-Case Modeling
(Continued)," Report on Object-Oriented Analysis and Design (ROAD),
SIGS Publications, Vol. 1, No. 3, New York, New York, September/October
1994, page 7.
[6] Donald G. Firesmith, "Modeling the
Dynamic Behavior of Systems, Mechanisms, and Classes with Scenarios,"
Report on Object-Oriented Analysis and Design (ROAD), SIGS
Publications, Vol. 1, No. 2, New York, New York, July/August 1994, pages
32-36.
[7] Grady Booch, Object-Oriented
Analysis and Design with Applications, The Benjamin/Cummings
Publishing Company, Redwood City, California, 1994, page 515.
[8] Derek Coleman, Patrick Arnold,
Stephanie Bodoff, Chris Dollin, Helena Gilchrist, Fiona Hayes, and Paul
Jeremaes, Object-Oriented Development: The Fusion Method, Prentice
Hall, Englewood Cliffs, NJ, 1994.
[9] Rebecca Wirfs-Brock, Brian Wilkerson,
and Lauren Wiener, Designing Object-Oriented Software, Prentice
Hall, Englewood Cliffs, NJ, 1990.
Knowledge Systems Corporation is a
member of the Smalltalk Webring.