OOSE Unit-3

Download as pptx, pdf, or txt
Download as pptx, pdf, or txt
You are on page 1of 129

GITAM School of Technology

19EAI334: OOSE Based Application


Development

1
Unit 3 Syllabus
System Design: Decomposing the System
• System Design Concepts: Subsystems and Classes,
Services and Subsystem Interfaces, Coupling and Cohesion, Layers and Partitions,
Architectural Styles System Design Activities: From Objects to Subsystems,
Analysis Model for a Route Planning System, Identifying Design Goals,
Identifying Subsystems
Static Modelling:
• Package Diagrams, Composite Structures, Component Diagrams, Deployment
Diagrams, System Design Activities: Addressing Design Goals: Mapping
Subsystems to Processors and Components, Identifying and Storing Persistent
Data, Providing Access Control, Designing the Global Control Flow, Identifying
Services, Identifying Boundary Conditions, Reviewing System Design

2
System Design
• 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.

3
System Design: Decomposing
the System
System design is decomposed into several activities, each addressing part of the
overall problem of decomposing the system:
• Identify design goals. Developers identify and prioritize the qualities of the
system that they should optimize.
• Design the initial subsystem decomposition. Developers decompose the system
into smaller parts based on the use case and analysis models. Developers use
standard architectural styles as a starting point during this activity.
• Refine the subsystem decomposition to address the design goals. The initial
decomposition usually does not satisfy all design goals. Developers refine it until
all goals are satisfied.

4
Introduction: A Floor Plan Example
• 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.

5
• During system design, we focus on the processes, data structures, and software
and hardware components necessary to implement it.
• The challenge of system design is that many conflicting criteria and constraints
must be met when decomposing the system.

• Figure 6-1 shows three successive revisions to a floor plan for a residential house.
We set out to satisfy the following constraints:
1. This house should have two bedrooms, a study, a kitchen, and a living room area.
2. The overall distance the occupants walk every day should be minimized.
3. The use of daylight should be maximized

6
Figure 6-1 Example of floor plan
design. Three successive versions show
how we minimize walking distance and
take advantage of sunlight.

7
• In the first version of the floor plan (at the top of Figure 6-1), we find that the
dining room is too far from the kitchen. To address this problem, we exchange it
with bedroom 2 (see gray arrows in Figure 6-1). This also has the advantage of
moving the living room to the south wall of the house.

• In the second revision, we find that the kitchen and the stairs are too far from the
entrance door.

• To address this problem, we move the entrance door to the north wall. This allows
us to reorient bedroom 2 and move the bathroom closer to both bedrooms. The
living area is increased, and we satisfied all original constraints.

8
• The design of a floor plan in architecture is similar to system design in software
engineering (Table 6-1).

9
An Overview of System Design
• Analysis results in the requirements model described by the following products:

• a set of nonfunctional requirements and constraints, such as maximum


response time, minimum throughput, reliability, operating system platform,
and so on
• a use case model, describing the system functionality from the actors’ point of
view
• an object model, describing the entities manipulated by the system
• a sequence diagram for each use case, showing the sequence of interactions
among objects participating in the use case.

10
System design results in the following products:

• design goals, describing the qualities of the system that developers should
optimize

• software architecture, describing the subsystem decomposition in terms of


subsystem responsibilities, dependencies among subsystems, subsystem mapping
to hardware, and major policy decisions such as control flow, access control, and
data storage

• boundary use cases, describing the system configuration, startup, shutdown, and
exception handling issues.

11
12
Figure 6-2 The activities of system design (UML activity diagram)
System Design Concepts
• Subsystems provide services to other subsystems
• A service is a set of related operations that share a common purpose. During system
design, we define the subsystems in terms of the services they provide. Later, during
object design, we define the subsystem interface in terms of the operations it
provides.
• Coupling measures the dependencies between two subsystems, whereas cohesion
measures the dependencies among classes within a subsystem. Ideal subsystem
decomposition should minimize coupling and maximize cohesion.
• Layering allows a system to be organized as a hierarchy of subsystems, each
providing higher-level services to the subsystem above it by using lower-level
services from the subsystems below it.
• Partitioning organizes subsystems as peers that mutually provide different services
13
to each other.
Subsystems and Classes
• To reduce the complexity, we define a system into application domain and
solution domain.
• In order to reduce the complexity of the application domain, we identified
smaller parts called “classes” and organized them into packages.
• Similarly, to reduce the complexity of the solution domain, we decompose a
system into simpler parts, called “subsystems,” which are made of a number of
solution domain classes.
• A subsystem is a replaceable part of the system with well-defined interfaces that
encapsulates the state and behavior of its contained classes.
• A subsystem typically corresponds to the amount of work that a single developer
or a single development team can tackle.

14
• By decomposing the system into relatively independent subsystems, concurrent
teams can work on individual subsystems with minimal communication overhead.
• In the case of complex subsystems, we recursively apply this principle and
decompose a subsystem into simpler subsystems (see Figure 6-3).

Figure 6-3 Subsystem decomposition (UML class diagram).

15
• This subsystem decomposition is depicted in Figure 6-4 using UML component
Diagram.
• 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 layer.
• A physical component corresponds to a subsystem that has an explicit run-
time equivalent, for example, a database server.

16
Figure 6-4 Subsystem decomposition for an accident management system (UML component diagram).
Subsystems are shown as UML components. Dashed arrows indicate dependencies between subsystems. 17
• Several programming languages (e.g., Java and Modula-2) provide constructs
for modeling subsystems (packages in Java, modules in Modula-2).

• In other languages, such as C or C++, subsystems are not explicitly modeled,


so developers use conventions for grouping classes (e.g., a subsystem can be
represented as a directory containing all the files that implement the
subsystem).

• Whether or not subsystems are explicitly represented in the programming


language, developers need to document carefully the subsystem
decomposition as subsystems are usually realized by different teams.

