Software Enginering
Software Enginering
Bonga University
College of Engineering and Technology
Department of Computer Science
January 2023
Bonga University, Ethiopia
CHAPTER-1
An Overview of Object-Oriented Systems Development
INTRODUCTION:
A software development methodology is a series of processes that lead to the development of
an application. A software development activity consists of:
• System analysis
• Modeling
• Design
• Implementation
• Testing and
• Maintenance
Software process: It describes how the work is to be carried out to achieve the original goal
based on the system requirement. Each process consists of number of steps and rules that should
be performed during development.
TWO ORTHOGONAL VIEWS OF SOFTWARE:
• Traditional technique
• Object oriented methodologies
Programs=Algorithm + Data Structures
➢ Object orientation emerged during the 1970s, particularly in programming languages like
Simula, Smalltalk, Eiffel and, later, C++ and Java
➢ Now there are also object-oriented analysis and design techniques and tools (e.g.UML),
databases and development
➢ Object-orientation attempts to unify many aspects of the systems analysis and design
process that were disparate before
➢ Important aspect of OO ==> potential for re-use of development work when OO
techniques are used
➢ Object-orientation has also been argued to be a more natural approach than other
Techniques
OO CONCEPTS
behavior) and
applicability of its instances
Review of objects:
The object-oriented system development makes software development easier and more natural by
raising the level of abstraction to the point where applications can be implemented. The name
object was chosen because “everyone knows what is an object is ”. The real question is “what do
objects have to do with system development” rather that “what is an object?”
Object:
A car is an object a real-world entity, identifiably separate from its surroundings. A car
has a well-defined set of attributes in relation to other object.
Attributes:
➢ Data of an object.
➢ Properties of an object.
Methods:
➢ Procedures of an object.or
➢ Behaviour of an object.
The term object was for formal utilized in the similar language. The term object means a
combination or data and logic that represent some real-world entity.
When developing an object oriented applications, two basic questions arise
➢ What objects does the application need?
➢ What functionality should those objects have?
Programming in an object-oriented system consists of adding new kind of objects to the system
and defining how they behave. The new object classes can be built from the objects supplied by
the object-oriented system.
Object state and properties (Attributes):
Properties represent the state of an object. In an object oriented methods we want to refer
to the description of these properties rather than how they are represented in a particular
programming language.
For example:
An employee object knows how to compute salary. To compute an employee salary, all that is
required is to send the compute payroll message to the employee object.So the simplification of
code simplifies application development and maintenance.
Objects Respond to Messages:
The capability of an object’s is determined by the methods defined for it. To do an operation, a
message is sent to an object. Objects represented to messages according to the methods defined
in its class.
For example:
When we press on the brake pedal of a car, we send a stop message to the car object. The car object
knows how to respond to the stop message since brake have been designed with specialized parts
such as break pads and drums precisely respond to that message.
Different object can respond to the same message in different ways. The car, motorcycle and
bicycle will all respond to a stop message, but the actual operations performed are object specific.It
is the receiver’s responsibility to respond to a message in an appropriate manner. This gives the
great deal or flexibility, since different object can respond to the same message in different ways.
This is known as polymorphism.
Class Hierarchy:
An object-oriented system organizes classes into a subclass super class hierarchy. The properties
and behaviours are used as the basis for making distinctions between classes are at the top and
more specific are at the bottom of the class hierarchy. The family car is the subclass of car. A
subclass inherits all the properties and methods defined in its super class.
Inheritance:
It is the property of object-oriented systems
that allow objects to be built from other
objects. Inheritance allows explicitly taking
advantage of the commonality of objects
when constructing new classes. Inheritance
is a relationship between classes where one
class is the parent class of another (derived)
class. The derived class holds the properties
and behaviour of base class in addition to the
properties and behaviour of derived class.
Dynamic Inheritance:
Dynamic inheritance allows objects to change and evolve over time. Since base classes provide
properties and attributes for objects, hanging base classes changes the properties and attributes of
a class.
Example:
A window objects change to icon and basic again. When we double click the folder the contents
will be displayed in a window and when close it, changes back to icon. It involves changing a base
class between a windows class and icon class.
Multiple Inheritances:
Some object-oriented systems permit a class .
to inherit its state (attributes) and behaviour
from more than one super class. This kind or
inheritance is referred to as multiple
inheritances.
For example:
Utility vehicle inherits the attributes fromthe
Car and Truck classes
A pilot “can fly” planes. The inverse of can fly is “is flown by “. Plane “is flown by” pilot
Cardinality:
It specifies how many instances of one class may relate to a single instance of an associated class.
Cardinality constrains the number of related objects and often is described as being “one” or
“many”.
Consumer-producer association:
A special form or association is a consumer-producer relationship, also known as a client-server
association (or) a use relationship. It can be viewed as one-way interaction. One object requests
the service or another object. The object that makes the request is the consumer or client and the
object that receives the request and provides the service is the producer (or) server
Aggregations:
All objects, except the most basic ones, are composed of and may contain other objects. Breaking
down objects in to the objects from which they are composed is de composition. This is possible
because an objects attributes need not be simple data fields, attributes can reference other objects.
Since each object has an identity, one object can refer to other objects. This is known as
aggregation. The car object is an aggregation of other objects such as engine, seat and wheel
objects.
Things
Things are the most important building blocks of UML. Things can be −
• Structural
• Behavioral
• Grouping
• Annotational
Structural Things
Structural things define the static part of the model. They represent the physical and conceptual
elements. Following are the brief descriptions of the structural things.
Class − Class represents a set of objects having similar responsibilities.
Interface − Interface defines a set of operations, which specify the responsibility of a class.
Use case −Use case represents a set of actions performed by a system for a specific goal.
Node − A node can be defined as a physical element that exists at run time.
Behavioral Things
A behavioral thing consists of the dynamic parts of UML models. Following are the behavioral
things −
Interaction − Interaction is defined as a behavior that consists of a group of messages
exchanged among elements to accomplish a specific task.
State machine − State machine is useful when the state of an object in its life cycle is important. It
defines the sequence of states an object goes through in response to events. Events are external
factors responsible for state change
Grouping Things
Grouping things can be defined as a mechanism to group elements of a UML model together.
There is only one grouping thing available −
Package − Package is the only one grouping thing available for gathering structural and
behavioral things.
Annotational Things
Annotational things can be defined as a mechanism to capture remarks, descriptions, and
comments of UML model elements. Note - It is the only one Annotational thing available. A note
is used to render comments, constraints, etc. of an UML element.
Relationship
Relationship is another most important building block of UML. It shows how the elements are
associated with each other and this association describes the functionality of an application.
There are four kinds of relationships available.
Dependency
Dependency is a relationship between two things in which change in one element also affects the
other.
Association
Association is basically a set of links that connects the elements of a UML model. It also
describes how many objects are taking part in that relationship.
Generalization
Generalization can be defined as a relationship which connects a specialized element with a
generalized element. It basically describes the inheritance relationship in the world of objects.
Realization
Realization can be defined as a relationship in which two elements are connected. One element
describes some responsibility, which is not implemented and the other one implements them. This
relationship exists in case of interfaces.
UML Diagrams
UML diagrams are the ultimate output of the entire discussion. All the elements, relationships
are used to make a complete UML diagram and the diagram represents a system.
The visual effect of the UML diagram is the most important part of the entire process. All theother
elements are used to make it complete.
UML includes the following nine diagrams, the details of which are described in the subsequent
chapters.
• Class diagram
• Object diagram
• Use case diagram
• Sequence diagram
• Collaboration diagram
• Activity diagram
• Statechart diagram
• Deployment diagram
• Component diagram
UML - Architecture
Any real-world system is used by different users. The users can be developers, testers, business
people, analysts, and many more. Hence, before designing a system, the architecture is made with
different perspectives in mind. The most important part is to visualize the system from the
perspective of different viewers. The better we understand the better we can build the system.
UML plays an important role in defining different perspectives of a system. These perspectives are
−
• Design
• Implementation
• Process
• Deployment
The center is the Use Case view which connects all these four. A Use Case represents the
functionality of the system. Hence, other perspectives are connected with use case.
Design of a system consists of classes, interfaces, and collaboration. UML provides class
diagram, object diagram to support this.
Implementation defines the components assembled together to make a complete physicalsystem.
UML component diagram is used to support the implementation perspective.
Process defines the flow of the system. Hence, the same elements as used in Design are also
used to support this perspective.
Deployment represents the physical nodes of the system that forms the hardware. UML
deployment diagram is used to support this perspective.
UML - Modeling Types
It is very important to distinguish between the UML model. Different diagrams are used for
different types of UML modeling. There are three important types of UML modeling.
Structural Modeling
Structural modeling captures the static features of a system. They consist of the following −
• Classes diagrams
• Objects diagrams
• Deployment diagrams
• Package diagrams
• Composite structure diagram
• Component diagram
Structural model represents the framework for the system and this framework is the place where all
other components exist. Hence, the class diagram, component diagram and deployment diagrams
are part of structural modeling. They all represent the elements and the mechanism to assemble
them.
The structural model never describes the dynamic behavior of the system. Class diagram is the most
widely used structural diagram.
Behavioral Modeling
Behavioral model describes the interaction in the system. It represents the interaction among the
structural diagrams. Behavioral modeling shows the dynamic nature of the system. They consist of
the following −
• Activity diagrams
• Interaction diagrams
• Use case diagrams
All the above show the dynamic sequence of flow in a system.
Architectural Modeling
Architectural model represents the overall framework of the system. It contains both structural and
behavioral elements of the system. Architectural model can be defined as the blueprint of the entire
system. Package diagram comes under architectural modeling.
UML - Basic Notations
UML is popular for its diagrammatic notations. We all know that UML is for visualizing, specifying,
constructing and documenting the components of software and non-software systems. Hence,
visualization is the most important part which needs to be understood and remembered.
UML notations are the most important elements in modeling. Efficient and appropriate use of
notations is very important for making a complete and meaningful model. The model is useless,
unless its purpose is depicted properly.
Hence, learning notations should be emphasized from the very beginning. Different notations are
available for things and relationships. UML diagrams are made using the notations of things and
relationships. Extensibility is another important feature which makes UML more powerful and
flexible.
The chapter describes basic UML notations in detail. This is just an extension to the UML building
block section discussed in Chapter Two.
Structural Things
Graphical notations used in structural things are most widely used in UML. These are considered as
the nouns of UML models. Following are the list of structural things.
• Classes
• Object
• Interface
• Collaboration
• Use case
• Active classes
• Components
• Nodes
Class Notation
UML class is represented by the following figure. The diagram is divided into four parts.
• The top section is used to name the class.
• The second one is used to show the attributes of the class.
• The third section is used to describe the operations performed by the class.
• The fourth section is optional to show any additional components.
Classes are used to represent objects. Objects can be anything having properties and
responsibility.
Object Notation
The object is represented in the same way as the class. The only difference is the name which is
underlined as shown in the following figure.
As the object is an actual implementation of a class, which is known as the instance of a class.
Hence, it has the same usage as the class.
Interface Notation
Interface is represented by a circle as shown in the following figure. It has a name which is
generally written below the circle.
Interface is used to describe the functionality without implementation. Interface is just like a
template where you define different functions, not the implementation. When a class implementsthe
interface, it also implements the functionality as per requirement.
Collaboration Notation
Collaboration is represented by a dotted eclipse as shown in the following figure. It has a name
written inside the eclipse.
An actor is used in a use case diagram to describe the internal or external entities.
Initial State Notation
Initial state is defined to show the start of a process. This notation is used in almost all diagrams.
The usage of Initial State Notation is to show the starting point of a process.
Final State Notation
Final state is used to show the end of a process. This notation is also used in almost all diagramsto
describe the end.
The usage of Final State Notation is to show the termination point of a process.
Active Class Notation
Active class looks similar to a class with a solid border. Active class is generally used to describe
the concurrent behavior of a system.
Component is used to represent any part of a system for which UML diagrams are made.
Node Notation
A node in UML is represented by a square box as shown in the following figure with a name. Anode
represents the physical component of the system.
Node is used to represent the physical part of a system such as the server, network, etc.
Behavioral Things
Dynamic parts are one of the most important elements in UML. UML has a set of powerful features
to represent the dynamic part of software and non-software systems. These features include
interactions and state machines.
Interactions can be of two types −
• Sequential (Represented by sequence diagram)
• Collaborative (Represented by collaboration diagram)
Interaction Notation
Interaction is basically a message exchange between two UML components. The following diagram
represents different notations used in an interaction.
State machine is used to describe different states of a system component. The state can be active,
idle, or any other depending upon the situation.
Grouping Things
Organizing the UML models is one of the most important aspects of the design. In UML, there is
only one element available for grouping and that is package.
Package Notation
Package notation is shown in the following figure and is used to wrap the components of a
system.
Annotational Things
In any diagram, explanation of different elements and their functionalities are very important.
Hence, UML has notes notation to support this requirement.
Note Notation
This notation is shown in the following figure. These notations are used to provide necessary
information of a system.
Relationships
A model is not complete unless the relationships between elements are described properly. The
Relationship gives a proper meaning to a UML model. Following are the different types of
relationships available in UML.
• Dependency
• Association
• Generalization
• Extensibility
Dependency Notation
Dependency is an important aspect in UML elements. It describes the dependent elements and
the direction of dependency.
Dependency is represented by a dotted arrow as shown in the following figure. The arrow head
represents the independent element and the other end represents the dependent element.
Generalization Notation
Generalization describes the inheritance relationship of the object-oriented world. It is a parent
and child relationship.
Generalization is represented by an arrow with a hollow arrow head as shown in the following
figure. One end represents the parent element and the other end represents the child element.
Extensibility notations are used to enhance the power of the language. It is basically additional
elements used to represent some extra behavior of the system. These extra behaviors are not covered
by the standard available notations.
UML - Standard Diagrams
n the previous chapters, we have discussed about the building blocks and other necessary elements
of UML. Now we need to understand where to use those elements.
The elements are like components which can be associated in different ways to make a complete
UML picture, which is known as diagram. Thus, it is very important to understand the different
diagrams to implement the knowledge in real-life systems.
Any complex system is best understood by making some kind of diagrams or pictures. These
diagrams have a better impact on our understanding. If we look around, we will realize that the
diagrams are not a new concept but it is used widely in different forms in different industries.
We prepare UML diagrams to understand the system in a better and simple way. A single diagram
is not enough to cover all the aspects of the system. UML defines various kinds of diagrams to cover
most of the aspects of a system.
You can also create your own set of diagrams to meet your requirements. Diagrams are generally
made in an incremental and iterative way.
There are two broad categories of diagrams and they are again divided into subcategories −
• Structural Diagrams
• Behavioral Diagrams
Structural Diagrams
The structural diagrams represent the static aspect of the system. These static aspects represent
those parts of a diagram, which forms the main structure and are therefore stable.
These static parts are represented by classes, interfaces, objects, components, and nodes. The
four structural diagrams are −
• Class diagram
• Object diagram
• Component diagram
• Deployment diagram
Class Diagram
Class diagrams are the most common diagrams used in UML. Class diagram consists of classes,
interfaces, associations, and collaboration. Class diagrams basically represent the object-oriented
view of a system, which is static in nature.
Active class is used in a class diagram to represent the concurrency of the system.
Class diagram represents the object orientation of a system. Hence, it is generally used for
development purpose. This is the most widely used diagram at the time of system construction.
Object Diagram
Object diagrams can be described as an instance of class diagram. Thus, these diagrams are more
close to real-life scenarios where we implement a system.
Object diagrams are a set of objects and their relationship is just like class diagrams. They also
represent the static view of the system.
The usage of object diagrams is similar to class diagrams but they are used to build prototype ofa
system from a practical perspective.
Component Diagram
Component diagrams represent a set of components and their relationships. These components
consist of classes, interfaces, or collaborations. Component diagrams represent the implementation
view of a system.
During the design phase, software artifacts (classes, interfaces, etc.) of a system are arranged in
different groups depending upon their relationship. Now, these groups are known as components.
Finally, it can be said component diagrams are used to visualize the implementation.
Deployment Diagram
Deployment diagrams are a set of nodes and their relationships. These nodes are physical entities
where the components are deployed.
Deployment diagrams are used for visualizing the deployment view of a system. This is generally
used by the deployment team.
Note − If the above descriptions and usages are observed carefully then it is very clear that all the
diagrams have some relationship with one another. Component diagrams are dependent upon the
classes, interfaces, etc. which are part of class/object diagram. Again, the deployment diagram is
dependent upon the components, which are used to make component diagrams.
Behavioral Diagrams
Any system can have two aspects, static and dynamic. So, a model is considered as complete when
both the aspects are fully covered.
Behavioral diagrams basically capture the dynamic aspect of a system. Dynamic aspect can be
further described as the changing/moving parts of a system.
Class diagram describes the attributes and operations of a class and also the constraints imposed on
the system. The class diagrams are widely used in the modeling of objectoriented systems because
they are the only UML diagrams, which can be mapped directly with object-oriented languages.
Class diagram shows a collection of classes, interfaces, associations, collaborations, and constraints.
It is also known as a structural diagram.
Purpose of Class Diagrams
The purpose of class diagram is to model the static view of an application. Class diagrams are the
only diagrams which can be directly mapped with object-oriented languages and thus widely used
at the time of construction.
UML diagrams like activity diagram, sequence diagram can only give the sequence flow of the
application, however class diagram is a bit different. It is the most popular UML diagram in the
coder community.
The purpose of the class diagram can be summarized as −
• Analysis and design of the static view of an application.
• Describe responsibilities of a system.
• Base for component and deployment diagrams.
• Forward and reverse engineering.
How to Draw a Class Diagram?
Class diagrams are the most popular UML diagrams used for construction of software applications.
It is very important to learn the drawing procedure of class diagram.
Class diagrams have a lot of properties to consider while drawing but here the diagram will be
considered from a top level view.
Class diagram is basically a graphical representation of the static view of the system and represents
different aspects of the application. A collection of class diagrams represent the wholesystem.
The following points should be remembered while drawing a class diagram −
• The name of the class diagram should be meaningful to describe the aspect of the system.
• Each element and their relationships should be identified in advance.
• Responsibility (attributes and methods) of each class should be clearly identified
• For each class, minimum number of properties should be specified, as unnecessary
properties will make the diagram complicated.
• Use notes whenever required to describe some aspect of the diagram. At the end of the
drawing it should be understandable to the developer/coder.
• Finally, before making the final version, the diagram should be drawn on plain paper and
reworked as many times as possible to make it correct.
The following diagram is an example of an Order System of an application. It describes a
particular aspect of the entire application.
• First of all, Order and Customer are identified as the two elements of the system. They
have a one-to-many relationship because a customer can have multiple orders.
• Order class is an abstract class and it has two concrete classes (inheritance relationship)
SpecialOrder and NormalOrder.
• The two inherited classes have all the properties as the Order class. In addition, they have
additional functions like dispatch () and receive ().
The following class diagram has been drawn considering all the points mentioned above.
The difference is that a class diagram represents an abstract model consisting of classes and their
relationships. However, an object diagram represents an instance at a particular moment, which is
concrete in nature.
It means the object diagram is closer to the actual system behavior. The purpose is to capture the
static view of a system at a particular moment.
The purpose of the object diagram can be summarized as −
• Forward and reverse engineering.
• Object relationships of a system
• Static view of an interaction.
• Understand object behaviour and their relationship from practical perspective
How to Draw an Object Diagram?
We have already discussed that an object diagram is an instance of a class diagram. It implies that
an object diagram consists of instances of things used in a class diagram.
So both diagrams are made of same basic elements but in different form. In class diagram elements
are in abstract form to represent the blue print and in object diagram the elements are in concrete
form to represent the real world object.
To capture a particular system, numbers of class diagrams are limited. However, if we consider
object diagrams then we can have unlimited number of instances, which are unique in nature. Only
those instances are considered, which have an impact on the system.
From the above discussion, it is clear that a single object diagram cannot capture all the necessary
instances or rather cannot specify all the objects of a system. Hence, the solution is −
• First, analyze the system and decide which instances have important data and association.
• Second, consider only those instances, which will cover the functionality.
• Third, make some optimization as the number of instances are unlimited.
Before drawing an object diagram, the following things should be remembered and understood
clearly −
• Object diagrams consist of objects.
• The link in object diagram is used to connect objects.
• Objects and links are the two elements used to construct an object diagram.
After this, the following things are to be decided before starting the construction of the diagram
−
• The object diagram should have a meaningful name to indicate its purpose.
• The most important elements are to be identified.
• The association among objects should be clarified.
• Values of different elements need to be captured to include in the object diagram.
• Add proper notes at points where more clarity is required.
The following diagram is an example of an object diagram. It represents the Order management
system which we have discussed in the chapter Class Diagram. The following diagram is an instance
of the system at a particular time of purchase. It has the following objects.
• Customer
• Order
• SpecialOrder
• NormalOrder
Now the customer object (C) is associated with three order objects (O1, O2, and O3). These
order objects are associated with special order and normal order objects (S1, S2, and N1). The
customer has the following three orders with different numbers (12, 32 and 40) for the particular
time considered.
The customer can increase the number of orders in future and in that scenario the object diagram
will reflect that. If order, special order, and normal order objects are observed then you will find
that they have some values.
For orders, the values are 12, 32, and 40 which implies that the objects have these values for a
particular moment (here the particular time when the purchase is made is considered as the moment)
when the instance is captured
The same is true for special order and normal order objects which have number of orders as 20, 30,
and 60. If a different time of purchase is considered, then these values will change accordingly.
The following object diagram has been drawn considering all the points mentioned above
These internal and external agents are known as actors. Use case diagrams consists of actors, use
cases and their relationships. The diagram is used to model the system/subsystem of an application.
A single use case diagram captures a particular functionality of a system.
Hence to model the entire system, a number of use case diagrams are used.
Purpose of Use Case Diagrams
The purpose of use case diagram is to capture the dynamic aspect of a system. However, this
definition is too generic to describe the purpose, as other four diagrams (activity, sequence,
collaboration, and Statechart) also have the same purpose. We will look into some specific purpose,
which will distinguish it from other four diagrams.
Use case diagrams are used to gather the requirements of a system including internal and external
influences. These requirements are mostly design requirements. Hence, when a system is analyzed
to gather its functionalities, use cases are prepared and actors are identified.
When the initial task is complete, use case diagrams are modelled to present the outside view.In
brief, the purposes of use case diagrams can be said to be as follows −
• Used to gather the requirements of a system.
• Used to get an outside view of a system.
• Identify the external and internal factors influencing the system.
• Show the interaction among the requirements are actors.
How to Draw a Use Case Diagram?
Use case diagrams are considered for high level requirement analysis of a system. When the
requirements of a system are analyzed, the functionalities are captured in use cases.
We can say that use cases are nothing but the system functionalities written in an organized manner.
The second thing which is relevant to use cases are the actors. Actors can be defined as something
that interacts with the system.
Actors can be a human user, some internal applications, or may be some external applications. When
we are planning to draw a use case diagram, we should have the following items identified.
• Functionalities to be represented as use case
• Actors
• Relationships among the use cases and actors.
Use case diagrams are drawn to capture the functional requirements of a system. After identifying
the above items, we have to use the following guidelines to draw an efficient use casediagram
• The name of a use case is very important. The name should be chosen in such a way so
that it can identify the functionalities performed.
• Give a suitable name for actors.
• Show relationships and dependencies clearly in the diagram.
• Do not try to include all types of relationships, as the main purpose of the diagram is to
identify the requirements.
• Use notes whenever required to clarify some important points.
Following is a sample use case diagram representing the order management system. Hence, if we
look into the diagram then we will find three use cases (Order, SpecialOrder, and NormalOrder)
and one actor which is the customer.
The SpecialOrder and NormalOrder use cases are extended from Order use case. Hence, they have
extended relationship. Another important point is to identify the system boundary, which is
shown in the picture. The actor Customer lies outside the system as it is an external user of the
system.
This interactive behavior is represented in UML by two diagrams known as Sequence diagram
and Collaboration diagram. The basic purpose of both the diagrams are similar.
Sequence diagram emphasizes on time sequence of messages and collaboration diagram emphasizes
on the structural organization of the objects that send and receive messages.
Purpose of Interaction Diagrams
The purpose of interaction diagrams is to visualize the interactive behavior of the system.
Visualizing the interaction is a difficult task. Hence, the solution is to use different types of models
to capture the different aspects of the interaction.
Sequence and collaboration diagrams are used to capture the dynamic nature but from a different
angle.
The purpose of interaction diagram is −
• To capture the dynamic behaviour of a system.
• To describe the message flow in the system.
• To describe the structural organization of the objects.
• To describe the interaction among objects.
How to Draw an Interaction Diagram?
As we have already discussed, the purpose of interaction diagrams is to capture the dynamic aspect
of a system. So to capture the dynamic aspect, we need to understand what a dynamic aspect is and
how it is visualized. Dynamic aspect can be defined as the snapshot of the running system at a
particular moment
We have two types of interaction diagrams in UML. One is the sequence diagram and the other is
the collaboration diagram. The sequence diagram captures the time sequence of the message flow
from one object to another and the collaboration diagram describes the organization of objects in a
system taking part in the message flow.
Following things are to be identified clearly before drawing the interaction diagram
• Objects taking part in the interaction.
• Message flows among the objects.
• The sequence in which the messages are flowing.
• Object organization.
Following are two interaction diagrams modeling the order management system. The first diagram
is a sequence diagram and the second is a collaboration diagram
The Sequence Diagram
The sequence diagram has four objects (Customer, Order, SpecialOrder and NormalOrder).
The following diagram shows the message sequence for SpecialOrder object and the same can be
used in case of NormalOrder object. It is important to understand the time sequence of message
flows. The message flow is nothing but a method call of an object.
The first call is sendOrder () which is a method of Order object. The next call is confirm () which
is a method of SpecialOrder object and the last call is Dispatch () which is a method of
SpecialOrder object. The following diagram mainly describes the method calls from one object
to another, and this is also the actual scenario when the system is running.
Statechart diagrams are used to model the states and also the events operating on the system. When
implementing a system, it is very important to clarify different states of an object during its life
time and Statechart diagrams are used for this purpose. When these states and events are identified,
they are used to model it and these models are used during the implementation of the system.
If we look into the practical implementation of Statechart diagram, then it is mainly used to analyze
the object states influenced by events. This analysis is helpful to understand the system behavior
during its execution.
The main usage can be described as −
• To model the object states of a system.
• To model the reactive system. Reactive system consists of reactive objects.
• To identify the events responsible for state changes.
• Forward and reverse engineering.
UML - Activity Diagrams
Activity diagram is another important diagram in UML to describe the dynamic aspects of the
system.
Activity diagram is basically a flowchart to represent the flow from one activity to another activity.
The activity can be described as an operation of the system.
The control flow is drawn from one operation to another. This flow can be sequential, branched, or
concurrent. Activity diagrams deal with all type of flow control by using different elements such as
fork, join, etc
Purpose of Activity Diagrams
The basic purposes of activity diagrams is similar to other four diagrams. It captures the dynamic
behavior of the system. Other four diagrams are used to show the message flow from one object to
another but activity diagram is used to show message flow from one activity to another.
Activity is a particular operation of the system. Activity diagrams are not only used for visualizing
the dynamic nature of a system, but they are also used to construct the executable system by using
forward and reverse engineering techniques. The only missing thing in the activity diagram is the
message part.
It does not show any message flow from one activity to another. Activity diagram is sometimes
considered as the flowchart. Although the diagrams look like a flowchart, they are not. It shows
different flows such as parallel, branched, concurrent, and single.
The purpose of an activity diagram can be described as −
• Draw the activity flow of a system.
• Describe the sequence from one activity to another.
• Describe the parallel, branched and concurrent flow of the system.
How to Draw an Activity Diagram?
Activity diagrams are mainly used as a flowchart that consists of activities performed by the system.
Activity diagrams are not exactly flowcharts as they have some additional capabilities. These
additional capabilities include branching, parallel flow, swimlane, etc.
Before drawing an activity diagram, we must have a clear understanding about the elements usedin
activity diagram. The main element of an activity diagram is the activity itself. An activity is a
function performed by the system. After identifying the activities, we need to understand how they
are associated with constraints and conditions.
Before drawing an activity diagram, we should identify the following elements −
• Activities
• Association
• Conditions
• Constraints
Once the above-mentioned parameters are identified, we need to make a mental layout of the
entire flow. This mental layout is then transformed into an activity diagram.
Following is an example of an activity diagram for order management system. In the diagram,
four activities are identified which are associated with conditions. One important point should be
clearly understood that an activity diagram cannot be exactly matched with the code. The activity
diagram is made to understand the flow of activities and is mainly used by the business users
Following diagram is drawn with the four main activities −
• Send order by the customer
• Receipt of the order
• Confirm the order
• Dispatch the order
After receiving the order request, condition checks are performed to check if it is normal or special
order. After the type of order is identified, dispatch activity is performed and that is marked as the
termination of the process.
level view of a system. This high level view is mainly for business users or any other person who
is not a technical person.
This diagram is used to model the activities which are nothing but business requirements. The
diagram has more impact on business understanding rather than on implementation details.
Activity diagram can be used for −
• Modeling work flow by using activities.
• Modeling business requirements.
• High level understanding of the system's functionalities.
• Investigating business requirements at a later stage.
UML - Component Diagrams
Component diagrams are different in terms of nature and behavior. Component diagrams are used
to model the physical aspects of a system. Now the question is, what are these physical aspects?
Physical aspects are the elements such as executables, libraries, files, documents, etc. which reside
in a node.
Component diagrams are used to visualize the organization and relationships among componentsin
a system. These diagrams are also used to make executable systems.
Purpose of Component Diagrams
Component diagram is a special kind of diagram in UML. The purpose is also different from all
other diagrams discussed so far. It does not describe the functionality of the system but it describes
the components used to make those functionalities.
Thus from that point of view, component diagrams are used to visualize the physical componentsin
a system. These components are libraries, packages, files, etc.
Component diagrams can also be described as a static implementation view of a system. Static
implementation represents the organization of the components at a particular moment.
A single component diagram cannot represent the entire system but a collection of diagrams is used
to represent the whole.
The purpose of the component diagram can be summarized as −
• Visualize the components of a system.
• Construct executables by using forward and reverse engineering.
• Describe the organization and relationships of the components.
How to Draw a Component Diagram?
Component diagrams are used to describe the physical artifacts of a system. This artifact includes
files, executables, libraries, etc
The purpose of this diagram is different. Component diagrams are used during the implementation
phase of an application. However, it is prepared well in advance to visualize the implementation
details.
Initially, the system is designed using different UML diagrams and then when the artifacts are ready,
component diagrams are used to get an idea of the implementation.
This diagram is very important as without it the application cannot be implemented efficiently. A
well-prepared component diagram is also important for other aspects such as application
performance, maintenance, etc.
Before drawing a component diagram, the following artifacts are to be identified clearly −
• Files used in the system.
• Libraries and other artifacts relevant to the application.
• Relationships among the artifacts.
After identifying the artifacts, the following points need to be kept in mind.
• Use a meaningful name to identify the component for which the diagram is to be drawn.
• Prepare a mental layout before producing the using tools.
• Use notes for clarifying important points.
Following is a component diagram for order management system. Here, the artifacts are files. The
diagram shows the files in the application and their relationships. In actual, the component diagram
also contains dlls, libraries, folders, etc.
In the following diagram, four files are identified and their relationships are produced. Component
diagram cannot be matched directly with other UML diagrams discussed so far as it is drawn for
completely different purpose.
The following component diagram has been drawn considering all the points mentioned above.
3.1 Introduction
A requirement is a feature that the system must have or a constraint that it must satisfy to be
accepted by the client. Requirements engineering aims at defining the requirements of the
system under construction. Requirements engineering includes two main activities;
requirements elicitation, which results in the specification of the system that the client
understands, and analysis, which results in an analysis model that the developers can
unambiguously interpret. Requirements elicitation is the more challenging of the two because
it requires the collaboration of several groups of participants with different backgrounds. On
the one hand, the client and the users are experts in their domain and have a general idea of
what the system should do, but they often have little experience in software development. On
the other hand, the developers have experience in building systems, but often have little
knowledge of the everyday environment of the users.
Scenarios and use cases provide tools for bridging this gap. A scenario describes an example
of system use in terms of a series of interactions between the user and the system. A use case
is an abstraction that describes a class of scenarios. Both scenarios and use cases are written
in natural language, a form that is understandable to the user.
Developers elicit requirements by observing and interviewing users. Developers first represent
the user’s current work processes as as-is scenarios, then develop visionary scenarios
describing the functionality to be provided by the future system. The client and users validate
the system description by reviewing the scenarios and by testing small prototypes provided by
the developers. As the definition of the system matures and stabilizes,developers and the client
agree on a requirements specification in the form of functional requirements, nonfunctional
requirements, use cases, and scenarios.
Requirements elicitation is about communication among developers, clients, and users to define
a new system. Failure to communicate and understand each others’ domains results ina system
that is difficult to use or that simply fails to support the user’s work. Errors introduced during
requirements elicitation are expensive to correct, as they are usually discovered late in the
process, often as late as delivery. Such errors include missing functionality that the system
should have supported, functionality that was incorrectly specified, user interfaces that are
misleading or unusable, and obsolete functionality. Requirements elicitation methods aim at
improving communication among developers, clients, and users. Developers construct a model
of the application domain by observing users in their environment. Developers select a
representation that is understandable by the clients and users (e.g., scenarios and use cases).
Developers validate the application domain model by constructing simple prototypes of the
user interface and collecting feedback from potentialusers. An example of a simple prototype
is the layout of a user interface with menu items and buttons. The potential user can manipulate
the menu items and buttons to get a feeling for the usage of the system, but there is no actual
response after buttons are clicked, because the required functionality is not implemented.
Requirements elicitation focuses on describing the purpose of the system. The client, the
developers, and the users identify a problem area and define a system that addresses the
problem. Such a definition is called a requirements specification and serves as a contract
between the client and the developers. The requirements specification is structured and
formalized during analysis (Next chapter, Analysis) to produce an analysis model (see Figure
3-1).
Figure 3-1: Products of requirements elicitation and analysis (UML activity diagram).
Requirements elicitation and analysis focus only on the user’s view of the system. For example,
the system functionality, the interaction between the user and the system, the errors that the
system can detect and handle, and the environmental conditions in which the system functions
are part of the requirements. The system structure, the implementation technology selected to
build the system, the system design, the development methodology, and other aspects not
directly visible to the user are not part of the requirements.
system with which the system interacts. For example, Figure 3-2 is an example of functional
requirements for SatWatch, a watch that resets itself without user intervention:
SatWatch is a wrist watch that displays the time based on its current location. SatWatch uses
GPS satellites (Global Positioning System) to determine its location and internal data structures
to convert this location into a time zone.
The information stored in SatWatch and its accuracy measuring time is such that the watch
owner never needs to reset the time. SatWatch adjusts the time and date displayed as the watch
owner crosses time zones and political boundaries. For this reason, SatWatch has no buttons
or controls available to the user.
SatWatch determines its location using GPS satellites and, as such, suffers from the same
limitations as all other GPS devices (e.g., inability to determine location at certain times of the
day in mountainous regions). During blackout periods, SatWatch assumes that it does not cross
a time zone or a political boundary. SatWatch corrects its time zone as soon as a blackout
period ends.
SatWatch has a two-line display showing, on the top line, the time (hour, minute, second,time
zone) and on the bottom line, the date (day, date, month, year). The display technology used is
such that the watch owner can see the time and date even under poor light conditions.
When political boundaries change, the watch owner may upgrade the software of the watch
using the WebifyWatch device (provided with the watch) and a personal computer connected
to the Internet.
The above functional requirements focus only on the possible interactions between SatWatch
and its external world (i.e., the watch owner, GPS, and WebifyWatch). The above description
does not focus on any of the implementation details (e.g., processor, language, display
technology).
The FURPS+ (Acronym using the first letter of the requirements categories: Functionality,
Usability, Reliability, Performance, and Supportability. The + indicates the additional
subcategories) provides the following categories of nonfunctional requirements:
• Usability is the ease with which a user can learn to operate, prepare inputs for, and
interpret outputs of a system or component. Usability requirements include, for
example, conventions adopted by the user interface, the scope of online help, and the
level of user documentation.
• Reliability is the ability of a system or component to perform its required functions
under stated conditions for a specified period of time. Reliability requirements include,
for example, an acceptable mean time to failure and the ability to detect specified faults
or to withstand specified security attacks.
The FURPS+ model provides additional categories of requirements typically also included
under the general label of nonfunctional requirements:
• Implementation requirements are constraints on the implementation of the system,
including the use of specific tools, programming languages, or hardware platforms.
• Interface requirements are constraints imposed by external systems, including legacy
systems and interchange formats.
• Operations requirements are constraints on the administration and management of
the system in the operational setting.
• Packaging requirements are constraints on the actual delivery of the system (e.g.,
constraints on the installation media for setting up the software).
• Legal requirements are concerned with licensing, regulation, and certification issues.
Nonfunctional requirements that fall into the URPS categories are called quality requirements
of the system. Nonfunctional requirements that fall into the implementation, interface,
operations, packaging, and legal categories are called constraints or pseudo requirements.
Budget and schedule requirements are usually not treated as nonfunctional requirements, as
they constrain attributes of the projects. Figure 3-3 depicts the nonfunctionalrequirements for
SatWatch.
Quality requirements for SatWatch
• Any user who knows how to read a digital watch and understands international time zone
abbreviations should be able to use SatWatch without the user manual. [Usability requirement]
• As the SatWatch has no buttons, no software faults requiring the resetting of the watch should
occur. [Reliability requirement]
• SatWatch should display the correct time zone within 5 minutes of the end of a GPS blackout
period. [Performance requirement]
• SatWatch should measure time within 1/100th second over 5 years. [Performance requirement]
• SatWatch should display time correctly in all 24 time zones. [Performance requirement]
• SatWatch should accept upgrades to its onboard via the Webify Watch serial interface.
[Supportability requirement]
requirement]
• SatWatch complies with the physical, electrical, and software interfaces defined by
WebifyWatch API 2.0. [Interface requirement]
Figure 3-3: Nonfunctional requirements for SatWatch.
functionality of the new system is extended, but the essential purpose of the system
remains the same. The requirements of the new system are extracted from an existing
system.
• An interface engineering project is the redesign of the user interface of an existing
system. The legacy system is left untouched except for its interface, which is redesigned
and reimplemented. This type of project is a reengineering project in which the legacy
system cannot be discarded without entailing high costs.
Figure 3-4: Actors for the SatWatch system. WatchOwner moves the watch (possibly across
time zones) and consults it to know what time it is. SatWatch interacts with GPS to compute its
position. WebifyWatch upgrades the data contained in the watch to reflect changes in time
policy (e.g., changes in daylight savings time start and end dates).
Consider a more complex example, FRIEND, a distributed information system for accident
management. It includes many actors, such as FieldOfficer, who represents the police and fire
officers who are responding to an incident, and Dispatcher, the police officer responsible for
answering 911 calls and dispatching resources to an incident. FRIEND supports both actors
by keeping track of incidents, resources, and task plans. It also has access to multiple databases,
such as a hazardous materials database and emergency operations procedures. The FieldOfficer
and the Dispatcher actors interact through different interfaces: FieldOfficers
access FRIEND through a mobile personal assistant, Dispatchers access FRIEND through a
workstation (see Figure 3-5).
Figure 3-5: Actors of the FRIEND system. FieldOfficers not only have access to different
functionality, they use different computers to access the system.
Actors are role abstractions and do not necessarily directly map to persons. The same person
can fill the role of FieldOfficer or Dispatcher at different times. However, the functionality they
access is substantially different. For that reason, these two roles are modeled as two different
actors.
The first step of requirements elicitation is the identification of actors. This serves both to
define the boundaries of the system and to find all the perspectives from which the developers
need to consider the system. When the system is deployed into an existing organization, most
actors usually exist before the system is developed: they correspond to roles in the organization.
During the initial stages of actor identification, it is hard to distinguish actors from objects. For
example, a database subsystem can at times be an actor, while in other cases it can be part of
the system. Note that once the system boundary is defined, there is no trouble distinguishing
between actors and such system components as objects or subsystems. Actors are outside of
the system boundary; they are external. Subsystems and objects are inside the system boundary;
they are internal. Thus, any external software system using the system to be developed is an
actor. When identifying actors, developers can ask the following questions:
In the FRIEND example, these questions lead to a long list of potential actors: fire fighter,
police officer, dispatcher, investigator, mayor, governor, an EPA hazardous material database,
system administrator, and so on. We then need to consolidate this list into a small number of
actors, who are different from the point of view of the usage of the system. For example, a fire
fighter and a police officer may share the same interface to the system, as they are both involved
with a single incident in the field. A dispatcher, on the other hand, managesmultiple concurrent
incidents and requires access to a larger amount of information. The mayor and the governor
will not likely interact directly with the system, but will use the services of a trained operator
instead.
Once the actors are identified, the next step in the requirements elicitation activity is to
determine the functionality that will be accessible to each actor. This information can be
extracted using scenarios and formalized using use cases.
Figure 3-6 is an example of scenario for the FRIEND system, an information system for
incident response. In this scenario, a police officer reports a fire and a Dispatcher initiates the
incident response. Note that this scenario is concrete, in the sense that it describes a single
instance. It does not attempt to describe all possible situations in which a fire incident is
reported. In particular, scenarios cannot contain descriptions of decisions.
To describe the outcome of a decision, two scenarios would be needed, one for the “true” path,
and another one for the “false” path.
Scenarios can have many different uses during requirements elicitation and during other
activities of the life cycle. Below is a selected number of scenario types:
• As-is scenarios describe a current situation. During reengineering, for example, the
current system is understood by observing users and describing their actions as
scenarios. These scenarios can then be validated for correctness and accuracy with the
users.
• Visionary scenarios describe a future system. Visionary scenarios are used both as a
point in the modeling space by developers as they refine their ideas of the future
In requirements elicitation, developers and users write and refine a series of scenarios in order
to gain a shared understanding of what the system should be. Initially, each scenario may be
high level and incomplete, as the warehouseOnFire scenario is. The following questions can
be used for identifying scenarios.
Developers use existing documents about the application domain to answer these questions.
These documents include user manuals of previous systems, procedures manuals, company
standards, user notes and cheat sheets, user and client interviews. Developers should always
write scenarios using application domain terms, as opposed to their own terms. As developers
gain further insight into the application domain and the possibilities of the available technology,
they iteratively and incrementally refine scenarios to include increasing amounts of detail.
In the FRIEND example, we identify four scenarios that span the type of tasks the system is
expected to support:
• warehouseOnFire (Figure 3-6): A fire is detected in a warehouse; two field officers
arrive at the scene and request resources.
• fenderBender: A car accident without casualties occurs on the highway. Police officers
document the incident and manage traffic while the damaged vehicles are towed away.
• catInATree: A cat is stuck in a tree. A fire truck is called to retrieve the cat. Because
the incident is low priority, the fire truck takes time to arrive at the scene. In the
meantime, the impatient cat owner climbs the tree, falls, and breaks a leg, requiring an
ambulance to be dispatched.
• earthQuake: An unprecedented earthquake seriously damages buildings and roads,
spanning multiple incidents and triggering the activation of a statewide emergency
operations plan. The governor is notified. Road damage hampers incident response.
The emphasis for developers during actor identification and scenario identification is to
understand the application domain. This results in a shared understanding of the scope of the
system and of the user work processes to be supported. Once developers have identified and
described actors and scenarios, they formalize scenarios into use cases.
Figure 3-7: An example of a use case, Report Emergency. Under Report Emergency, the left
column denotes actor actions, and the right column denotes system responses.
Figure 3-7 depicts the use case Report Emergency of which the scenario warehouseOnFire (see
Figure 3-6) is an instance. The Field Officer actor initiates this use case by activating the
“Report Emergency” function of FRIEND. The use case completes when the Field Officer actor
receives an acknowledgment that an incident has been created. The steps in the flow of events
are indented to denote who initiates the step. Steps 1 and 3 are initiated by the actor, while steps
2 and 4 are initiated by the system. This use case is general and encompasses a range of
scenarios. For example, the Report Emergency use case could also apply to the fender-bender
scenario. Use cases can be written at varying levels of detail as in the case of scenarios. Initially,
developers name use cases, attach them to the initiating actors, and provide a high-level
description of the use case as in Figure 3-7. The name of a use case should be a verb phrase
denoting what the actor is trying to accomplish. The verb phrase “Report Emergency”
indicates that an actor is attempting to report an emergency to the
system (and hence, to the Dispatcher actor). This use case is not called “Record Emergency”
because the name should reflect the perspective of the actor, not the system. It is also not called
“Attempt to Report an Emergency” because the name should reflect the goal of the use case,
not the actual activity.
Attaching use cases to initiating actors enables developers to clarify the roles of the different
users. Often, by focusing on who initiates each use case, developers identify new actors that
have been previously overlooked.
Describing a use case entails specifying four fields. Describing the entry and exit conditions of
a use case enables developers to understand the conditions under which a use case is invoked
and the impact of the use case on the state of the environment and of the system. By examining
the entry and exit conditions of use cases, developers can determine if there maybe missing
use cases. For example, if a use case requires that the emergency operations plan dealing with
earthquakes should be activated, the requirements specification should also provide a use case
for activating this plan. Describing the flow of events of a use case enables developers and
clients to discuss the interaction between actors and system. This results in many decisions
about the boundary of the system, that is, about deciding which actions are accomplished by
the actor and which actions are accomplished by the system. Finally, describing the quality
requirements associated with a use case enables developers to elicit nonfunctional requirements
in the context of a specific functionality.
Writing use cases is a craft. An analyst learns to write better use cases with experience.
Consequently, different analysts tend to develop different styles, which can make it difficult
to produce a consistent requirements specification. To address the issue of learning how to
write use cases and how to ensure consistency among the use cases of a requirements
specification, analysts adopt a use case writing guide. Figure 3-8 is a simple writing guide
adapted from [Cockburn, 2001] that can be used for novice use case writers. Figure 3-9
provides an example of a poor use case that violates the writing guideline in several ways. The
ReportEmergency use case in Figure 3-7 may be illustrative enough to describe how FRIEND
supports reporting emergencies and to obtain general feedback from the user, but it does not
provide sufficient detail for a requirements specification. Next, we discuss how use cases are
refined and detailed.
focus from the actual steps accomplished by the user and is better addressed with visual
mock-ups (e.g., the Report Emergency only refers to the “Report Emergency” function,
not the menu, the button, nor the actual command that corresponds to this function).
• A use case should not exceed two or three pages in length. Otherwise, use include and
extend relationships to decompose it in smaller use cases.
Figure 3-9: An example of a poor use case. Violations of the writing guide are indicated in
italics in the right column.
The use of scenarios and use cases to define the functionality of the system aims at creating
requirements that are validated by the user early in the development. As the design and
implementation of the system starts, the cost of changing the requirements specification and
adding new unforeseen functionality increases. Although requirements change until late in the
development, developers and users should strive to address most requirements issues early.
This entails many changes and much validation during requirements elicitation. Note that many
use cases are rewritten several times, others substantially refined, and yet others completely
dropped. To save time, much of the exploration work can be done using scenarios and user
interface mock-ups.
Figure 3-10: Refined description for the ReportEmergency use case. Additions emphasized in
italics.
The following heuristics can be used for writing scenarios and use cases:
The focus of this activity is on completeness and correctness. Developers identify functionality
not covered by scenarios, and document it by refining use cases or writing new ones.
Developers describe seldom occurring cases and exception handling as seen by the
actors. Whereas the initial identification of use cases and actors focused on establishing the
boundary of the system, the refinement of use cases yields increasingly more details about the
features provided by the system and the constraints associated with them. In particular, the
following aspects of the use cases, initially ignored, are detailed during refinement:
• The elements that are manipulated by the system are detailed. In Figure 3-10, we added
details about the attributes of the emergency reporting form and the types of incidents.
• The low-level sequence of interactions between the actor and the system are specified.
In Figure 3-10, we added information about how the Dispatcher generates an
acknowledgment by selecting resources.
• Access rights (which actors can invoke which use cases) are specified.
• Missing exceptions are identified and their handling specified.
• Common functionality among use cases are factored out.
In the next section, we describe how to reorganize actors and use cases with relationships,
which addresses the last three bullets points above.
Figure 3-11: Example of communication relationships among actors and use cases in FRIEND
(UML use case diagram). The FieldOfficer initiates the ReportEmergency use case, and the
Dispatcher initiates the OpenIncident and AllocateResources use cases. FieldOfficers cannot
directly open an incident or allocate resources on their own.
The relationships between actors and use cases are identified when use cases are identified.
Figure 3-11 depicts an example of communication relationships in the case of the FRIEND
system. The «initiate» stereotype denotes the initiation of the use case by an actor, and the
«participate» stereotype denotes that an actor (who did not initiate the use case) communicates
with the use case.
Figure 3-12: Example of use of extend relationship (UML use case diagram). ConnectionDown
extends the ReportEmergency use case. The ReportEmergency use case becomes shorter and
solely focused on emergency reporting.
Figure 3-13: Example of include relationships among use cases. ViewMap describes the flow
of events for viewing a city map (e.g., scrolling, zooming, query by street name) and is used
by both OpenIncident and AllocateResources use cases.
Factoring out shared behavior from use cases has many benefits, including shorter descriptions
and fewer redundancies. Behavior should only be factored out into a separate use case if it is
shared across two or more use cases. Excessive fragmentation of the requirements specification
across a large number of use cases makes the specification confusing to users and clients.
Figure 3-14 shows the ConnectionDown example described with an include relationship (left
column) and with an extend relationship (right column). In the left column, we need to insert
text in two places in the event flow where the ConnectionDown use case can be invoked. Also,
if additional exceptional situations are described (e.g., a help function on the FieldOfficer
station), the ReportEmergency use case will have to be modified and will become cluttered
with conditions. In the right column, we need to describe only the conditions under which the
exceptional use case is invoked, which can include a large number of use cases (e.g., “any use
case in which the connection between the FieldOfficer and the Dispatcher is lost”). Moreover,
additional exceptional situations can be added without modifying the base use case (e.g.,
ReportEmergency). The ability to extend the system without modifying existing parts is
critical, as it allows us to ensure that the original behavior is left untouched. The distinction
between include and extend is a documentation issue: using the correct type of relationship
reduces dependencies among use cases, reduces redundancy, and lowers the probability of
introducing errors when requirements change. However, the impact on other development
activities is minimal.
In summary, the following heuristics can be used for selecting an extend or an include
relationship.
Heuristics for extend and include relationships
• Use extend relationships for exceptional, optional, or seldom-occurring behavior. An
example of seldom-occurring behavior is the breakdown of a resource (e.g., a fire
truck). An example of optional behavior is the notification of nearby resources
responding to an unrelated incident.
• Use include relationships for behavior that is shared across two or more use cases.
• However, use discretion when applying the above two heuristics and do not
overstructure the use case model. A few longer use cases (e.g., two pages long) are
easier to understand and review than many short ones (e.g., ten lines long).
In all cases, the purpose of adding include and extend relationships is to reduce or remove
redundancies from the use case model, thus eliminating potential inconsistencies.
to the project. Misunderstandings result from the same terms being used in different contexts
and with different meanings.
To establish a clear terminology, developers identify the participating objects for each use case.
Developers should identify, name, and describe them unambiguously and collate them into a
glossary (data dictionary). Building this glossary constitutes the first step toward analysis,
which we discuss in the next chapter. The glossary is included in the requirements specification
and, later, in the user manuals. Developers keep the glossary up to date as the requirements
specification evolves. The benefits of the glossary are manyfold: new developers are exposed
to a consistent set of definitions, a single term is used for each concept (instead of a developer
term and a user term), and each term has a precise and clear official meaning.
The identification of participating objects results in the initial analysis object model. The
identification of participating objects during requirements elicitation only constitutes a first
step toward the complete analysis object model. The complete analysis model is usually not
used as a means of communication between users and developers, as users are often unfamiliar
with object-oriented concepts. However, the description of the objects (i.e., the definitions of
the terms in the glossary) and their attributes are visible to the users and reviewed. We describe
in detail the further refinement of the analysis model in next chapter Analysis.
Many heuristics have been proposed in the literature for identifying objects. Here are a selected
few:
During requirements elicitation, participating objects are generated for each use case. If two
use cases refer to the same concept, the corresponding object should be the same. If two objects
share the same name and do not correspond to the same concept, one or both concepts are
renamed to acknowledge and emphasize their difference. This consolidation eliminates any
ambiguity in the terminology used. For example, Table 3-2 depicts the initial participating
objects we identified for the ReportEmergency use case.
Once participating objects are identified and consolidated, the developers can use them as a
checklist for ensuring that the set of identified use cases is complete.
• Which use cases modify and destroy this object (i.e., which use cases edit or remove
this information from the system)?
• Which actor can initiate these use cases?
• Is this object needed (i.e., is there at least one use case that depends on this
information?)
For example, consider a mosaic display that an air traffic controller uses to track planes. A
mosaic display system compiles data from a series of radars and databases (hence the term
“mosaic”) into a summary display indicating all aircraft in a certain area, including their
identification, speed, and altitude. The number of aircraft such a system can display constrains
the performance of the air traffic controller and the cost of the system. If the system can only
handle a few aircraft simultaneously, the system cannot be used at busy airports. On the other
hand, a system able to handle a large number of aircraft is more costly and more complex to
build and to test.
Nonfunctional requirements can impact the work of the user in unexpected ways. To accurately
elicit all the essential nonfunctional requirements, both client and developer must collaborate
so that they identify (minimally) which attributes of the system that are difficult to realize are
critical for the work of the user. In the mosaic display example above, the number of aircraft
that a single mosaic display must be able to handle has implications on the size of the icons
used for displaying aircraft, the features for identifying aircraft and their properties, the refresh
rate of the data, and so on.
accurate mechanism, so that the time never needs to be reset, and a low unit cost, so that it is
acceptable to the user to replace the watch with a new one when it breaks. These two
nonfunctional requirements conflict as the unit cost of the watch increases with its accuracy.
To deal with such conflicts, the client and the developer prioritize the nonfunctional
requirements, so that they can be addressed consistently during the realization of the system.
There are unfortunately few systematic methods for eliciting nonfunctional requirements. In
practice, analysts use a taxonomy of nonfunctional requirements (e.g., the FURPS+ scheme
described previously) to generate check lists of questions to help the client and the developers
focus on the nonfunctional aspects of the system. As the actors of the system have already been
identified at this point, this check list can be organized by role and distributed to representative
users. The advantage of such check lists is that they can be reused and expanded for each new
system in a given application domain, thus reducing the number of omissions. Note that such
check lists can also result in the elicitation of additional functional requirements. For example,
when asking questions about the operation of the system, the client and developers may uncover
a number of use cases related with the administration of the system. Table 3-3 depicts example
questions for each of the FURPS+ category.
Once the client and the developers identify a set of nonfunctional requirements, they can
organize them into refinement and dependency graphs to identify further nonfunctional
requirements and identify conflicts.
The first part of the document, including use cases and nonfunctional requirements, is written
during requirements elicitation. The formalization of the specification in terms of object models
is written during analysis. Figure 3-15 is an example template for a RAD used in this course.
The first section of the RAD is an Introduction. Its purpose is to provide a brief overview of
the function of the system and the reasons for its development, its scope, and references to the
development context (e.g., reference to the problem statement written by the client, references
to existing systems, feasibility studies). The introduction also includes the objectives and
success criteria of the project.
The second section, Current system, describes the current state of affairs. If the new system
will replace an existing system, this section describes the functionality and the problems of
the current system. Otherwise, this section describes how the tasks supported by the new
system are accomplished now. For example, in the case of SatWatch, the user currently resets
her watch whenever she travels across a time zone. Because of the manual nature of this
operation, the user occasionally sets the wrong time and occasionally neglects to reset. In
contrast, the SatWatch will continually ensure accurate time within its lifetime. In the case of
FRIEND, the current system is paper based: dispatchers keep track of resource assignments
by filling out forms. Communication between dispatchers and field officers is by radio. The
current system requires a high documentation and management cost that FRIEND aims to
reduce.
The third section, Proposed system, documents the requirements elicitation and the analysis
model of the new system. It is divided into four subsections:
• Overview presents a functional overview of the system.
• Functional requirements describes the high-level functionality of the system.
• Nonfunctional requirements describes user-level requirements that are not directly
related to functionality. This includes usability, reliability, performance, supportability,
implementation, interface, operational, packaging, and legal requirements.
• System models describes the scenarios, use cases, object model, and dynamic models
for the system. This section contains the complete functional specification, including
mock-ups illustrating the user interface of the system and navigational paths
representing the sequence of screens. The subsections Object model and Dynamic
model are written during the Analysis activity, described in the next chapter.
The RAD should baselined and put under configuration management. The
be written after revision history section of the RAD will provide a history of
the use case changes include the author responsible for each change, the
model is stable, date of the change, and a brief description of the change.
that is, when the
Figure 3-15: Outline of the Requirements Analysis Document
number of
(RAD). Sections in italics are completed during analysis in
modifications to
next chapter.
the requirements
is minimal. The
requirements,
however, are
updated
throughout the
development
process when
specification
problems are
discovered or
when the scope
Analysis results in a model of the system that aims to be correct, complete, consistent, and
unambiguous. Developers formalize the requirements specification produced during
requirements elicitation and examine in more detail boundary conditions and exceptional cases.
Developers validate, correct and clarify the requirements specification if any errors or
ambiguities are found. The client and the user are usually involved in this activity when the
requirements specification must be changed and when additional information must be gathered.
Analysis focuses on producing a model of the system, called the analysis model, which is
correct, complete, consistent, and verifiable. Analysis is different from requirements elicitation
in that developers focus on structuring and formalizing the requirements elicited from users
(Figure 4-1). This formalization leads to new insights and the discovery of errors in the
requirements. As the analysis model may not be understandable to the users and the client,
developers need to update the requirements specification to reflect insights gained during
analysis, then review the changes with the client and the users. In the end, the requirements,
however large, should be understandable by the client and the users.
Figure 4-1: Products of requirements elicitation and analysis (UML activity diagram).
There is a natural tendency for users and developers to postpone difficult decisions until later
in the project. A decision may be difficult because of lack of domain knowledge, lack of
technological knowledge, or simply because of disagreements among users and developers.
Postponing decisions enables the project to move on smoothly and avoids confrontation with
reality or peers. Unfortunately, difficult decisions eventually must be made, often at higher
cost when intrinsic problems are discovered during testing, or worse, during user evaluation.
Translating a requirements specification into a formal or semiformal model forces developers
to identify and resolve difficult issues early in the development.
The analysis model is composed of three individual models: the functional model,
represented by use cases and scenarios, the analysis object model, represented by class and
object diagrams, and the dynamic model, represented by state machine and sequence diagrams
(Figure 4-2).
Figure 4-2: The analysis model is composed of the functional model, the object model, and the
dynamic model. In UML, the functional model is represented with use case diagrams, the object
model with class diagrams, and the dynamic model with state machine and sequence diagrams.
In the previous chapter, we described how to elicit requirements from the users and describe
them as use cases and scenarios. In this chapter, we describe how to refine the functional model
and derive the object and the dynamic model. This leads to a more precise and complete
specification as details are added to the analysis model.
The dynamic model focuses on the behavior of the system. The dynamic model is depicted
with sequence diagrams and with state machines. Sequence diagrams represent the interactions
among a set of objects during a single use case. State machines represent the behavior of a
single object (or a group of very tightly coupled objects). The dynamic model serves to assign
responsibilities to individual classes and, in the process, to identify new classes, associations,
and attributes to be added to the analysis object model.
When working with either the analysis object model or the dynamic model, it is essential to
remember that these models represent user-level concepts, not actual software classes or
components. For example, classes such as Database, Subsystem, SessionManager, Network,
should not appear in the analysis model as the user is completely shielded from those concepts.
Note that most classes in the analysis object model will correspond to one or more software
classes in the source code. However, the software classes will include many more attributes
and associations than their analysis counterparts. Consequently, analysis classes should be
viewed as high-level abstractions that will be realized in much more detail later. Figure 4-3
depicts good and bad examples of analysis objects for the SatWatch example.
Figure 4-3: Examples and counterexamples of classes in the analysis object model of SatWatch.
Modeling the system with entity, boundary, and control objects provides developers with
simple heuristics to distinguish different, but related concepts. For example, the time that is
tracked by a watch has different properties than the display that depicts the time. Differentiating
between boundary and entity objects forces that distinction: The time that is tracked by the
watch is represented by the Time object. The display is represented by the LCDDisplay. This
approach with three object types results in smaller and more specialized objects. The three
object- type approach also leads to models that are more resilient to change: the interface to
the system (represented by the boundary objects) is more likely to change than its basic
functionality (represented by the entity and control objects). By
separating the interface from the basic functionality, we are able to keep most of a model
untouched when, for example, the user interface changes, but the entity objects do not.
To distinguish between different types of objects, UML provides the stereotype mechanism
to enable the developer to attach such meta-information to modeling elements. For example, in
Figure 4-4, we attach the «control» stereotype to the ChangeDateControl object. In addition
to stereotypes, we may also use naming conventions for clarity and recommend distinguishing
the three different types of objects on a syntactical basis: control objects may have the suffix
Control appended to their name; boundary objects may be named to clearly denote an interface
feature (e.g., by including the suffix Form, Button, Display, or Boundary); entity objects
usually do not have any suffix appended to their name. Another benefit of this naming
convention is that the type of the class is represented even when the UML stereotype is not
available, for example, when examining only the source code.
Generalization is the modeling activity that identifies abstract concepts from lower-level ones.
For example, assume we are reverse-engineering an emergency management system and
discover screens for managing traffic accidents and fires. Noticing common features among
these three concepts, we create an abstract concept called Emergency to describe the common
(and general) features of traffic accidents and fires.
Specialization is the activity that identifies more specific concepts from a high-level one. For
example, assume that we are building an emergency management system from scratch and that
we are discussing its functionality with the client. The client first introduces us with the concept
of an incident, then describes three types of Incidents: Disasters, which require the
collaboration of several agencies, Emergencies, which require immediate handling but can be
handled by a single agency, and LowPriorityIncidents, that do not need to be handled if
resources are required for other, higher-priority Incidents.
Figure 4-5: An example of a generalization hierarchy (UML class diagram). The top of the
hierarchy represents the most general concept, whereas the bottom nodes represent the most
specialized concepts.
We illustrate each activity by focusing on the ReportEmergency use case of FRIEND described
in Requirements Elicitation chapter. These activities are guided by heuristics. The methods and
heuristics presented in this section are adapted from [De Marco, 1978], [Jacobson et al., 1999],
[Rumbaugh et al., 1991], and [Wirfs-Brock et al., 1990].
Table 4-1: Abbott’s heuristics for mapping parts of speech to model components.
Natural language analysis has the advantage of focusing on the users’ terms. However, it suffers
from several limitations. First, the quality of the object model depends highly on the style of
writing of the analyst (e.g., consistency of terms used, verbification of nouns). Developers can
address this limitation by rephrasing and clarifying the requirements specification as they
identify and standardize objects and terms. A second limitation of natural language analysis
is that there are many more nouns than relevant classes. Many nouns correspond to attributes
or synonyms for other nouns. Sorting through all the nouns for a large requirements
specification is a time-consuming activity. In general, Abbott’s heuristics work well for
generating a list of initial candidate objects from short descriptions,
such as the flow of events of a scenario or a use case. The following heuristics can be used in
conjunction with Abbott’s heuristics:
Developers name and briefly describe the objects, their attributes, and their responsibilities as
they are identified. Uniquely naming objects promotes a standard terminology. For entity
objects we recommend always to start with the names used by end users and application domain
specialists. Describing objects, even briefly, allows developers to clarify the conceptsthey use
and avoid misunderstandings (e.g., using one object for two different but related concepts).
Developers need not, however, spend a lot of time detailing objects or attributes given that the
analysis model is still in flux. Developers should document attributes and responsibilities if
they are not obvious; a tentative name and a brief description for each object is sufficient
otherwise. There will be plenty of iterations during which objects can be revised. However,
once the analysis model is stable, the description of each object should be as detailed as
necessary.
For example, after a first examination of the ReportEmergency use case (Figure 4-6), we use
application domain knowledge and interviews with the users to identify the objects Dispatcher,
EmergencyReport, FieldOfficer, and Incident. Note that the EmergencyReport object is not
mentioned explicitly by name in the ReportEmergency use case. Step 4 of the use case refers
to the emergency report as the “information submitted by the FieldOfficer.” After review with
the client, we discover that this information is usually referred to as the “emergency report”
and decide to name the corresponding object EmergencyReport.
The definition of entity objects leads to the initial analysis model described in Table 4-2. Note
that this model is far from a complete description of the system implementing the
ReportEmergency use case. In the next section, we describe the identification of boundary
objects.
Table 4-2: Entity objects for the ReportEmergency use case.
We find the boundary objects of Table 4-3 by examining the ReportEmergency use case.
Note that the IncidentForm is not explicitly mentioned anywhere in the ReportEmergency use
case. We identified this object by observing that the Dispatcher needs an interface to view the
emergency report submitted by the FieldOfficer and to send back an acknowledgment. The
terms used for describing the boundary objects in the analysis model should follow the user
terminology, even if it is tempting to use terms from the implementation domain.
Table 4-3: Boundary objects for the ReportEmergency use case.
We have made progress toward describing the system. We now have included the interface
between the actor and the system. We are, however, still missing some significant pieces of the
description, such as the order in which the interactions between the actors and the system occur.
In the next section, we describe the identification of control objects.
Initially, we model the control flow of the ReportEmergency use case with a control object for
each actor: ReportEmergencyControl for the FieldOfficer and ManageEmergency-Controlfor
the Dispatcher, respectively (Table 4-4).
The decision to model the control flow of the ReportEmergency use case with two control
objects stems from the knowledge that the FieldOfficerStation and the DispatcherStation are
actually two subsystems communicating over an asynchronous link. This decision could have
been postponed until the system design activity. On the other hand, making this concept visible
in the analysis model allows us to focus on such exception behavior as the loss of
communication between both stations.
In modeling the ReportEmergency use case, we modeled the same functionality by using entity,
boundary, and control objects. By shifting from the event flow perspective to a structural
perspective, we increased the level of detail of the description and selected standard terms to
refer to the main entities of the application domain and the system. In the next section, we
construct a sequence diagram using the ReportEmergency use case and the objects we
discovered to ensure the completeness of our model.
In this section, we model the sequence of interactions among objects needed to realize the use
case. Figures 4-7 through 4-9 are sequence diagrams associated with the ReportEmergency use
case. The columns of a sequence diagram represent the objects that participate in the use case.
The left-most column is the actor who initiates the use case. Horizontal arrows across columns
represent messages, or stimuli, that are sent from one object to the other. Time proceeds
vertically from top to bottom. For example, the first arrow in Figure 4-7 represents the press
message sent by a FieldOfficer to an ReportEmergencyButton. The receipt of a message
triggers the activation of an operation. The activation is represented by a vertical rectangle from
which other messages can originate. The length of the rectangle represents the time the
operation is active. In Figure 4-7, the operation triggered by the press message sends a create
message to the ReportEmergencyControl class. An operation can be thought of as a service that
the object provides to other objects. Sequence diagrams also depict the lifetime of objects.
Objects that already exist before the first stimuli in the sequence diagram are depicted at the
top of the diagram. Objects that are created during the interaction are depicted with the «create»
message pointing to the object. Instances that are destroyed during the interaction have a cross
indicating when the object ceases to exist. Between the rectangle representing the object and
the cross (or the bottom of the diagram, if the object survives the interaction), a dashed line
represents the time span when the object can receive messages. The object cannot receive
messages below the cross sign. For example, in Figure 4-7 an object of class
ReportEmergencyForm is created when object of ReportEmergencyControl
sends the «create» message and is destroyed once the EmergencyReportForm has been
submitted.
In general, the second column of a sequence diagram represents the boundary object with which
the actor interacts to initiate the use case (e.g., ReportEmergencyButton). The third column is
a control object that manages the rest of the use case (e.g., ReportEmergency– Control). From
then on, the control object creates other boundary objects and may interact with other control
objects as well (e.g., ManageEmergencyControl).
In Figure 4-8, we discover the entity object Acknowledgment that we forgot during our initial
examination of the ReportEmergency use case (in Table 5-2). The Acknowledgment object is
different from an AcknowledgmentNotice: Acknowledgment holds the information associated
with an Acknowledgment and is created before the AcknowledgmentNotice boundary object.
When describing the Acknowledgment object, we also realize that the original
ReportEmergency use case (described in Figure 4-6) is incomplete. It only mentions the
existence of an Acknowledgment and does not describe the information associated with it. In
this case, developers need clarification from the client to define what information is needed
in the Acknowledgment. After obtaining such clarification, the Acknowledgment object is
added to the analysis model (Table 4-5), and the ReportEmergency use case is clarified to
include the additional information (Figure 4-10).
Figure 4-8: Sequence diagram for the Report Emergency use case (continued from Figure 4-
7).
Figure 4-9: Sequence diagram for the Report Emergency use case (continued from Figure 4-
8).
By constructing sequence diagrams, we not only model the order of the interaction among the
objects, we also distribute the behavior of the use case. That is, we assign responsibilities to
each object in the form of a set of operations.
These operations can be shared by any use case in which a given object participates. Note that
the definition of an object that is shared across two or more use cases should be identical; that
is, if an operation appears in more than one sequence diagram, its behavior should be the same.
Sharing operations across use cases allows developers to remove redundancies in the
requirements specification and to improve its consistency. Note that clarity should always be
given precedence to eliminating redundancy. Fragmenting behavior across many operations
unnecessarily complicates the requirements specification.
In analysis, sequence diagrams are used to help identify new participating objects and missing
behavior. Because sequence diagrams focus on high-level behavior, implementation issues
such as performance should not be addressed at this point. Given that building
Figure 4-10: Refined ReportEmergency use case. The discovery and addition of the
Acknowledgment object to the analysis model revealed that the original ReportEmergency use
case did not accurately describe the information associated with Acknowledgments. The
refinements are indicated in boldface.
Figure 4-12: An example of association between the EmergencyReport and the FieldOfficer
classes.
• A role at each end, identifying the function of each class with respect to the associations (e.g.,
author is the role played by FieldOfficer in the Writes association).
• A multiplicity at each end, identifying the possible number of instances (e.g.,*indicates a
FieldOfficer may write zero or more EmergencyReports, whereas 1indicates that each
EmergencyReport has exactly one FieldOfficer as author).
Once the number of changes to the model is minimal and the scope of the changes localized,
the analysis model becomes stable. Then the analysis model is reviewed, first by the developers
(i.e., internal reviews), then jointly by the developers and the client. The goal of the review is
to make sure that the requirements specification is correct, complete, consistent, and
unambiguous. Moreover, developers and client also review if the requirements are realistic and
verifiable. Note that developers should be prepared to discover errors downstream and make
changes to the specification. It is, however, a worthwhile investment to catch as many
requirements errors upstream as possible. The review can be facilitated by a checklist or a list
of questions.
revise these sections as ambiguities and new functionality are discovered. The main effort, however,
focuses on writing the sections documenting the analysis object model (RAD Sections 3.4.3 and 3.4.4).
RAD Section 3.4.3, Object models, documents in detail all the objects we identified, their attributes, and,
when we used sequence diagrams, operations. As each object is described with textual definitions,
relationships among objects are illustrated with class diagrams.
RAD Section 3.4.4, Dynamic models, documents the behavior of the object model in terms of state
machine diagrams and sequence diagrams. Although this information is redundant with the use case
model, dynamic models enable us to represent more precisely complex behaviors, including use cases
involving many actors.
The RAD, once completed and published, will be baseline and put under configuration management. The
revision history section of the RAD will provide a history of changes including the author responsible for
each change, the date of the change, and brief descriptionof the change.
Figure 4-12: Overview outline of the Requirements Analysis Document (RAD). See Figure 3- 15 for a
detailed outline.
CoSc-3092 OBJECT ORIENTED SOFTWARE ENGINEERING
5.1 Introduction
System design is the transformation of an analysis model into a system design model. During
system design, developers define the design goals of the project and decompose the system into
smaller subsystems that can be realized by individual teams. Developers also select strategies
for building the system, such as the hardware/software strategy, the persistent data management
strategy, the global control flow, the access control policy, and the handling of boundary
conditions. The result of system design is a model that includes a subsystem decomposition
and a clear description of each of these strategies.
System design, object design, and implementation constitute the construction of the system.
During these three activities, developers bridge the gap between the requirements specification,
produced during requirements elicitation and analysis, and the system that is delivered to the
users. System design is the first step in this process and focuses on decomposing the system
into manageable parts.
During requirements elicitation and analysis, we concentrated on the purpose and the
functionality of the system. During system design, we focus on the processes, data structures,
and software and hardware components necessary to implement it.
The design goals are derived from the nonfunctional requirements. Developers divide the
system into manageable pieces to deal with complexity: each subsystem is assigned to a team
and realized independently. Figure 5-1 depicts the relationship of system design with other
software engineering activities.
For example, the accident management system we previously described can be decomposed
into a DispatcherInterface subsystem, realizing the user interface for the Dispatcher; a
FieldOfficerInterface subsystem, realizing the user interface for the FieldOfficer; an
IncidentManagement subsystem, responsible for the creation, modification, and storage of
Incidents; a ResourceManagement subsystem, responsible for tracking available Resources
(e.g., FireTrucks and Ambulances); a MapManagement for depicting Maps and Locations; and
a Notification subsystem, implementing the communication between FieldOfficer terminals
and Dispatcher stations.
Figure 5-2: Subsystem decomposition for an accident management system (UML component
diagram). Subsystems are shown as UML components. Dashed arrows indicate dependencies
between subsystems.
This subsystem decomposition is depicted in Figure 5-2 using UML components. Components
are depicted as rectangles with the component icon in the upper right corner. Dependencies
among components can be depicted with dashed stick arrows. In UML, components can
represent both logical and physical components. A logical component corresponds to a
subsystem that has no explicit run-time equivalent, for example, individual business
components that are composed together into a single run-time application logic
System design focuses on defining the services provided by each subsystem, that is,
enumerating the operations, their parameters, and their high-level behavior. Provided and
required interfaces can be depicted in UML with assembly connectors, also called ball-and-
socket connectors. The provided interface is shown as a ball icon (also called lollipop) with its
name next to it. A required interface is shown as a socket icon. The dependency between two
subsystems is shown by connecting the corresponding ball and socket in the component
diagram.
Figure 5-3 depicts the dependencies among the FieldOfficerInterface, DispatchterInterface and
ResourceManagement subsystems. The FieldOfficerInterface requires the
ResourceUpdateService to update the status and location of the FieldOfficer. The
DispatcherInterface requires the ResourceAllocationService to identify available resources and
allocating them to new Incidents. The ResourceManagement subsystem provides both services.
Note that we use the ball-and-socket notation when the subsystem decomposition is already
fairly stable and that our focus has shifted from the identification of subsystems to the definition
of services. During the early stages of system design, we may not have such a clear
understanding of the allocation of functionality to subsystems, in which case we use the
dependency notation (dashed arrows) of Figure 5-2.
In general, there is a trade-off between cohesion and coupling. We can often increase cohesion
by decomposing the system into smaller subsystems. However, this also increases coupling as
the number of interfaces increases. A good heuristic is that developers can deal with 7 ± 2
concepts at any one level of abstraction. If there are more than nine subsystems at any given
level of abstraction, or if a subsystem provides more than nine services, you should consider
revising the decomposition. By the same token, the number of layers should not be more than
7 ± 2. In fact, good systems design can often be accomplished with just three layers.
Figure 5-4: Subsystem decomposition of a system into three layers (UML object diagram, layers
depicted as packages). A subset from a layered decomposition that includes at least one
subsystem from each layer is called a vertical slice. For example, the subsystems A, B, and E
constitute a vertical slice, whereas the subsystems D and G do not.
Another approach to dealing with complexity is to partition the system into peer subsystems,
each responsible for a different class of services.
For example, an onboard system for a car could be decomposed into a travel service that
provides real-time directions to the driver, an individual preferences service that remembers a
driver’s seat position and favorite radio station, and vehicle service that tracks the car’s gas
consumption, repairs, and scheduled maintenance. Each subsystem depends loosely on the
others, but can often operate in isolation.
In general, a subsystem decomposition is the result of both partitioning and layering. We first
partition the system into top-level subsystems, which are responsible for specific functionality
or run on a specific hardware node. Each of the resulting subsystems are, if complexity justifies
it, decomposed into lower- and lower-level layers until they are simple enough to be
implemented by a single developer. Each subsystem adds a certain processing overhead
because of its interface with other systems. Excessive partitioning or layering can increase
complexity.
A Web server, for example, is a component that provides services to Web browsers. A Web
browser is a component that provides services to a user. A node is a physical device or an
execution environment in which components are executed. A system is composed of interacting
run-time components that can be distributed among several nodes. Furthermore a node can
contain another node, for example, a device can contain an execution environment.
In UML deployment diagrams, nodes are represented by boxes containing component icons.
Nodes can be stereotyped to denote physical devices or execution environments.
Communication paths between nodes are represented by solid lines. The protocol used by two
nodes to communicate can be indicated with a stereotype on the communication path.
Figure 5-5 depicts an example of a deployment diagram with two Web browsers accessing a
Web server. The Web server in turns accesses a database server. We can see from the diagram
that the Web browsers do not directly access the database at any time.
Figure 5-5: A UML deployment diagram representing the allocation of components to different
nodes. Web browsers on PCs and Macs can access a WebServer that provides information
from a Database.
The deployment diagram in Figure 7-2 focuses on the allocation of components to nodes and
provides a high-level view of each component.
Using MyTrip, a driver can plan a trip from a home computer by contacting a trip-planning
service on the Web (PlanTrip in Figure 5-6). The trip is saved for later retrieval on the server.
The trip-planning service must support more than one driver.
The driver then goes to the car and starts the trip, while the onboard computer gives directions
based on trip information from the planning service and her current position indicated by an
onboard GPS system (ExecuteTrip in Figure 5-7).
We perform the analysis for the MyTrip system following the techniques outlined in Analysis
chapter, and obtain the model in Figure 5-8.
Figure 5-8: Analysis model for the MyTrip route planning and execution.
In addition, during requirements elicitation, our client specified the following nonfunctional
requirements for MyTrip:
For example, in the light of the nonfunctional requirements for MyTrip described earlier, we
identify reliability and fault tolerance to connectivity loss as design goals. We then identify
security as a design goal, as numerous drivers will have access to the same trip planning server.
We add modifiability as a design goal, as we want to provide the ability for drivers to select a
trip planning service of their choice. The following summarizes the design goals we identified.
In general, we can select design goals from a long list of highly desirable qualities. Below is
the list of number of possible design criteria. These criteria are organized into five groups:
performance, dependability, cost, maintenance, and end user criteria. Performance,
dependability, and end user criteria are usually specified in the requirements or inferred from
the application domain. Cost and maintenance criteria are dictated by the customer and the
supplier.
1. Performance criteria include the speed and space requirements imposed on the
system.
• Response time: How soon is a user request acknowledged after the request has
been issued?
• Throughput: How many tasks can the system accomplish in a fixed period of
time?
• Memory: How much space is required for the system to run?
2. Dependability criteria determine how much effort should be expended in
minimizing system crashes and their consequences.
• Robustness: Ability to survive invalid user input
• Reliability: Difference between specified and observed behavior
• Availability: Percentage of time that system can be used to accomplish normal
tasks
• Fault tolerance: Ability to operate under erroneous conditions
• Security: Ability to withstand malicious attacks
• Safety: Ability to avoid endangering human lives, even in the presence of
errors and Failures
3. Cost criteria include the cost to develop the system, to deploy it, and to administer it.
• Development cost: Cost of developing the initial system
• Deployment cost: Cost of installing the system and training the users
• Upgrade cost: Cost of translating data from the previous system. This criteria
results in backward compatibility requirements
• Maintenance cost: Cost required for bug fixes and enhancements to the system
• Administration cost: Cost required to administer the system
4. Maintenance criteria determine how difficult it is to change the system after
deployment.
• Extensibility: How easy is it to add functionality or new classes to the system?
When defining design goals, only a small subset of these criteria can be simultaneously taken
into account. It is, for example, unrealistic to develop software that is safe, secure, and cheap.
Once we have a clear idea of the design goals, we can proceed to design an initial subsystem
decomposition.
The initial subsystem decomposition should be derived from the functional requirements. For
example, in the MyTrip system, we identify two major groups of objects: those that are
involved during the PlanTrip use case and those that are involved during the ExecuteTrip use
case. The Trip, Direction, Crossing, Segment, and Destination classes are shared betweenboth
use cases. This set of classes is tightly coupled as it is used as a whole to represent a Trip. We
decide to assign them with PlanningService to the PlanningSubsystem, and the remainder of
the classes are assigned to the RoutingSubsystem (Figure 5-9). This leads to only one
association crossing subsystem boundaries. Note that this subsystem decomposition is a
repository in which the PlanningSubsystem is responsible for the central data structure.
Another heuristic for subsystem identification is to keep functionally related objects together.
A starting point is to assign the participating objects that have been identified in each use case
to the subsystems. Some group of objects, as the Trip group in MyTrip, are shared and used for
communicating information from one subsystem to another. We can either create a new
subsystem to accommodate them or assign them to the subsystem that creates these objects.
Heuristics for grouping objects into subsystems:
• Assign objects identified in one use case into the same subsystem.
• Create a dedicated subsystem for objects used for moving data among subsystems.
• Minimize the number of associations crossing subsystem boundaries.
• All objects in the same subsystem should be functionally related.
Figure 5-9: Initial subsystem decomposition for MyTrip (UML class diagram).
Selecting a hardware configuration also includes selecting a virtual machine onto which the
system should be built. The virtual machine includes the operating system and any software
components that are needed, such as a database management system or a communication
package.
The selection of a virtual machine reduces the distance between the system and the hardware
platform on which it will run. The more functionality the components provide, the less
development work is involved. The selection of the virtual machine, however, may be
constrained by a client who acquires hardware before the start of the project. The selection of
a virtual machine may also be constrained by cost considerations: it can be difficult to estimate
whether building a component costs more than buying it.
We select a Unix machine as the virtual machine for the :WebServer, and the Web browsers
Safari and Internet Explorer as the virtual machines for the :OnBoardComputer.
Figure 5-10: Allocation of MyTrip subsystems to devices and execution environments (UML
deployment diagram). RoutingSubsystem runs on the OnBoardComputer; PlanningSubsystem
runs on an Apache server.
In the MyTrip system, both RoutingSubsystem and PlanningSubsystem share the objects Trip,
Destination, Crossing, Segment, and Direction. Instances of these classes need to communicate
via a wireless modem using some communication protocol. We create a new subsystem to
support this communication: CommunicationSubsystem, a subsystem located on both nodes
for managing the communication between them.
We also notice that only segments constituting the planned trip are stored in
RoutingSubsystem. Adjacent segments not part of the trip are stored only in the
PlanningSubsystem. To take this into account, we need objects in the RoutingSubsystem that
can act as surrogates to Segments and Trips in the PlanningSubsystem. An object that acts on
the behalf of another one is called a “proxy.” We therefore create two new classes,
SegmentProxy and TripProxy, and make them part of the RoutingSubsystem. In case of
replanning by the driver, this class will transparently request the CommunicationSubsystem to
retrieve the information associated with its corresponding Segments on the
PlanningSubsystem. Finally, the CommunicationSubsystem is used for transferring a complete
trip from PlanningSubsystem to RouteAssistant. The revised design model and the additional
class descriptions are depicted in Figure 5-11.
Figure 5-11: Revised design model for MyTrip (UML component diagram).
Where and how data is stored in the system affects system decomposition. The selection of a
specific database management system can also have implications on the overall control strategy
and concurrency management.
For example, in MyTrip, we decide to store the current Trip in a file on a removable disk to
allow the recovery of the Trip in case the driver shuts off the car before reaching the final
Destination. Using a file is the simplest and most efficient solution in this case, given that the
RoutingSubsystem will only store complete Trips to the file before shutdown and load the file
at start-up. In the PlanningSubsystem, however, the Trips will be stored in a database. This
subsystem can then be used to manage all Trips for many drivers, as well as the maps needed
to generate the Trips. Using a database for this subsystem allows us to perform complex queries
on these data. We add the TripFileStoreSubsystem and the MapDBStoreSubsystem subsystems
to MyTrip to reflect these decisions, as illustrated in Figure 5-12.
Figure 5-12: Subsystem decomposition of MyTrip after deciding on the issue of data stores
(UML component diagram).
Defining access control for a multi-user system is usually more complex. In general, we need
to define for each actor which operations they can access on each shared object. For example,
a bank teller may post credits and debits up to a predefined amount. If the transaction exceeds
the predefined amount, a manager must approve the transaction. Managers can examine the
branch statistics; but cannot access the statistics of other branches. Analysts can access
information across all branches of the corporation, but cannot post transactions on individual
accounts.
In an environment where resources are shared among multiple users, authentication is usually
not sufficient. In the case of a network, for example, it is relatively easy for an intruder to find
tools to snoop the network traffic, including packets generated by other users. Encryption is
used to prevent such unauthorized access. Using an encryption algorithm, we can translate a
message, called “plaintext,” into an encrypted message, called a “ciphertext,” such that even if
intercepted, it cannot be understood. Only the receiver has sufficient knowledge to correctly
decrypt the message, that is, to reverse the original process.
Control flow is a design problem. During analysis control flow is not an issue, because we
assume that all objects are running simultaneously executing operations any time they need
to. During system design, we need to take into account that not every object has the luxury of
running on its own processor.
For example, let us focus on the interfaces of the CommunicationSubsystem of MyTrip. The
responsibility of the CommunicationSubsystem is to transport trips from the
PlanningSubsystem to the RoutingSubsystem. The RoutingSubsystem initiates the connection,
as the PlanningSubsystem is a server that is always available, while the RoutingSubsystem runs
only while the car is powered. This asymmetry leads us to define three interfaces (Figure 5-
13):
• ConnectionManager allows a subsystem to register with theCommunicationSubsystem,
to authenticate, find other nodes, and initiate and close connections.
• TripRequester allows a subsystem to request a list of available trips and download
selected trips.
• TripProvider allows a subsystem to provide a list of trips that are available for the
specified car driver and respond to specific trip requests.
Figure 5-13: Refining the subsystem decompositions by identifying subsystem services (UML
component diagram). The CommunicationSubsystem provides three services for managing
connections, uploading trips, and downloading trips.
For example, we now have a good idea of how MyTrip should work in steady state. We have,
however, not yet addressed how MyTrip is initialized. For example, how are maps loadedinto
the PlanningService? How is MyTrip installed in the car? How does MyTrip know which
PlanningService to connect to? How are drivers added to the PlanningService? We quickly
discover use cases that have not been specified.
We identify boundary use cases by examining each subsystem and each persistent object:
• Configuration. For each persistent object, we examine in which use cases it is created or
destroyed (or archived). For objects that are not created or destroyed in any of the common use
cases (e.g., Maps in the MyTrip system), we add a use case invoked by a system administrator
(e.g., ManageMaps in the MyTrip system).
• Start-up and shutdown. For each component (e.g., a WebServer), we add three use cases
to start, shutdown, and configure the component.
• Exception handling. For each type of component failure (e.g., network outage), we decide
how the system should react (e.g., inform users of the failure).
Figure 5-14: Example outline for the System Design Document (SDD).
The first section of the SDD is an Introduction. Its purpose is to provide a brief overview of
the software architecture and the design goals. It also provides references to other documents
and traceability information (e.g., related requirements analysis document, references to
existing systems, constraints impacting the software architecture).
The second section, Current software architecture, describes the architecture of the system
being replaced. If there is no previous system, this section can be replaced by a survey of current
architectures for similar systems. The purpose of this section is to make explicit the background
information that system architects used, their assumptions, and common issues the new system
will address.
The third section, Proposed system architecture, documents the system design model of the
new system. It is divided into seven subsections:
• Overview presents a bird’s-eye view of the software architecture and briefly describes
the assignment of functionality to each subsystem.
• Subsystem decomposition describes the decomposition into subsystems and the
responsibilities of each. This is the main product of system design.
• Hardware/software mapping describes how subsystems are assigned to hardware and
off-the-shelf components. It also lists the issues introduced by multiple nodes and
software reuse.
• Persistent data management describes the persistent data stored by the system and the
data management infrastructure required for it. This section typically includes the
description of data schemes, the selection of a database, and the description of the
encapsulation of the database.
• Access control and security describes the user model of the system. This section also
describes security issues, such as the selection of an authentication mechanism, the use
of encryption, and the management of keys.
• Global software control describes how the global software control is implemented. In
particular, this section should describe how requests are initiated and how subsystems
synchronize. This section should list and address synchronization and concurrency
issues.
• Boundary conditions describe the start-up, shutdown, and error behavior of the system.
The fourth section, Subsystem services, describes the services provided by each subsystem.
The SDD is written after the initial system decomposition is done. The SDD, moreover, is
updated throughout the process when design decisions are made or problems are discovered.
The first section of the ODD is an introduction to the document. It describes the general trade-
offs made by developers (e.g., buy vs. build, memory space vs. response time), guidelines and
conventions (e.g., naming conventions, boundary cases, exception handling mechanisms), and
an overview of the document.
Interface documentation guidelines and coding conventions are the single most important
factor that can improve communication between developers during object design. These
include a list of rules that developers should use when designing and naming interfaces. These
are examples of such conventions:
• Classes are named with singular nouns.
• Methods are named with verb phrases, fields, and parameters with noun phrases.
• Error status is returned via an exception, not a return value.
Such conventions help developers design interfaces consistently, even if many developers
contribute to the interface specification. Moreover, making these conventions explicit before
object design makes it easier for developers to follow them. In general, these conventions
should not evolve during the project.
The second section of the ODD, Packages, describes the decomposition of subsystems into
packages and the file organization of the code. This includes an overview of each package, its
dependencies with other packages, and its expected usage.
The third section, Class interfaces, describes the classes and their public interfaces. This
includes an overview of each class, its dependencies with other classes and packages, its public
attributes, operations, and the exceptions they can raise.
Testing is the process of finding differences between the expected behavior specified by system
models and the observed behavior of the implemented system. When differences are found,
developers identify the defect causing the observed failure and modify the system to correct it.
From a modeling point of view, testing is the attempt to show that the implementation of the
system is inconsistent with the system models.
Reliability is a measure of success with which the observed behavior of a system conformsto
the specification of its behavior. Software reliability is the probability that a software system
will not cause system failure for a specified time under specified conditions [IEEE Std. 982.2-
1988].
Failure is any deviation of the observed behavior from the specified behavior.
An erroneous state (also called an error) means the system is in a state such that further
processing by the system will lead to a failure, which then causes the system to deviate from
its intended behavior.
A fault, also called “defect” or “bug,” is the mechanical or algorithmic cause of an erroneous
state. The goal of testing is to maximize the number of discovered faults, which then allows
developers to correct them and increase the reliability of the system.
We define testing as the systematic attempt to find faults in a planned way in the implemented
software. Testing requires a thinking, in that developers try to detect faults in the system, that
is, differences between the reality of the system and the requirements.
Fault detection techniques, such as debugging and testing, are used during the development
process to identify erroneous states and find the underlying faults before releasing the system.
In this chapter, we focus on fault detection techniques, including reviews and testing. A review
is the manual inspection of parts or all aspects of the system without actually executing the
system. There are two types of reviews: walkthrough and inspection.
In a code walkthrough, the developer informally presents the code, and associated
documentation of the component to the review team. The review team makes comments on the
mapping of the analysis and object design to the code using use cases and scenarios from the
analysis phase. An inspection is similar to a walkthrough, but the presentation of the
component is formal. Infact, in a code inspection, the developer is not allowed to present the
artifacts (models, code, and documentation). This is done by the review team, which is
responsible for checking the interface and code of the component against the requirements. It
also checks the algorithms for efficiency with respect to the nonfunctional requirements.
Finally, it checks comments about the code and compares them with the code itself to find
inaccurate and incomplete comments. The developer is only present in case the review needs
clarifications about the definition and use of data structures or algorithms. Code reviews have
proven to be effective at detecting faults. In some experiments, up to 85 percent of all identified
faults were found incode reviews.
Debugging assumes that faults can be found by starting from an unplanned failure. The
developer moves the system through a succession of states, ultimately arriving at and
identifying the erroneous state. Once this state has been identified, the algorithmic or
mechanical fault causing this state must be determined.
Testing is a fault detection technique that tries to create failures or erroneous states in a planned
way. The characteristic of a good test model is that it contains test cases that identify faults.
Tests should include a broad range of input values, including invalid inputs and boundary cases,
otherwise, faults may not be detected. Unfortunately, such an approach requires extremely
lengthy testing times for even small systems. Figure 7-1 depicts an overview of testing
activities:
Figure 7-1: Testing activities and their related work products (UML activity diagram).
Swimlanes indicate who executes the test.
• Usability testing tries to find faults in the user interface design of the system. Often,
systems fail to accomplish their intended purpose simply because their users are
confused by the user interface and unwillingly introduce erroneous data.
• Unit testing tries to find faults in participating objects and/or subsystems with respect
to the use cases from the use case model.
• Integration testing is the activity of finding faults by testing individual componentsin
combination. Structural testing is the culmination of integration testing involving all
components of the system. Integration tests and structural tests exploit knowledge from
the SDD (System Design Document) using an integration strategy described in the Test
Plan (TP).
• System testing tests all the components together, seen as a single system to identify
faults with respect to the scenarios from the problem statement and the requirements
and design goals identified in the analysis and system design, respectively:
o Functional testing tests the requirements from the RAD and the user manual.
o Performance testing checks the nonfunctional requirements and additional
design goals from the SDD. Functional and performance testing are done by
developers.
o Acceptance testing and installation testing check the system against the
project agreement and is done by the client, if necessary, with help by the
developers.
6.2Testing Concepts
In this section, we present the model elements used during testing:
• A test component is a part of the system that can be isolated for testing. A component
can be an object, a group of objects, or one or more subsystems.
• A fault, also called bug or defect, is a design or coding mistake that may cause abnormal
component behavior.
• An erroneous state is a manifestation of a fault during the execution of the system. An
erroneous state is caused by one or more faults and can lead to a failure.
• A failure is a deviation between the specification and the actual behavior. A failure is
triggered by one or more erroneous states.
• A test case is a set of inputs and expected results that exercises a test component with
the purpose of causing failures and detecting faults.
• A test stub is a partial implementation of components on which the tested component
depends. A test driver is a partial implementation of a component that depends on the
test component. Test stubs and drivers enable components to be isolated from the rest
of the system for testing.
• A correction is a change to a component. The purpose of a correction is to repair a
fault.
6.3.5 System testing, which focuses on the complete system, its functional and nonfunctional
requirements, and its target environment.
Component Inspection
Inspections find faults in a component by reviewing its source code in a formal meeting.
Inspections can be conducted before or after the unit test. The first structured inspection process
was Michael Fagan’s inspection method [Fagan, 1976]. The inspection is conducted by a team
of developers, including the author of the component, a moderator who facilitates the process,
and one or more reviewers who find faults in the component.
Usability Testing
Usability testing tests the user’s understanding of the system. Usability testing does not
compare the system against a specification. Instead, it focuses on finding differences between
the system and the users’ expectation of what it should do. As it is difficult to define a formal
model of the user against which to test, usability testing takes an empirical approach:
participants representative of the user population find problems by manipulating the user
interface or a simulation thereof. Usability tests are also concerned with user interface details,
such as the look and feel of the user interface, the geometrical layout of the screens, sequence
of interactions, and the hardware.
Developers first formulate a set of test objectives, describing what they hope to learn in the
test. These can include, for example, evaluating specific dimensions or geometrical layout of
the user interface, evaluating the impact of response time on user efficiency, or evaluating
whether the online help documentation is sufficient for novice users. The test objectives are
then evaluated in a series of experiments in which participants are trained to accomplish
predefined tasks (e.g., exercising the user interface feature under investigation). Developers
observe the participants and collect data measuring user performance (e.g., time to accomplish
a task, error rate) and preferences (e.g, opinions and thought processes) to identify specific
problems with the system or collect ideas for improving it.
pulls the levers [Kelly, 1984]. Wizard of Oz prototypes are used for testing natural
language applications, when the speech recognition or the natural language parsing
subsystems are incomplete. A human operator intercepts user queries and rephrases
them in terms that the system understands, without the test user being aware of the
operator. The advantages of prototype tests are that they provide a realistic view of the
system to the user and that prototypes can be instrumented to collect detailed data.
However, prototypes require more effort to build than test scenarios.
• Product test. This test is similar to the prototype test except that a functional version
of the system is used in place of the prototype. A product test can only be conducted
after most of the system is developed. It also requires that the system be easily
modifiable such that the results of the usability test can be taken into account.
Many unit testing techniques have been devised. Below, we describe the most important ones:
equivalence testing, boundary testing, and path testing.
Equivalence testing
This blackbox testing technique minimizes the number of test cases. The possible inputs are
partitioned into equivalence classes, and a test case is selected for each class. The assumption
of equivalence testing is that systems usually behave in similar ways for all members of a class.
To test the behavior associated with an equivalence class, we only need to test one member of
the class. Equivalence testing consists of two steps: identification of the equivalence classes
and selection of the test inputs. For each equivalence class, at least two pieces of data are
selected: a typical input, which exercises the common case, and an invalid input, which
exercises the exception handling capabilities of the component. After all equivalence classes
have been identified, a test input for each class has to be identified that covers the equivalence
class.
For example, consider a method that returns the number of days in a month, given the month
and year (see Figure 7-2). The month and year are specified as integers. By convention, 1
represents the month of January, 2 the month of February, and so on. The range of valid inputs
for the year is 0 to maxInt.
Figure 6-2: Interface for a method computing the number of days in a given month (in Java).
The getNumDaysInMonth() method takes two parameters, a month and a year, both specified
as integers.
We find three equivalence classes for the month parameter: months with 31 days (i.e., 1, 3, 5,
7, 8, 10, 12), months with 30 days (i.e., 4, 6, 9, 11), and February, which can have 28 or 29
days. Non positive integers and integers larger than 12 are invalid values for the month
parameter. Similarly, we find two equivalence classes for the year: leap years and non–leap
years. By specification, negative integers are invalid values for the year. First we select one
valid value for each equivalence class (e.g., February, June, July, 1901, and 1904). Given that
the return value of the getNumDaysInMonth() method depends on both parameters, we
combine these values to test for interaction, resulting in the six equivalence classes displayed
in Table 6-1.
Table 6.1: Equivalence classes and selected valid inputs for testing the getNumDaysInMonth()
method.
Boundary testing
This special case of equivalence testing focuses on the conditions at the boundary of the
equivalence classes. Rather than selecting any element in the equivalence class, boundary
testing requires that the elements be selected from the “edges” of the equivalence class.
In our example, the month of February presents several boundary cases. In general, years that
are multiples of 4 are leap years. Years that are multiples of 100, however, are not leap years,
unless they are also multiple of 400. For example, 2000 was a leap year, whereas 1900 was not.
Both year 1900 and 2000 are good boundary cases we should test. Other boundary cases include
the months 0 and 13, which are at the boundaries of the invalid equivalence class. Table 6-2
displays the additional boundary cases we selected for the getNumDaysInMonth() method.
Table 6-2: Additional boundary cases selected for the getNumDaysInMonth() method.
Path testing
This whitebox testing technique identifies faults in the implementation of the component. The
assumption behind path testing is that, by exercising all possible paths through the code at least
once, most faults will trigger failures. The identification of paths requires knowledge of the
source code and data structures. The starting point for path testing is the flow graph. A flow
graph consists of nodes representing executable blocks and edges representing flow of control.
A flow graph is constructed from the code of a component by mapping decision statements
(e.g., if statements, while loops) to nodes. Statements between each decision (e.g., then block,
else block) are mapped to other nodes. Associations between each node represent the
precedence relationships.
Complete path testing consists of designing test cases such that each edge in the activity
diagram is traversed at least once. This is done by examining the condition associated with
each branch point and selecting an input for the true branch and another input for the false
branch.
Integration testing detects faults that have not been detected during unit testing by focusing
on small groups of components. Two or more components are integrated and tested, and when
no new faults are revealed, additional components are added to the group. If two components
are tested together, we call this a double test. Testing three components together is a triple test,
and a test with four components is called a quadruple test. This procedure allows the testing
of increasingly more complex parts of the system while keeping the location of potential faults
relatively small (i.e., the most recently added component is usually the one that triggers the
most recently discovered faults).
The order in which components are tested, however, can influence the total effort required by
the integration test. A careful ordering of components can reduce the resources needed for the
overall integration test. In the next sections, we discuss horizontal integration testing strategies,
in which components are integrated according to layers, and vertical integration testing
strategies, in which components are integrated according to functions.
Several approaches have been devised to implement a integration testing strategy: big bang
testing, bottom-up testing, and top-down testing. Each of these strategies was originally devised
by assuming that the system decomposition is hierarchical and that each of the components
belongs to hierarchical layers ordered with respect to the “Call” association. These strategies,
however, can be easily adapted to nonhierarchical system decompositions. Figure 7-3 shows a
hierarchical system decomposition that we use for discussing these strategies.
The big bang testing strategy assumes that all components are first tested individually and then
tested together as a single system. The advantage is that no additional test stubs or drivers are
needed. Although this strategy sounds simple, big bang testing is expensive: if a test uncovers
a failure, it is impossible to distinguish failures in the interface from failures within a
component. Moreover, it is difficult to pinpoint the specific component (or combination of
components) responsible for the failure, as all components in the system are potentially
exercised. This results in integration strategies that integrate only a few components at the time.
Figure 6-3: Example of a hierarchal system decomposition with three layers (UML class
diagram, layers represented by packages).
The bottom-up testing strategy first tests each component of the bottom layer individually,
and then integrates them with components of the next layer up. This is repeated until all
components from all layers are combined. Test drivers are used to simulate the components of
higher layers that have not yet been integrated. Note that no test stubs are necessary during
bottom-up testing.
The top-down testing strategy unit tests the components of the top layer first, and then
integrates the components of the next layer down. When all components of the new layer have
been tested together, the next layer is selected. Again, the tests incrementally add one
component at a time. This is repeated until all layers are combined and involved in the test.
Test stubs are used to simulate the components of lower layers that have not yet been integrated.
Note that test drivers are not needed during top-down testing.
Figures 6-4 and 6-5 illustrate the possible combinations of subsystems that can be used during
integration testing. Using a bottom-up strategy, subsystems E, F, and G are united tested first,
then the triple test B-E-F and the double test D-G are executed, and so on. Usinga top-down
strategy, subsystem A is unit tested, then double tests A-B, A-C, and A-D are executed, then
the quad test A-B-C-D is executed, and so on. Both strategies cover the same number of
subsystem dependencies, but exercise them in different order.
Figure 6-4: Bottom-up test strategy. After unit testing subsystems E, F, and G, the bottom up
integration test proceeds with the triple test B-E-F and the double test D-G.
Figure 6-5: Top-down test strategy. After unit testing subsystem A, the integration test proceeds
with the double tests A-B, A-C, and A-D, followed by the quad test A-B-C-D.
6.3.4.3 Pilot testing. Tests of common functionality among a selected group of end users in
the target environment
6.3.4.4 Acceptance testing. Usability, functional, and performance tests performed by the
customer in the development environment against acceptance criteria (from Project
Agreement)
6.3.4.5 Installation testing. Usability, functional, and performance tests performed by the
customer in the target environment. If the system is only installed at a small selected
set of customers it is called a beta test.
Functional testing
Functional testing, also called requirements testing, finds differences between the functional
requirements and the system. Functional testing is a blackbox technique: test cases are derived
from the use case model. In systems with complex functional requirements, it is usually not
possible to test all use cases for all valid and invalid inputs. The goal of the tester is to select
those tests that are relevant to the user and have a high probability of uncovering afailure. Note
that functional testing is different from usability testing, which also focuses on the use case
model. Functional testing finds differences between the use case model and the observed
system behavior, whereas usability testing finds differences between the use case model and
the user’s expectation of the system.
Performance testing
Performance testing finds differences between the design goals selected during system design
and the system. Because the design goals are derived from the nonfunctional requirements, the
test cases can be derived from the SDD or from the RAD. The following tests are performed
during performance testing:
6.3.4.6 Stress testing checks if the system can respond to many simultaneous requests. For
example, if an information system for car dealers is required to interface with 6000
dealers, the stress test evaluates how the system performs with more than 6000
simultaneous users.
6.3.4.7 Volume testing attempts to find faults associated with large amounts of data, such as
static limits imposed by the data structure, or high-complexity algorithms, or high disk
fragmentation.
6.3.4.8 Security testing attempts to find security faults in the system. There are few systematic
methods for finding security faults. Usually this test is accomplished by “tiger teams”
who attempt to break into the system, using their experience and knowledge of typical
security flaws.
6.3.4.9 Timing testing attempts to find behaviors that violate timing constraints described by
the nonfunctional requirements.
6.3.4.10 Recovery testing evaluates the ability of the system to recover from erroneous
states, such as the unavailability of resources, a hardware failure, or a network failure.
After all the functional and performance tests have been performed, and no failures have been
detected during these tests, the system is said to be validated.
Pilot testing
During the pilot test, also called the field test, the system is installed and used by a selected set
of users. Users exercise the system as if it had been permanently installed. No explicit
guidelines or test scenarios are given to the users. Pilot tests are useful when a system is built
without a specific set of requirements or without a specific customer in mind. In this case, a
group of people is invited to use the system for a limited time and to give their feedback to
the developers.
An alpha test is a pilot test with users exercising the system in the development environment.
In a beta test, the pilot test is performed by a limited number of end users in the target
environment. The Internet has made the distribution of software very easy. As a result, beta
tests are more and more common. In fact, some companies now use it as the main method for
system testing their software.
Acceptance testing
Acceptance testing refers to the process of testing the system against the user requirements.
The input to acceptance testing is the software that has been successfully tested at system level.
Acceptance tests should always be done by the user or their representatives. If this is not
possible, they should witness the acceptance tests and sign off the results.
After acceptance testing, the client reports to the project manager which requirements are not
satisfied. Acceptance testing also gives the opportunity for a dialog between the developers and
client about conditions that have changed and which requirements must be added, modified, or
deleted because of the changes. If requirements must be changed, the changes should be
reported in the minutes to the client acceptance review and should form the basis for another
iteration of the software life-cycle process. If the customer is satisfied, the system is accepted,
possibly contingent on a list of changes recorded in the minutes of the acceptancetest.
Installation testing
After the system is accepted, it is installed in the target environment. A good system testing
plan allows the easy reconfiguration of the system from the development environment to the
target environment. The desired outcome of the installation test is that the installed system
correctly addresses all requirements.
In most cases, the installation test repeats the test cases executed during function and
performance testing in the target environment. Some requirements cannot be executed in the
development environment because they require target-specific resources. To test these
requirements, additional test cases have to be designed and performed as part of the installation
test. Once the customer is satisfied with the results of the installation test, system testing is
complete, and the system is formally delivered and ready for operation.
Developers responsible for testing can design test cases as soon as the models they validate
become stable. Functional tests can be developed when the use cases are completed. Unit tests
of subsystems can be developed when their interfaces is defined. Similarly, test stubs and
drivers can be developed when component interfaces are stable. Developing tests early enables
the execution of tests to start as soon as components become available.
The second key element in shortening testing time is to parallelize testing activities. All
component tests can be conducted in parallel; double tests for components in which no faults
were discovered can be initiated while other components are repaired.
For example, the quad test A-B-C-D in Figure 7-6 can be performed as soon as double tests A-
B, A-C, and A-D have not resulted in any failures. These double tests, in turn, can be performed
as soon as unit test A is completed. The quad test A-B-C-D can be performed in parallel with
the double test D-G and the triple test B-E-F, even if tests E, F, or G uncover failures and delay
the rest of the tests.
Testing represents a substantial part of the overall project resources. A typical guideline for
projects is to allocate 25 percent of project resources to testing. However, this number can go
up depending on safety and reliability requirements on the system. Hence, it is critical that test
planning start early, as early as the use case model is stable.
6.4.3 Each execution of each test is documented by a Test Incident Report. The actual results
of the tests and differences from the expected output are recorded.
6.4.4 The Test Report Summary document lists all the failures discovered during the tests that
need to be investigated. From the Test Report Summary, the developers analyze and
prioritize each failure and plan for changes in the system and in the models. These
changes in turn can trigger new test cases and new test executions.
The Test Plan (TP) and the Test Case Specifications (TCS) are written early in the process, as
soon as the test planning and each test case are completed. These documents are under
configuration management and updated as the system models change. Figure 7-7 is an outline
for a Test Plan.
Section 1 of the test plan describes the objectives and extent of the tests. The goal is to provide
a framework that can be used by managers and testers to plan and execute the necessary tests
in a timely and cost-effective manner.
Section 2 explains the relationship of the test plan to the other documents produced during the
development effort such as the RAD, SDD, and ODD (Object Design Document). It explains
how all the tests are related to the functional and nonfunctional requirements, as well as to the
system design stated in the respective documents. If necessary, this section introduces a naming
scheme to establish the correspondence between requirements and tests.
Section 3, focusing on the structural aspects of testing, provides an overview of the system in
terms of the components that are tested during the unit test. The granularity of components and
their dependencies are defined in this section.
Section 4, focusing on the functional aspects of testing, identifies all features and combinations
of features to be tested. It also describes all those features that are not to be tested and the
reasons for not testing them.
Section 5 specifies generic pass/fail criteria for the tests covered in this plan. They are
supplemented by pass/fail criteria in the test design specification.
Section 6 describes the general approach to the testing process. It discusses the reasons for
the selected integration testing strategy. Different strategies are often needed to test different
parts of the system. A UML class diagram can be used to illustrate the dependencies between
the individual tests and their involvement in the integration tests.
Section 7 specifies the criteria for suspending the testing on the test items associated with the
plan. It also specifies the test activities that must be repeated when testing is resumed.
Section 8 identifies the resources that are needed for testing. This should include the physical
characteristics of the facilities, including the hardware, software, special test tools, and other
resources needed (office space, etc.) to support the tests.
Section 9, the core of the test plan, lists the test cases that are used during testing. Each test
case is described in detail in a separate Test Case Specification document. Each execution of
these tests will be documented in a Test Incident Report document. We describe these
documents in more details later in this section.
Section 10 of the test plan covers responsibilities, staffing and training needs, risks and
contingencies, and the test schedule.
The Test Case Specification identifier is the name of the test case, used to distinguish it from
other test cases. Conventions such as naming the test cases from the features or the component
being tested allow developers to more easily refer to test cases.
Section 2 of the TCS lists the components under test and the features being exercised.
Section 4 lists the expected output. This output is computed manually or with a competing
system (such as a legacy system being replaced).
Section 5 lists the hardware and software platform needed to execute the test, including any
test drivers or stubs.
Section 6 lists any constraints needed to execute the test such as timing, load, or operator
intervention.
The Test Incident Report lists the actual test results and the failures that were experienced. The
description of the results must include which features were demonstrated and whether the
features have been met. If a failure has been experienced, the test incident report should contain
sufficient information to allow the failure to be reproduced. Failures from all Test Incident
Reports are collected and listed in the Test Summary Report and then further analyzed and
prioritized by the developers.