18
Services and Subsystem
Interfaces
• A service is a set of related operations that share a common purpose.
• A subsystem providing a notification service, for example, defines operations to send
notices, look up notification channels, and subscribe and unsubscribe to a channel.
• The set of operations of a subsystem that are available to other subsystems form the
subsystem interface.
• The subsystem interface includes the name of the operations, their parameters,
their types, and their return values.
• System design focuses on defining the services provided by each subsystem, that is,
enumerating the operations, their parameters, and their high-level behavior.
• Object design will focus on the application programmer interface (API), which
refines and extends the subsystem interfaces. The API also includes the type of the
parameters and the return value of each operation.
19
• 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 6-5 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.
20
Figure 6-5 Services provided by the ResourceManagement subsystem (UML component
diagram, ball-and-socket notation depicting provided and required interface

21
Coupling and Cohesion
• Coupling is the measure of dependencies between two subsystems.
• If two subsystems are loosely coupled, they are relatively independent, so
modifications to one of the subsystems will have little impact on the other.
• If two subsystems are strongly coupled, modifications to one subsystem is
likely to have impact on the other.

• A desirable property of a subsystem decomposition is that subsystems are as


loosely coupled as reasonable. This minimizes the impact that errors or future
changes in one subsystem have on other subsystems.

22
• Consider, for example, the emergency response system depicted in Figure 6-4 (Earlier
slides) . During system design, we decide to store all persistent data (i.e., all data that
outlive a single execution of the system) in a relational database. This leads to an
additional subsystem called Database (Figure 6-6).
• Initially, we design the interface of the database subsystem so that subsystems that need
to store data simply issue commands in the native query language of the database, such as
SQL. For example, the IncidentManagement subsystem issues SQL queries to store and
retrieve records representing Incidents in the database.
• This leads to a situation with a high coupling among the Database subsystem and the
three client subsystems (i.e., IncidentManagement, ResourceManagement, and
MapManagement) that need to store and retrieve data, as any change in the way the data
is stored will require changes in the client subsystems.
23
• For example, if we change database vendors we will have to change the
subsystems to use a different dialect of the query language.
• To reduce the coupling among these four subsystems, we decide to create a new
subsystem, called Storage, which shields the Database from the other subsystems.
• In this alternative, the three client subsystems use services provided by the
Storage subsystem, which is then responsible for issuing queries in SQL to the
Database subsystem.
• If we decide to change database vendors or to use a different storage mechanism
(e.g., flat files), we only need to change the Storage subsystem. Hence, the overall
coupling of the subsystem decomposition has been decreased.

24
Figure 6-6 Example of reducing the
coupling of subsystems (UML component
diagram, subsystems FieldOfficerInterface,
DispatcherInterface, and Notification
omitted for clarity). Alternative 1 depicts a
situation where all subsystems access the
database directly, making them vulnerable
to changes in the interface of the Database
subsystem. Alternative 2 shields the
database with an additional subsystem
(Storage). In this situation, only one
subsystem will need to change if there are
changes in the interface of the Database
subsystem. The assumption behind this
design change is that the Storage
subsystem has a more stable interface than
the Database subsystem.

25
• Cohesion is the measure of dependencies within a subsystem. If a subsystem
contains many objects that are related to each other and perform similar tasks, its
cohesion is high. If a subsystem contains a number of unrelated objects, its
cohesion is low. A desirable property of a subsystem decomposition is that it leads
to subsystems with high cohesion.
• For example, consider a decision tracking system for recording design problems,
discussions, alternative evaluations, decisions, and their implementation in terms
of tasks (Figure 6-7).
• DesignProblem and Option represent the exploration of the design space: we
formulate the system in terms of a number of DesignProblems and document each
Option they explore. The Criterion class represents the qualities in which we are
interested. Once we assessed the explored Options against desirable Criteria, we
implement Decisions in terms of Tasks. Tasks are recursively decomposed into
Subtasks small enough to be assigned to individual developers. We call atomic
tasks ActionItems.
26
Figure 6-7 Decision tracking system (UML component diagram). The DecisionSubsystem has a low cohesion: The
27
classes Criterion, Option, and DesignProblem have no relationships with Subtask, ActionItem, and Task
• The decision tracking system is small enough that we could lump all these classes
into one subsystem called DecisionSubsystem (see Figure 6-7). However, we
observe that the class model can be partitioned into two subgraphs. One, called the
RationaleSubsystem, contains the classes DesignProblem, Option, Criterion, and
Decision. The other, called the PlanningSubsystem, contains Task, Subtask, and
ActionItem (see Figure 6-8).

• Both subsystems have a higher cohesion than the original DecisionSubsystem.


This enables us to reuse each part independently, as other subsystems need only
the planning part or the rationale part. Moreover, the resulting subsystems are
smaller than the original subsystem, enabling us to assign each of them to a single
developer. The coupling between the subsystems is relatively low, with only one
association between the two subsystems.

28
Figure 6-8 Alternative subsystem decomposition for the decision tracking system of Figure 6-7 (UML component diagram,
ball-and-socket notation). The cohesion of the RationaleSubsystem and the PlanningSubsystem is higher than the
cohesion of the original DecisionSubsystem. The RationaleSubsystem and PlanningSubsystem subsystems are also simpler.
However, we introduced an interface for realizing the relationship between Task and Decision. 29
Layers and Partitions
• A hierarchical decomposition of a system yields an ordered set of layers.
• A layer is a grouping of subsystems providing related services, possibly realized
using services from another layer.
• Layers are ordered such that each layer can depend only on lower level layers and
has no knowledge of the layers above it. The layer that does not depend on any
other layer is called the bottom layer, and the layer that is not used by any other
is called the top layer (Figure 6-9).
• In a closed architecture, each layer can access only the layer immediately below
it. In an open architecture, a layer can also access layers at deeper levels.

30
Figure 6-9 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
31
• An example of a closed architecture is the Reference Model of Open Systems
Interconnection (in short, the OSI model), which is composed of seven layers. Each layer
is responsible for performing a well-defined function. In addition, each layer provides its
services by using services of the layer below (Figure 6-10).
architecture: the OSI model (UML component
Figure 6-10 An example of closed

network services into seven layers, each


diagram). The OSI model decomposes

responsible for a different level of abstraction.

32
• Until recently, only the four bottom layers of the OSI model were well
standardized.
• Unix and many desktop operating systems, for example, provide interfaces to
TCP/IP that implemented the Transport, Network, and Datalink layers.
• The application developer still needed to fill the gap between the Transport layer
and the Application layer.
• With the growing number of distributed applications, this gap motivated the
development of middleware such as CORBA and Java RMI. CORBA and Java
RMI allow us to access remote objects transparently by sending messages to them
as messages are sent to local objects, effectively implementing the Presentation
and Session layers (see Figure 6-11).

33
Figure 6-11 An example of closed architecture (UML component diagram). CORBA enables the access of objects
implemented in different languages on different hosts. CORBA effectively implements the Presentation and Session layers
34
of the OSI stack.
• X11 provides low-level drawing
facilities.
• AWT is the low-level interface provided
by Java to shield programmers from the
window system.
• Swing provides a large number of
sophisticated user interface objects.
• Some Applications often bypass the
Swing layer.

Figure 6-12 An example of open architecture: the Swing user interface


library on an X11 platform (UML component diagram).
35
• 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 fuel 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. 36
Architectural Styles
• As the complexity of systems increases, the specification of system
decomposition is critical. It is difficult to modify or correct weak decomposition
once development has started, as most subsystem interfaces would have to
change.
• In recognition of the importance of this problem, the concept of software
architecture has emerged.
• A software architecture includes system decomposition, global control flow,
handling of boundary conditions, and inter-subsystem communication
protocols.
• Architectural styles can be used as a basis for the architecture of different systems.

37
Repository
• In the repository architectural style (see Figure 6-13), subsystems access and modify a
single data structure called the central repository.
• Subsystems are relatively independent and interact only through the repository. Control
flow can be dictated either by the central repository (e.g., triggers on the data invoke
peripheral systems) or by the subsystems (e.g., independent flow of control and
synchronization through locks in the repository).

Figure 6-13 Repository architectural style (UML component diagram). Every Subsystem depends only on a
central data structure called the Repository. The Repository has no knowledge of the other Subsystems.
38
• Repositories are typically used for database management systems, such as a
payroll system or a bank system. The central location of the data makes it easier to
deal with concurrency and integrity issues between subsystems.
• Compilers and software development environments also follow a repository
architectural style (Figure 6-14). The different subsystems of a compiler access
and update a central parse tree and a symbol table. Debuggers and syntax editors
access the symbol table as well.
• The repository subsystem can also be used for implementing the global control
flow. In the compiler example of Figure 6-14, each individual tool (e.g., the
compiler, the debugger, and the editor) is invoked by the user. The repository only
ensures that concurrent accesses are serialized. Conversely, the repository can be
used to invoke the subsystems based on the state of the central data structure.
These systems are called “blackboard systems”. The HEARSAY II speech
understanding system [Erman et al., 1980], one of the first blackboard systems,
invoked tools based on the current state of the blackboard.
39
Figure 6-14 An instance of the
repository architectural style (UML
component diagram). A Compiler
incrementally generates a ParseTree
and a SymbolTable that can be used by
SourceLevelDebuggers and
SyntaxEditors.

Repositories are well suited for applications with constantly changing, complex data processing
tasks. Once a central repository is well defined, we can easily add new services in the form of
additional subsystems.
The main disadvantage of repository systems is that the central repository can quickly become a
bottleneck, both from a performance aspect and a modifiability aspect. The coupling between
each subsystem and the repository is high, thus making it difficult to change the repository
without having an impact on all subsystems. 40
Model/View/Controller
• In the Model/View/Controller (MVC) architectural style (Figure 6-15), subsystems are
classified into three different types: model subsystems maintain domain knowledge, view
subsystems display it to the user, and controller subsystems manage the sequence of
interactions with the user. The model subsystems are developed such that they do not depend
on any view or controller subsystem. Changes in their state are propagated to the view
subsystem via a subscribe/notify protocol. The MVC is a special case of the repository where
Model implements the central data structure and control objects dictate the control flow.

41
• For example, Figures 6-16 and 6-17
illustrate the sequence of events that
occur in an MVC architectural style.
• Figure 6-16 displays two views of a
file system. The bottom window lists
the content of the Comp-Based
Software Engineering folder,
including the file
9DesignPatterns2.ppt. The top
window displays information about
this file. Figure 6-16 An example of MVC architectural style. The “model” is the
• The name of the file filename 9DesignPAtterns2.ppt. One “view” is a window titled CBSE,
which displays the contents of a folder containing the file
9DesignPatterns2.ppt appears in 9DesignPatterns2.ppt. The other “view” is window called
three places: in both windows and in 9DesignPatterns2.ppt Info, which displays information related to the
the title of the top window. file. If the file name is changed, both views are updated by the
“controller.”
42
• Assume now that we change the
name of the file to
9DesignPatterns.ppt.
• Figure 6-17 shows the sequence of
events:
1. The InfoView and the FolderView both
subscribe for changes to the File models
they display (when they are created).
2. The user types the new name of the file.
3. The Controller, the object responsible for
interacting with the user during file name
changes, sends a request to the Model.
4. The Model changes the file name and
notifies all subscribers of the change.
5. Both InfoView and FolderView are updated,
so the user sees a consistent change.

43
• The subscription and notification functionality associated with this sequence of
events are usually realized with an Observer design pattern. The Observer design
pattern allows the Model and the View objects to be further decoupled by
removing direct dependencies from the Model to the View.
• The rationale between the separation of Model, View, and Controller is that user
interfaces, i.e., the View and the Controller, are much more often subject to
change than is domain knowledge, i.e., the Model. Moreover, by removing any
dependency from the Model on the View with the subscription/notification
protocol, changes in the views (user interfaces) do not have any effect on the
model subsystems.
• MVC is well suited for interactive systems, especially when multiple views of the
same model are needed. MVC can be used for maintaining consistency across
distributed data; however it introduces the some performance bottleneck as for
other repository styles.

44
Client/server
• In the client/server architectural style (Figure 6-18), a subsystem, the server,
provides services to instances of other subsystems called the clients, which are
responsible for interacting with the user. The request for a service is usually done via
a remote procedure call mechanism or a common object broker (e.g., CORBA,
Java RMI, or HTTP). Control flow in the clients and the servers is independent
except for synchronization to manage requests or to receive results.

45
An information system with a central database is an example of a client/server
architectural style. The clients are responsible for receiving inputs from the user,
performing range checks, and initiating database transactions when all necessary data
are collected. The server is then responsible for performing the transaction and
guaranteeing the integrity of the data. In this case, a client/server architectural style is a
special case of the repository architectural style in which the central data structure is
managed by a process. Client/server systems, however, are not restricted to a single
server. On the World Wide Web, a single client can easily access data from thousands of
different servers (Figure 6-19).

46
Peer-to-peer
• A peer-to-peer architectural style (see Figure 6-20) is a generalization of the client/
server architectural style in which subsystems can act both as client or as servers, in
the sense that each subsystem can request and provide services. The control flow within
each subsystem is independent from the others except for synchronizations on requests.
• An example of a peer-to-peer architectural style is a database that both accepts requests
from the application and notifies to the application whenever certain data are changed
(Figure 6-21). Peer-to-peer systems are more difficult to design than client/server
systems because they introduce the possibility of deadlocks and complicate the control
flow.

47
• Callbacks are operations that are temporary and customized for a specific purpose. For
example, a DBUser peer in Figure 6-21 can tell the DBMS peer which operation to
invoke upon a change notification. The DBUser then uses the callback operation
specified by each DBUser for notification when a change occurs. Peer-to-peer systems
in which a “server” peer invokes “client” peers only through callbacks are often
referred to as client/server systems, even though this is inaccurate since the “server”
can also initiate the control flow.
48
Three-tier
The three-tier architectural style organizes subsystems into three layers (Figure 6-22):
• The interface layer includes all boundary objects that deal with the user, including windows, forms, web
pages, and so on.
• The application logic layer includes all control and entity objects, realizing the processing, rule checking,
and notification required by the application.
• The storage layer realizes the storage, retrieval, and query of persistent objects.

The three-tier architectural style was initially described in the 1970s for information systems. The storage
layer, an analog to the Repository subsystem in the repository architectural style, can be shared by several
different applications operating on the same data. In turn, the separation between the interface layer and the
application logic layer enables the development or modification of different user interfaces for the 49same
Four-tier
• The four-tier architectural style is a three-tier
architecture in which the Interface layer is
decomposed into a Presentation Client layer and
a Presentation Server layer (Figure 6-23). The
Presentation Client layer is located on the user
machines, whereas the Presentation Server layer
can be located on one or more servers. The four-tier
architecture enables a wide range of different
presentation clients in the application, while
reusing some of the presentation objects across
clients. For example, a banking information system
can include a host of different clients, such as a
Web browser interface for home users, an
Automated Teller Machine, and an application
client for bank employees. Forms shared by all
three clients can then be defined and processed in
the Presentation Server layer, thus removing
redundancy across clients.
50
Pipe and filter
• In the pipe and filter architectural style (Figure 6-24), subsystems process data
received from a set of inputs and send results to other subsystems via a set of
outputs. The subsystems are called “filters,” and the associations between the
subsystems are called “pipes.” Each filter knows only the content and the format
of the data received on the input pipes, not the filters that produced them. Each
filter is executed concurrently, and synchronization is accomplished via the pipes.
The pipe and filter architectural style is modifiable: filters can be substituted for
others or reconfigured to achieve a different purpose.

Figure 6-24 Pipe and filter architectural style (UML class diagram). A Filter can have many inputs and outputs. A
Pipe connects one of the outputs of a Filter to one of the inputs of another Filter. 51
• The best known example of a pipe and filter architectural style is the Unix shell.
Most filters are written such that they read their input and write their results on
standard pipes. This enables a Unix user to combine them in many different ways.
• Figure 6-25 shows an example made of four filters. The output of ps (process
status) is fed into grep (search for a pattern) to remove all the processes that are not
owned by a specific user. The output of grep (i.e., the processes owned by the user)
is then sorted by sort and sent to more, which is a filter that displays its input to a
terminal, one screen at a time.

Figure 6-25 Unix command line as an instance of the pipe and filter style (UML activity diagram).
52
System Design Activities: From
Objects to Subsystems
• System design consists of transforming the analysis model into the design
model that takes into account the nonfunctional requirements described in the
requirements analysis document.
• We illustrate these activities with an example, MyTrip, a route planning system
for car drivers.
• We start with the analysis model from MyTrip; then we describe the
identification of design goals and the design of an initial system decomposition.

53
Starting Point: Analysis Model for a
Route Planning System
• Using MyTrip, a driver can plan a trip from a home computer by contacting a trip-
planning service on the Web (PlanTrip in Figure 6-26). The trip is saved for later
retrieval on the server. The trip-planning service must support more than one
driver.

54
• 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 6-27).

55
• We perform the analysis for the MyTrip system and obtain the model in Figure 6-28.

56
• In addition, during requirements elicitation, our client specified the following
nonfunctional requirements for MyTrip:

57
Identifying Design Goals
• The definition of design goals is the first step of system design. It identifies the
qualities that our system should focus on. Many design goals can be inferred from the
nonfunctional requirements or from the application domain. Others will have to be
elicited from the client. It is, however, necessary to state them explicitly such that
every important design decision can be made consistently following the same set of
criteria.

• For example, in the light of the nonfunctional requirements for MyTrip, 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.
58
The following box summarizes the design goals we identified.

In general, we can select design goals from a long list of highly desirable qualities. Tables
6-2 through 6-6 list a 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 59
• Performance criteria (Table 6-2) include the speed and space requirements
imposed on the system.
• Should the system be responsive, or should it accomplish a maximum number of
tasks? Is memory space available for speed optimizations, or should memory be
used sparingly?

60
• Dependability criteria (Table 6-3) determine how much effort should be
expended in minimizing system crashes and their consequences. How often can
the system crash? How available to the user should the system be? Should the
system tolerate errors and failures? Are security risks associated with the system
environment? Are safety issues associated with system crashes?

61
• Cost criteria (Table 6-4) include the cost to develop the system, to deploy it, and
to administer it. Note that cost criteria not only include design considerations but
managerial ones, as well. When the system is replacing an older one, the cost of
ensuring backward compatibility or transitioning to the new system has to be
taken into account. There are also trade-offs between different types of costs such
as development cost, end user training cost, transition costs, and maintenance
costs. Maintaining backward compatibility with a previous system can add to the
development cost while reducing the transition cost.

62
• Maintenance criteria (Table 6-5) determine how difficult it is to change the
system after deployment. How easily can new functionality be added? How easily
can existing functions be revised? Can the system be adapted to a different
application domain? How much effort will be required to port the system to a
different platform? These criteria are harder to optimize and plan for, as it is
seldom clear how successful the project will be and how long the system will be
operational.

63
• End user criteria (Table 6-6) include qualities that are desirable from a users’
point of view, but have not yet been covered under the performance and
dependability criteria. Is the software difficult to use and to learn? Can the users
accomplish needed tasks on the system? Often these criteria do not receive much
attention, especially when the client contracting the system is different from its
users.

64
• 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. Typically, developers need to
prioritize design goals and trade them off against each other as well as against managerial goals as the project
runs behind schedule or over budget. Table 6-7 lists several possible trade-offs.

65
Identifying Subsystems
• Finding subsystems during system design is similar to finding objects during analysis.
• Moreover, subsystem decomposition is constantly revised whenever new issues are
addressed: several subsystems are merged into one subsystem, a complex subsystem is
split into parts, and some subsystems are added to address new functionality. The
first iterations over subsystem decomposition can introduce drastic changes in the
system design model. These are often best handled through Brainstorming.
• 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 between both 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 6-29).
66
Figure 6-29 Initial subsystem decomposition for MyTrip (UML class diagram).
67
• 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.

68
Encapsulating subsystems with the Facade
design pattern
• Subsystem decomposition reduces the
complexity of the solution domain by
minimizing coupling among subsystems.
• The Facade design pattern allows us to
further reduce dependencies between
classes by encapsulating a subsystem with
a simple, unified interface.
• For example, in Figure 6-30, the Compiler
class is a façade hiding the classes
CodeGenerator, Optimizer, ParseNode,
Parser, and Lexer. The façade provides
access only to the public services offered by
the subsystem and hides all other details,
effectively reducing coupling between
subsystems. 69
Static Modelling: Package
Diagrams
• A package is used as a container to organize the elements present in the system into
a more manageable unit. It is very useful to represent the system’s architecture and
design as a cohesive unit and a concise manner.
• Package: The basic building block of the Package Diagram is a Package. It is a
container for organizing different diagram elements such as classes, interfaces, etc. It
is represented in the Diagram in a folder-like icon with its name.
• NameSpace: It represents the package’s name in the diagram. It generally appears on
top of the package symbol which helps to uniquely identify the package in the
diagram.
• Package Merge: It is a relationship that signifies how a package can be merged or
combined. It is represented as a direct arrow between two packages, signifying that
the contents of one package can be merged with the contents of the other.

70
• Package Import: It is another relationship that shows one package’s access
to the contents of a different package. It is represented as a Dashed Arrow.
• Dependency: Dependencies are used to show that there might be some
element or package that can be dependent upon any other element or
package, meaning that changing anything of that package will result in
alteration of the contents of the other package which is dependent upon the
first one.
• Element: An element can be a single unit inside of a package, it can be a
class, an interface or subsystems. This packages are connected and reside
inside of packages that hold them.
• For example, if we consider a Class, then there can be many functions inside
it and many variables or subclass can also be present, all of these are
considered as an Element of that Class and they are connected with the
Main Class, without the existence of the main class, they will also not exist
or have no relevance.
71
• Constraint: It is like a condition or requirement set related to a package. It is
represented by curly braces.

Subsystem

The above is the notation of a simple Package. The above notation is used to represent
subsystem.

72
• Dependency

The above dashed arrow sign is used to show the dependency among two elements or
two packages.

• Import
The above notation is of the Import, here it also
uses a dashed arrow line but the difference is, the
word <<import>> is being written to represent
the below package or function or element has
been imported from the above package.

73
• Merge

This notation above denotes that the


Package 1 can be merged with
• Package Relationships Package 2
Package Merge Relationship
This relationship is used to represent that the contents of a package can be merged with
the contents of another package. This implies that the source and the target package has
some elements common in them, so that they can be merged together.

74
• Package Dependency Relationship
• A package can be dependent on other
different packages, signifying that the
source package is somehow dependent
on the target package.

• Package Import Relationship


• This relationship is used to represent that
a package is importing another package
to use. It signifies that the importing
package can access the public contents of
the imported package.

75
• Package Access Relationship
• This type of relationship signifies that there is a access relationship between two
or more packages, meaning that one package can access the contents of another
package without importing it.

The above diagram depicts the Access relationship between the


Front End and Back End services. It is much needed that a front
end service can easily access the important Back End services
to carry out any operation.

76
Composite Structures
• A composite structure diagram is a
UML structural diagram that
provides a logical overview of all
or part of a software system.
• It acts as a look inside a given
structured classifier, defining its
configuration classes, interfaces,
packages, and the relationships
between them at a micro-level.

77
Basic components of a composite structure diagram

78
79
80
Component Diagrams
• Component diagrams range from simple and high level to detailed and complex.
Either way, you'll want to familiarize yourself with the appropriate UML symbols.
The following are shape types that you will commonly encounter when reading
and building component diagrams:

81
82
83
84
85
Example:

86
Deployment Diagrams
• UML deployment diagrams are used to depict the relationship among run-time
components and nodes.
• Components are self-contained entities that provide services to other components
or actors.
• A Web server, for example, is a component that provides services to Web
browsers. A Web browser such as Safari is a component that provides services to a
user.
• A node is a physical device or an execution environment in which components are
executed.

87
• 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 7-2 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.

88
Figure 7-2 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.
89
• The deployment diagram in Figure 7-2 focuses on the allocation of components to
nodes and provides a high-level view of each component. Components can be
refined to include information about the interfaces they provide and the classes
they contain. Figure 7-3 illustrates the WebServer component and its containing
classes.

Figure 7-3 Refined view of the WebServer component (UML component diagram). WebServer provides an http
interface and requires a jdbc interface. The http interface is realized by the HttpService class.
90
System Design Activities:
Addressing Design Goals
We describe the activities needed to ensure that subsystem decomposition addresses
all the nonfunctional requirements and can account for any constraints during the
implementation phase.
We have identified a set of design goals and designed an initial subsystem
decomposition for MyTrip. Here, we refine the subsystem decomposition by
• Mapping Subsystems to Processors and Components
• Identifying and Storing Persistent Data
• Providing Access Control
• Designing the Global Control Flow
• Identifying Services
• Identifying Boundary Conditions
• Reviewing the System Design Model 91
Mapping Subsystems to Processors and
Components
• Selecting a hardware configuration and a platform
• Many systems run on more than one computer and depend on access to an intranet or to the Internet.
The use of multiple computers can address high-performance needs and interconnect multiple
distributed users. Consequently, we need to examine carefully the allocation of subsystems to computers
and the design of the infrastructure for supporting communication between subsystems. These
computers are modeled as nodes in UML deployment diagrams. Because the hardware mapping activity
has significant impact on the performance and complexity of the system, we perform it early in system
design.
• 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.
92
• In MyTrip, we deduce from the requirements that PlanningSubsystem and RoutingSubsystem run
on two different nodes: the former is a Web-based service on an Internet host, the latter runs on the
onboard computer. Figure 7-4 illustrates the hardware allocation for MyTrip with two devices
called :OnBoardComputer and :WebHost, and an execution environment called :Apache.
• 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 7-4 Allocation of MyTrip subsystems to devices and execution environments (UML deployment
diagram). RoutingSubsystem runs on the OnBoardComputer; PlanningSubsystem runs on an Apache server.
93
• Allocating objects and subsystems to nodes
• Once the hardware configuration has been defined and the virtual machines selected, objects and
subsystems are assigned to nodes. This often triggers the identification of new objects and subsystems for
transporting data among the nodes.
• 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 alternates 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. These proxies are
examples of the Proxy design pattern.
• 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 7-5.
94
• In general, allocating subsystems to
hardware nodes enables us to
distribute functionality and
processing power where it is most
needed.
• Unfortunately, it also introduces
issues related to storing, transferring,
replicating, and synchronizing data
among subsystems.
• For this reason, developers also
select the components they will use
for developing the system.

Figure 7-5 Revised design model for MyTrip (UML component diagram)

95
Identifying and Storing Persistent Data
• Persistent data outlive a single execution of the system. For example, at the end
of the day, an author saves his work into a file on a word processor. The file can
then be reopened later. The word processor need not run for the file to exist.
Similarly, information related to employees, their employment status, and their
paychecks live in a database management system. This allows all the programs that
operate on employee data to do so consistently. Moreover, storing data in a database
enables the system to perform complex queries on a large data set (e.g., the records
of several thousand employees).
• Where and how data is stored in the system affects system decomposition. In
some cases, for example, in a repository architectural style, a subsystem can be
completely dedicated to the storage of data. The selection of a specific database
management system can also have implications on the overall control strategy and
concurrency management.
96
• 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 Figure 7-6 Subsystem decomposition of MyTrip after deciding
the TripFileStoreSubsystem and the on the issue of data stores (UML component diagram).
MapDBStoreSubsystem subsystems to MyTrip to
reflect these decisions, as illustrated in Figure 7-6.
97
• Identifying persistent objects
• First, we identify which data must be persistent. The entity objects identified during
analysis are obvious candidates for persistency. In MyTrip, Trips and their related
classes (Crossing, Destination, PlanningService, and Segment) must be stored. Note that
not all entity objects must be persistent. For example, Location and Direction are
constantly recomputed as the car moves.
• Persistent objects are not limited to entity objects. In a multi-user system, information
related to users (e.g., Drivers) is persistent, as well as some attributes of the boundary
objects (e.g., window positions, user interface preferences, state of long-running control
objects). In general, we can identify persistent objects by examining all the classes that
must survive system shutdown, either in case of a controlled shutdown or an unexpected
crash. The system will then restore these long-lived objects by retrieving their attributes
from storage during system initialization or on demand as the persistent objects are
needed.

98
• Selecting a storage management strategy
Once all persistent objects are identified, we need to decide how these objects
should be stored. The decision for storage management is more complex and is
usually dictated by nonfunctional requirements:
• Should the objects be retrieved quickly?
• Must the system perform complex queries to retrieve these objects?
• Do objects require a lot of memory or disk space?
In general, there are currently three options for storage management:
• Flat files. Files are the storage abstractions provided by operating systems. The application stores
its data as a sequence of bytes and defines how and when data should be retrieved. The file
abstraction is relatively low level and enables the application to perform a variety of size and
speed optimizations. Files, however, require the application to take care of many issues, such as
concurrent access and loss of data in case of system crash.

99
• Relational database. A relational database provides data abstraction at a higher level than flat
files. Data are stored in tables that comply with a predefined type called a schema. Each column in
the table represents an attribute. Each row represents a data item as a tuple of attribute values.
Several tuples in different tables are used to represent the attributes of an individual object.
Mapping complex object models to a relational schema is challenging. Specialized methods
provide a systematic way of performing this mapping. Relational databases also provide services
for concurrency management, access control, and crash recovery. Relational databases have been
used for a while and are a mature technology. Although scalable and ideal for large data sets, they
are relatively slow for small data sets and for unstructured data (e.g., images, natural language
text).
• Object-oriented database. An object-oriented database provides services similar to a relational
database. Unlike a relational database, it stores data as objects and associations. In addition to
providing a higher level of abstraction (and thus reducing the need to translate between objects
and storage entities), object-oriented databases provide developers with inheritance and abstract
data types. Object-oriented databases significantly reduce the time for the initial development of
the storage subsystem. However, they are slower than relational databases for typical queries and
are more difficult to tune.

100
• Figure 7-7 summarizes trade-offs when selecting a storage management system. Note that within a
complex system, hybrid solutions mixing flat files and a database management system can be used for
different sets of persistent objects.

101
Providing Access Control
• In multi-user systems, different actors have access to different functionality and data.
For example, an everyday actor may only access the data it creates, whereas a system
administrator actor may have unlimited access to system data and to other users’ data.
• During analysis, we modeled these distinctions by associating different use cases to
different actors. During system design, we model access by determining which objects
are shared among actors, and by defining how actors can control access. Depending on
the security requirements of the system, we also define how actors are authenticated to the
system (i.e., how actors prove to the system who they are) and how selected data in the
system should be encrypted.
• For example, in MyTrip, storing maps and Trips for many drivers in the same database
introduces security issues. We must ensure that Trips are sent only to the driver who created
them. The descriptions for the Driver class and the revised descriptions for the
PlanningSubsystem and the CommunicationSubsystem are displayed in Table 7-1. The
revisions to the design model are indicated in italics.
102
103
• Defining access control for a multi-user system is usually more complex than in
MyTrip. 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.
• We model access on classes with an access matrix. The rows of the matrix
represent the actors of the system. The columns represent classes whose access
we control. An entry (class, actor) in the access matrix is called an access right
and lists the operations (e.g., postSmallDebit(), postLargeDebit(),
examineGlobalStats()) that can be executed on instances of the class by the actor.
Table 7-2 depicts the access matrix for our bank.

104
105
We can represent the access matrix using one of three different approaches: global access table,
access control list, and capabilities.
• A global access table represents explicitly every cell in the matrix as a (actor,class,
operation) tuple. Determining if an actor has access to a specific object requires looking up
the corresponding tuple. If no such tuple is found, access is denied.
• An access control list associates a list of (actor,operation) pairs with each class to be
accessed. Empty cells are discarded. Every time an object is accessed, its access list is
checked for the corresponding actor and operation. An example of an access control list is the
guest list for a party. A butler checks the arriving guests by comparing their names against
names on the guest list. If there is a match, the guests can enter; otherwise, they are turned
away
• A capability associates a (class,operation) pair with an actor. A capability allows an actor
access to an object of the class described in the capability. Denying a capability is equivalent
to denying access. An example of a capability is an invitation card for a party. In this case, the
butler checks if the arriving guests hold an invitation for the party. If the invitation is valid,
the guests are admitted; otherwise, they are turned away. No other checks are necessary.
106
• Each row in the global access matrix represents a different access view of the classes
listed in the columns. All of these access views should be consistent. Usually,
however, access views are implemented by defining a subclass for each different type
of (actor,operation) tuple. For example, in our banking system, we would implement
an AccountViewedByTeller and AccountViewedByManager class as subclasses of
Account. Only the appropriate classes are available to the corresponding actor. For
example, the Analyst client software would not include an Account class, because the
Analyst has no access to any operation in this class. This reduces the risk that an
error in the system results in the possibility of unauthorized access.
• Often, the number of actors and the number of protected objects are too large for
either the capability or the access control list representations. In such cases, rules can
be used as a compact representation of the global access matrix. For example,
firewalls protect services located on Intranet Hosts from other hosts on the Internet.
Based on the source host and port, destination host and port, and packet size, the
firewall allows or denies packets to reach their destination.

107
• As there are potentially many different combinations of source and destination
hosts and ports, firewall access is specified in terms of a list of rules. For a given
packet, the list is searched sequentially until a matching rule is found. The action
of the matching rule then dictates whether the current packet should be filtered or
not. For completeness, the last rule of the list matches any packet and has a deny
action, thus filtering out packets that do not match any of the other rules. Table 7-
3 depicts an example list of rules for the firewall depicted in Figure 7-8.
• The first two rules allow any host (located in the internet or in the intranet) to
access the http service on the Web Server and to deliver mail to the Mail Server.
The next two rules allow Intranet hosts to update the pages of the Web Server and
to retrieve mail from the Mail Server. Consequently, since these are the last two
rules that allow packets through, all Internet hosts are denied access to modify
web pages on the Web Server, read mail from the Mail Server, or any other service
on any of the Intranet hosts. For readability and robustness purposes, these can
also have been specified with deny rules (rows 5–7 in Table 7-3).
108
Figure 7-8 Packet filtering firewall: a filter, located at
the router, allows or denies individual packets based on
header information, such as source and destination.
109
• When the number of actors and objects is large, a rule-based representation is more compact
than either access control lists or capabilities. Moreover, a small set of rules is more
readable, and hence, more easily proofed by a human reader, which is a critical aspect when
setting up a secure environment.
• An access matrix only represents static access control. This means that access rights can be
modeled as attributes of the objects of the system. In the bank information system example,
consider a broker actor who is assigned a set of portfolios. By policy, a broker cannot access
portfolios managed by another broker. In this case, we need to model access rights
dynamically in the system, and, hence, this type of access is called dynamic access control.
• For example, Figure 7-9 shows how this access can be implemented with a protection Proxy
design pattern. For each Portfolio, we create a PortfolioProxy to protect the Portfolio and
check for access. An Access association between a legitimate Broker and a PortfolioProxy
indicates which Portfolio the Broker has access to. To access a Portfolio, the Broker sends a
message to the corresponding PortfolioProxy. The PortfolioProxy first checks if the
invoking Broker has the appropriate association with the PortfolioProxy. If access is
granted, the PortfolioProxy delegates the message to the Portfolio. Otherwise, the operation
fails. 110
Figure 7-9 Dynamic access implemented with a protection Proxy. The Access association class contains a set of
operations that a Broker can use to access a Portfolio. Every operation in the PortfolioProxy first checks with the
isAccessible() operation if the invoking Broker has legitimate access. Once access has been granted, PortfolioProxy
delegates the operation to the actual Portfolio object. One Access association can be used to control access to many
Portfolios. 111
• In both static and dynamic access control, we assume that we know the actor: either the user behind
the keyboard or the calling subsystem. This process of verifying the association between the identity
of the user or subsystem and the system is called authentication. A widely used authentication
mechanism, for example, is for the user to specify a user name, known by everybody, and a
corresponding password, only known to the system and stored in an access control list.
• The system protects its users’ passwords by encrypting them before storing or transmitting them. If
only a single user knows this user name–password combination, then we can assume that the user
behind the keyboard is legitimate. Although password authentication can be made secure with
current technology, it suffers from many usability disadvantages: users choose passwords that are
easy to remember and, thus, easy to guess. They also tend to write their password on notes that they
keep close to their monitor, and thus, visible to many other users, authorized or not.
• Fortunately, other, more secure authentication mechanisms are available. For example, a smart card
can be used in conjunction with a password: an intruder would need both the smart card and the
password to gain access to the system. Better, we can use a biometric sensor for analyzing patterns
of blood vessels in a person’s fingers or eyes. An intruder would then need the physical presence of
the legitimate user to gain access to the system, which is much more difficult than just stealing a
smart card.
112
• 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 (see Figure 7-10).
Protocols such as TCP/IP were not designed with security in mind: an intruder can forge
packets such that they appear as if they were coming from legitimate 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. The
encryption process is parameterized by a “key,” such that the method of encryption and
decryption can be switched quickly in case the intruder manages to obtain sufficient knowledge
to decrypt the message.
• Secure authentication and encryption are fundamentally difficult problems. You should always
select one or more off-the-shelf algorithms or packages instead of designing your own (unless
you are in the business of building such packages). Many such packages are based on public
standards that are widely reviewed by academia and the industry, thus ensuring a relatively
high level of reliability and security.
113
Figure 7-10 Passive attack. Given current technology, a passive intruder can listen to all network traffic. To prevent this kind of
attack, encryption makes the information in transit difficult to understand.

Once authentication and encryption are provided, application-specific access control can be more
easily implemented on top of these building blocks. In all cases, addressing security issues is a
difficult topic. When addressing these issues, developers should record their assumptions and describe
the intruder scenarios they are considering. When several alternatives are explored, developers should
state the design problems they are attempting to solve and record the results of the evaluation.
114
Designing the Global Control Flow
• Control flow is the sequencing of actions in a system. In object-oriented systems, sequencing actions
includes deciding which operations should be executed and in which order. These decisions are based on
external events generated by an actor or on the passage of time.
• 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. There
are three possible control flow mechanisms:
1) Procedure-driven control. Operations wait for input
whenever they need data from an actor. This kind of
control flow is mostly used in legacy systems and
systems written in procedural languages. It introduces
difficulties when used with object-oriented languages.
As the sequencing of operations is distributed among a
large set of objects, it becomes increasingly difficult to
determine the order of inputs by looking at the code
(Figure 7-11). 115
2) Event-driven control. A main loop waits for an
external event. Whenever an event becomes available, it
is dispatched to the appropriate object, based on
information associated with the event. This kind of
control flow has the advantage of leading to a simpler
structure and to centralizing all input in the main loop.
However, it makes the implementation of multi-step
sequences more difficult to implement (Figure 7-12).

3) Threads. Threads are the concurrent variation of


procedure-driven control: The system can create an
arbitrary number of threads, each responding to a
different event. If a thread needs additional data, it waits
for input from a specific actor. This kind of control flow
is the most intuitive of the three mechanisms. However,
debugging threaded software requires good tools:
preemptive thread schedulers introduce nondeterminism
and, thus, make testing harder (Figure 7-13).
116
• Procedure-driven control is useful for testing subsystems. A driver makes specific calls to
methods offered by the subsystem. For the control flow of the final system, though, procedure
driven control should be avoided.
• The trade-off between event-driven control and threads is more complicated. Event-driven
control is more mature than threads. Modern languages have only recently started to provide
support for thread programming. As more debugging tools become available and experience
is accumulated, developing thread-based systems will become easier. Also, many user
interface packages supply the infrastructure for dispatching events and impose this kind of
control flow on the design. Although threads are more intuitive, they currently introduce
many problems during debugging and testing. Until more mature tools and infrastructures are
available for developing with threads, event-driven control flow is preferred.
• Once a control flow mechanism is selected, we can realize it with a set of one or more control
objects. The role of control objects is to record external events, store temporary states about
them, and issue the right sequence of operation calls on the boundary and entity objects
associated with the external event. Localizing control flow decisions for a use case in a single
object not only results in more understandable code, but it also makes the system more
resilient to changes in control flow implementation. 117
Identifying Services
• Until this point, we have examined the key system design decisions that impact the subsystem
decomposition. We have now identified the main subsystems and we have a rough idea of how to
allocate responsibilities to each subsystem. In this activity, we refine the subsystem
decomposition by identifying the services provided by each subsystems. We review each
dependency between subsystems and define an interface for each service we identified (depicted in
UML by a lollipop). In this activity, we name the identified services. During object design, we
specify each service precisely in terms of operations, parameters, and constraints.
• By focusing on dependencies between subsystems, we refine the subsystem responsibilities, we
find omissions in our decomposition, and we validate the current software architecture. By
focusing on services (as opposed to attributes or operations), we remain at the architectural
abstraction level, allowing us to reassign responsibilities between subsystems, without changing
many modeling elements.
• 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 7-14): 118
• ConnectionManager allows a
subsystem to register with the
CommunicationSubsystem, 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.

119
• While we have not yet specified any operations of the CommunicationSubsystem, naming services
provides us with enough detail for identifying missing functionality and discussing design trade-offs. For
example:
1) Should the RoutingSubsystem be able to provide data (e.g., average speed on current trip leg, location
of traffic jam) back to the PlanningSubsystem in a future use case?
2) Should the CommunicationSubsystem only deal with entire trips or should provide the ability to send
trips in multiple packages?
• These questions lead us to further design decisions. We add service to the CommunicationSubsystem for
returning real-time data to the PlanningSubsystem. We can structure the interface of the
CommunicationSubsystem so that we could support either downloading policy.
• Note that, by convention, we use noun phrases to name services (e.g., TripRequester), as they correspond
to an interface including both attributes and operations. Operations provided by the interface are named
with verb phrases starting with a lower case (e.g, requestTrip()). Attributes defined by the interface are
named with noun phrases starting with a lower case (e.g., connectionStatus).
• Once we reviewed the dependencies among subsystems and identified corresponding services, we have a
concrete understanding of the subsystem responsibilities for the steady state. We are now ready to examine
boundary cases.

120
Identifying Boundary Conditions
• We need to identify the boundary conditions of the system—that is, to decide how the system
is started, initialized, and shut down—and we need to define how we deal with major failures
such as data corruption and network outages, whether they are caused by a software error or a
power outage. Uses cases dealing with these conditions are called boundary use cases.

• 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 loaded into
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.

• It is common that boundary use cases are not specified during analysis or that they are treated
separately from the common use cases. For example, many system administration functions
can be inferred from the everyday user requirements (registering and deleting users, managing
access control), whereas, many other functions are consequences of design decisions (cache
sizes, location of database server, location of backup server) and not of requirement decisions.
121
In general, we identify boundary use cases by examining each subsystem and each persistent object:
1) 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).
2) Start-up and shutdown. For each component (e.g., a WebServer), we add three use cases to start,
shutdown, and configure the component. Note that a single use case can manage several tightly
coupled components.
3) 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). We document each of these decisions with an
exceptional use case that extends the relevant common uses cases identified during requirements
elicitation. Note that, when tolerating the effects of a failure, the handling of an exceptional condition
can lead to changing the system design instead of adding an exceptional use case. For example, the
RouteAssistant can completely download the Trip onto the car before the start of the trip.

122
In general, an exception is an event or error that occurs during the execution of the system.
Exceptions are caused by three different sources:
1) A hardware failure. Hardware ages and fails. A hard disk crash can lead to the permanent
loss of data. The failure of a network link, for example, can momentarily disconnect two nodes
of the system.
2) Changes in the operating environment. The environment also affects the way a system
works. A wireless mobile system can lose connectivity if it is out of range of a transmitter. A
power outage can bring down the system, unless it is fitted with back-up batteries.
3) A software fault. An error can occur because the system or one of its components contains
a design error. Although writing bug-free software is difficult, individual subsystems can
anticipate errors from other subsystems and protect against them.

Exception handling is the mechanism by which a system treats an exception. In the case of a
user error, the system should display a meaningful error message to the user so that he/she can
correct his/her input. In the case of a network link failure, the system should save its temporary
state so that it can recover when the network comes back online.
123
• For example, consider a wireless navigation system in a car that retrieves on-demand
traffic information from a central computer. When the car enters a tunnel, the transfer
of information will be interrupted in the physical network layer. The network layer will
raise an exception (e.g., “socket unexpectedly closed”) and forward it to the upper layer.
The upper layer has the option of forwarding the exception to a higher layer or of
tolerating the exception (e.g., wait for a short time and attempt to retrieve the data again,
operate with older traffic data).
• When identifying boundary conditions, developers examine each component failure and
decide how to handle it. They can design components to tolerate the failure or write
boundary use cases to specify how the user will experience the failure.
• Developing reliable systems is a difficult topic. Often, trading off some functionality can
make system design easier. In MyTrip, we assumed that the connection is always possible
at the source destination and that replanning could be affected by communication
problems along the trip.

124
• For example (Figure 7-15), we now modify the analysis model for MyTrip to include the
boundary use cases. In particular, we add three use cases: ManageDrivers, to add,
remove, and edit drivers; ManageMaps, to add, remove, and update maps used to
generate trips; and ManageServer, to perform routine configuration, start-up, and
shutdown. StartServer, part of ManageServer, is provided as an example in Figure 7-16.

Figure 7-15 Administration use cases for MyTrip (UML use case diagram). ManageDrivers is invoked to add, remove,
modify, or read data about drivers (e.g., user name and password, usage log, encryption key generation). ManageMaps is
invoked to add, remove, or update maps that are used to generate trips. ManageServer includes all the functions necessary
to start up and shutdown the server. 125
• In this case, revising the use case model by
adding three use cases does not affect
subsystem decomposition. We added new
use cases to existing subsystems: The
MapDBStoreSubsystem should be able to
detect whether or not it was properly shut
down and should be able to perform
consistency checks and repair corrupted
data, as necessary. We revise the
description of MapDBStoreSubsystem
(Figure 7-17).

126
Reviewing System Design
• Like analysis, system design is an evolutionary and iterative activity. Unlike analysis, there is no
external agent, such as the client, to review the successive iterations and ensure better quality. This
quality improvement activity is still necessary, and project managers and developers need to
organize a review process to substitute for it. Several alternatives exist, such as using the developers
who were not involved in system design to act as independent reviewers, or to use developers from
another project to act as a peer review. These review processes work only if the reviewers have an
incentive to discover and report problems.
• In addition to meeting the design goals that were identified during system design, we need to ensure
that the system design model is correct, complete, consistent, realistic, and readable.

The system design model is correct if the analysis model can be mapped to the system design model. You
should ask the following questions to determine if the system design is correct:
• Can every subsystem be traced back to a use case or a nonfunctional requirement?
• Can every use case be mapped to a set of subsystems?
• Can every design goal be traced back to a nonfunctional requirement?
• Is every nonfunctional requirement addressed in the system design model?
• Does each actor have an access policy?
• Is every access policy consistent with the nonfunctional security requirement? 127
The model is complete if every requirement and every system design issue has been addressed.
You should ask the following questions to determine if the system design is complete:
• Have the boundary conditions been handled?
• Was there a walkthrough of the use cases to identify missing functionality in the system design?
• Have all use cases been examined and assigned a control object?
• Have all aspects of system design (i.e., hardware allocation, persistent storage, access control, legacy
code, boundary conditions) been addressed?
• Do all subsystems have definitions?

The model is consistent if it does not contain any contradictions. You should ask the following
questions to determine if a system design is consistent:
• Are conflicting design goals prioritized?
• Does any design goal violate a nonfunctional requirement?
• Are there multiple subsystems or classes with the same name?
• Are collections of objects exchanged among subsystems in a consistent manner?

128
The model is realistic if the corresponding system can be implemented. You ask the following
questions to determine if a system design is realistic:
• Are any new technologies or components included in the system? Was the appropriateness or robustness
of these technologies or components evaluated? How?
• Have performance and reliability requirements been reviewed in the context of
subsystem decomposition?
• Have concurrency issues (e.g., contention, deadlocks) been addressed?

The model is readable if developers not involved in the system design can understand the model.
You should ask the following questions to ensure that the system design is readable:
• Are subsystem names understandable?
• Do entities (e.g., subsystems, classes) with similar names denote similar concepts?
• Are all entities described at the same level of detail?

129

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy