5th Unit Ooad
5th Unit Ooad
Advanced Behavioral Modeling: Events and signals, state machines, processes and
threads, time and space, state chart diagrams.
UNIT - IV
In the real world, things happen. Not only do things happen, but lots of things may
happen at the same time, and at the most unexpected times. "Things that happen" are
called events, and each one represents the specification of a significant occurrence
that has a location in time and space.
In the context of state machines, you use events to model the occurrence of a
stimulus that can trigger a state transition. Events may include signals, calls, the
passing of time, or a change in state.
In the UML, each thing that happens is modeled as an event. An event is the
specification of a significant occurrence that has a location in time and space. A
signal, the passing of time, and a change of state are asynchronous events,
representing events that can happen at arbitrary times.
Fig: Events
Kinds of Events
A signal may be sent as the action of a state transition in a state machine or the
sending of a message in an interaction. The execution of an operation can also send
signals.
In the UML, as the below figure shows, you model signals (and exceptions) as
stereotyped classes. You can use a dependency, stereotyped as send, to indicate that
an operation sends a particular signal.
Fig: Signals
Call Events
A signal event represents the occurrence of a signal, a call event represents the
dispatch of an operation. In both cases, the event may trigger a state transition in a
state machine.
Whereas a signal is an asynchronous event, a call event is, in general, synchronous.
This means that when an object invokes an operation on another object that has a
state machine, control passes from the sender to the receiver, the transition is
triggered by the event, the operation is completed, the receiver transitions to a new
state, and control returns to the sender.
The below figure models a family of signals that may be handled by an autonomous
robot. Note that the root signal (RobotSignal) is abstract, which means that there may
be no direct instances. This signal has two immediate concrete specializations
(Collision and HardwareFault), one of which (HardwareFault) is further specialized.
Note that the Collision signal has one parameter
Modeling Exceptions
In the UML, exceptions are kinds of signals, which you model as stereotyped classes.
Exceptions May be attached to specification operations.
You model exceptions primarily to specify the kinds of exceptions that an object may
throw through its operations.
To model exceptions
For each class and interface, and for each operation of such elements, consider the
exceptional conditions that may be raised.
Arrange these exceptions in a hierarchy. Elevate general ones, lower specialized
ones, and introduce intermediate exceptions, as necessary.
For each operation, specify the exceptions that it may raise. You can do so explicitly
(by showing send dependencies from an operation to its exceptions) or you can put
this in the operation's specification.
The below figure models a hierarchy of exceptions that may be raised by a standard
library of container classes, such as the template class Set. This hierarchy is headed by
the abstract signal Exception and includes three specialized exceptions: Duplicate,
Overflow, and Underflow. As shown, the add operation raises Duplicate and Overflow
exceptions, and the remove operation raises only the Underflow exception. Alternatively,
you could have put these dependencies in the background by naming them in each
operation's specification. Either way, by knowing which exceptions each operation may
send, you can create clients that use the Set class correctly.
State Machines
Using an interaction, you can model the behavior of a society of objects that work
together.
Using a state machine, you can model the behavior of an individual object.
A state machine is a behavior that specifies the sequences of states an object goes
through during its lifetime in response to events, together with its responses to those
events.
You can visualize a state machine in two ways: by emphasizing the flow of control
from activity to activity (using activity diagrams), or by emphasizing the potential
states of the objects and the transitions among those states (using statechart
diagrams).
Well-structured state machines are like well-structured algorithms: They are efficient,
simple, adaptable, and understandable.
A state machine is a behavior that specifies the sequences of states an object goes
through during its lifetime in response to events, together with its responses to those
events.
A state is a condition or situation during the life of an object during which it satisfies
some condition, performs some activity, or waits for some event.
A transition is a relationship between two states indicating that an object in the first
state will perform certain actions and enter the second state when a specified event
occurs and specified conditions are satisfied.
States
A state is a condition or situation during the life of an object during which it satisfies
some condition, performs some activity, or waits for some event.
An object remains in a state for a finite amount of time. For example, a Heater in a
home might be in any of four states: Idle (waiting for a command to start heating the
house), Activating (its gas is on, but it's waiting to come up to temperature), Active
As below figure shows, you represent a state as a rectangle with rounded corners.
Fig: States
First, there's the initial state, which indicates the default starting place for the state
machine or substate. An initial state is represented as a filled black circle.
Second, there's the final state, which indicates that the execution of the state machine
or the enclosing state has been completed. A final state is represented as a filled black
circle surrounded by an unfilled circle.
Transitions
A transition is a relationship between two states indicating that an object in the first
state will perform certain actions and enter the second state when a specified event
occurs and specified conditions are satisfied.
On such a change of state, the transition is said to fire. Until the transition fires, the
object is said to be in the source state; after it fires, it is said to be in the target state.
For example, a Heater might transition from the Idle to the Activating state when an
event such as tooCold (with the parameter desiredTemp) occurs.
As below figure shows, a transition is rendered as a solid directed line from the
source to the target state. A self-transition is a transition whose source and target
states are the same.
Fig: Transitions
Event Trigger
An event is the specification of a significant occurrence that has a location in time
and space.
As shown in the previous figure, events may include signals, calls, the passing of
time, or a change in state.
Guard
As the previous figure shows, a guard condition is rendered as a Boolean expression
enclosed in square brackets and placed after the trigger event.
A guard condition is evaluated only after the trigger event for its transition occurs.
Action
An action is an executable atomic computation. Actions may include operation calls
(to the object that owns the state machine, as well as to other visible objects), the
creation or destruction of another object, or the sending of a signal to an object.
As the previous figure shows, there's a special notation for sending a signal• the
signal name is prefixed with the keyword send as a visual cue.
The UML's state machines have a number of advanced features that help you to
manage complex behavioral models
Some of these advanced features include entry and exit actions, internal transitions,
activities, and deferred events.
In a number of modeling situations, you'll want to dispatch the same action whenever
you enter a state, no matter which transition led you there.
Similarly, when you leave a state, you'll want to dispatch the same action no matter
which transition led you away.
As Figure A: shows, the UML provides a shorthand for this idiom. In the symbol for
the state, you can include an entry action (marked by the keyword event entry) and an
exit action (marked by the keyword event exit), together with an appropriate action.
Whenever you enter the state, its entry action is dispatched; whenever you leave the
state, its exit action is dispatched.
Internal Transitions
Once inside a state, you'll encounter events you'll want to handle without leaving the
state. These are called internal transitions, and they are subtly different from self-
transitions
As Figure A shows, the UML provides a shorthand for this idiom, as well (for
example, for the event newTarget). In the symbol for the state, you can include an
internal transition (marked by an event). Whenever you are in the state and that event
is triggered, the corresponding action is dispatched without leaving and then
reentering the state. Therefore, the event is handledwithout dispatching the state's exit
and then entry actions.
Activities
When an object is in a state, it generally sits idle, waiting for an event to occur.
Sometimes, however, you may wish to model an ongoing activity. While in a state,
the object does some work that will continue until it is interrupted by an event.
As Figure A shows, in the UML, you use the special do transition to specify the work
that's to be done inside a state after the entry action is dispatched. The activity of a do
transition might name another state machine (such as followTarget). You can also
specify a sequence of actions• for example, do / op1(a); op2(b); op3(c).
Deferred Events
A deferred event is a list of events whose occurrence in the state is postponed until a
state in which the listed events are not deferred becomes active, at which time they
occur and may trigger transitions as if they had just occurred.
As you can see in the previous figure, you can specify a deferred event by listing the
event with the special action defer. In this example, selfTest events may happen
while in the Tracking state, but they are held until the object is in the Engaging state,
at which time it appears as if they just occurred.
There’s one more feature of the UML's state machines substates that does even more
to help you simplify the modeling of complex behaviors.
A substate is a state that's nested inside another one.
For example, a Heater might be in the Heating state, but also while in the Heating
state, there might be a nested state called Activating. In this case, it's proper to say
that the object is both Heating and Activating.
A simple state is a state that has no substructure.
A state that has substates that is, nested states is called a composite state.
A composite state may contain either concurrent (orthogonal) or sequential (disjoint)
substates.
In the UML, you render a composite state just as you do a simple state, but with an
optional graphic compartment that shows a nested state machine.
Substates may be nested to any level.
Sequential Substates
In the UML, a simpler way to model this idiom is by using history states.
A history state allows a composite state that contains sequential substates to
remember the last substate that was active in it prior to the transition from the
composite state.
The below figure shows, you represent a shallow history state as a small circle
containing the symbol H.
Concurrent Substates
Sequential substates are the most common kind of nested state machine.
These substates let you specify two or more state machines that execute in parallel in
the context of the enclosing object.
For example Maintenance state from below figure. Maintenance is decomposed into
two concurrent substates,
Testing and Commanding, shown by nesting them in the Maintenance state but
separating them from one another with a dashed line.
When control passes from the Idle to the Maintenance state, control then forks to two
concurrent flows the enclosing object will be in the Testing state and the
Commanding state.
Furthermore, while in the Commanding state, the enclosing object will be in the
Waiting or the Command state.
When you model the lifetime of an object, you essentially specify three things: the
events to which the object can respond, the response to those events, and the impact
of the past on current behavior.
Modeling the lifetime of an object also involves deciding on the order in which the
object can meaningfully respond to events, starting at the time of the object's creation
and continuing until its destruction.
Set the context for the state machine, whether it is a class, a use case, or the system as
a whole.
If the context is a class or a use case, collect the neighboring classes, including any
parents of the class and any classes reachable by associations or dependences. These
neighbors are candidate targets for actions and are candidates for including in guard
conditions.
If the context is the system as a whole, narrow your focus to one behavior of the
system. Theoretically, every object in the system may be a participant in a model of
the system's lifetime, and except for the most trivial systems, a complete model
would be intractable.
Establish the initial and final states for the object. To guide the rest of your model,
possibly state the pre- and post conditions of the initial and final states, respectively.
Starting from the initial state to the final state, lay out the top-level states the object
may be in. Connect these states with transitions triggered by the appropriate events.
Continue by adding actions to these transitions.
Identify any entry or exit actions (especially if you find that the idiom they cover is
used in the state machine).
Check that all events mentioned in the state machine match events expected by the
interface of the object. Similarly, check that all events expected by the interface of
the object are handled by the state machine. Finally, look to places where you
explicitly want to ignore events.
Check that all actions mentioned in the state machine are sustained by the
relationships, methods, and operations of the enclosing object.
Trace through the state machine, either manually or by using tools, to check it against
expected sequences of events and their responses. Be especially diligent in looking
for unreachable states and states in which the machine may get stuck.
After rearranging your state machine, check it against expected sequences again to
ensure that you have not changed the object's semantics.
For example, the below figure shows the state machine for the controller in a home
security system, which is responsible for monitoring various sensors around the
perimeter of the house.
In the UML, you model each independent flow of control as an active object that
represents a process or thread that can initiate control activity.
A process is a heavyweight flow that can execute concurrently with other processes;
a thread is a lightweight flow that can execute concurrently with other threads within
the same process.
The UML provides a graphical representation of an active class, the below figure
shows.
Active classes are kinds of classes, so have all the usual compartments for class
name, attributes, and operations. Active classes often receive signals, which you
typically enumerate in an extra compartment.
An active object is an object that owns a process or thread and can initiate control
activity. An
Active class is a class whose instances are active objects.
A process is a heavyweight flow that can execute concurrently with other processes.
A thread is a lightweight flow that can execute concurrently with other threads
within the same process.
Graphically, an active class is rendered as a rectangle with thick lines. Processes and
threads are rendered as stereotyped active classes (and also appear as sequences in
interaction diagrams).
Active classes share the same properties as all other classes. Active classes may have
instances.
Active classes may use any of the UML's extensibility mechanisms, including
stereotypes, tagged values, and constraints.
Active classes may be realized by collaborations, and the behavior of an active class
may be specified by using state machines.
The UML defines two standard stereotypes that apply to active classes.
A thread is lightweight. It may be known to the operating system itself. More often, it
is hidden inside a heavier-weight process and runs inside the address space of the
enclosing process. In Java, for example, a thread is a child of the class Thread.
Communication
When objects collaborate with one another, they interact by passing messages from
one to the other.
In a system with both active and passive objects, there are four possible combinations
of interaction that you must consider.
First, a message may be passed from one passive object to another. Assuming there
is only one flow of control passing through these objects at a time, such an
interaction is nothing more than the simple invocation of an operation.
Second, a message may be passed from one active object to another. When that
happens, you have interprocess communication, and there are two possible styles of
communication.
o First, one active object might synchronously call an operation of another.
That kind of communication has rendezvous semantics, which means
that the caller calls the operation; the caller waits for the receiver to accept
the call; the operation is invoked; a return object (if any) is passed back to
the caller.
Fourth, a message may be passed from a passive object to an active one. At first
glance, this may seem illegal, but if you remember that every flow of control is
rooted in some active object, you'll understand that a passive object passing a
message to an active object has the same semantics as an active object passing a
message to an active object.
Identify the opportunities for concurrent action and reify each flow as an active class.
Generalize common sets of active objects into an active class. Be careful not to over
engineer the process view of your system by introducing too much concurrency.
Ensure that each active class is both tightly cohesive and loosely coupled relative to
these neighboring classes and that each has the right set of attributes, operations, and
signals.
Capture these static decisions in class diagrams, explicitly highlighting each active
class.
Pay close attention to communication among active objects. Apply synchronous and
asynchronous messaging, as appropriate.
Pay close attention to synchronization among these active objects and the passive
objects with which they collaborate. Apply sequential, guarded, or concurrent
operation semantics, as appropriate.
Consider which of these active objects represent processes and which represent
threads. Distinguish them using the appropriate stereotype.
Modeling time and space is an essential element of any real time and/or distributed
system.
You use a number of the UML's features, including timing marks, time expressions,
constraints, and tagged values, to visualize, specify, construct, and document these
systems.
To represent the modeling needs of real time and distributed systems, the UML
provides a graphic representation for timing marks, time expressions, timing
constraints, and location, as below figure shows.
Graphically, a timing mark is formed as an expression from the name given to the
message (which is typically different from the name of the action dispatched by the
message).
Graphically, a timing constraint is rendered as for any constraint• that is, a string
enclosed by brackets and generally connected to an element by a dependency
relationship.
Time
Real time systems are, by their very name, time-critical systems. Events may happen
at regular or irregular times; the response to an event must happen at predictable
absolute times or at predictable times relative to the event itself.
The passing of messages represents the dynamic aspect of any system, so when you
model the time-critical nature of a system with the UML.
Fig: Time
In the UML, you model the deployment view of a system by using deployment
diagrams that represent the topology of the processors and devices on which your
system executes.
Each instance of a node will own instances of certain components, and each instance
of a component will be owned by exactly one instance of a node (although instances
of the same kind of component may be spread across different nodes). For example,
as Figure 23-3 shows, the executable component vision.exe may reside on the node
named KioskServer.
Fig: Location
For each event in an interaction, consider whether it must start at some absolute time.
Model that real time property as a timing constraint on the message.
For each time critical operation in each class, consider its time complexity. Model
those semantics as timing constraints on the operation.
For example, as shown in figure, the left-most constraint specifies the repeating start
time the call event refresh. Similarly, the center timing constraint specifies the
maximum duration for calls to getImage. Finally, the right-most constraint specifies
the time complexity of the call event getImage.
For each interesting class of objects in your system, consider its locality of reference.
In other words, consider all its neighbors and their locations.
A tightly coupled locality will have neighboring objects close by; a loosely coupled
one will have distant objects (and thus, there will be latency in communicating with
them).
Next consider patterns of interaction among related sets of objects. Co-locate sets of
objects that have high degrees of interaction, to reduce the cost of communication.
Next consider the distribution of responsibilities across the system. Redistribute your
objects to balance the load of each node.
Consider also issues of security, volatility, and quality of service, and redistribute
your objects as appropriate.
Below figure provides an object diagram that models the distribution of certain
objects in a retail system. The value of this diagram is that it lets you visualize the
physical distribution of certain key objects. As the diagram shows, two objects reside
on a Workstation (the Order and Sales objects), two objects reside on a Server (the
ObserverAgent and the Product objects), and one object resides on a DataWarehouse
(the ProductTable object).
Using the become and copy stereotyped messages, render the allocation of an object
to a new node.
The below figure provides a collaboration diagram that models the migration of a
Web agent that moves from node to node, collecting information and bidding on
resources in order to automatically deliver a lowest-cost travel ticket. Specifically,
this diagram shows an instance (named t) of the class TravelAgent migrating from
one server to another. Along the way, the object interacts with anonymous
Auctioneer instances at each node, eventually delivering a bid for the Itinerary object,
located on the client server.
Statechart diagrams are one of the five diagrams in the UML for modeling the
dynamic aspects of systems.
Both activity and statechart diagrams are useful in modeling the lifetime of an object.
However, whereas an activity diagram shows flow of control from activity to
activity, a statechart diagram shows flow of control from state to state.
Statechart diagrams are not only important for modeling the dynamic aspects of a
system, but also for constructing executable systems through forward and reverse
engineering.
In the UML, you model the event-ordered behavior of an object by using statechart
diagrams.
A statechart diagram shows a state machine, emphasizing the flow of control from
state to state.
A state machine is a behavior that specifies the sequences of states an object goes
through during its lifetime in response to events, together with its responses to those
events.
A transition is a relationship between two states indicating that an object in the first
state will perform certain actions and enter the second state when a specified event
occurs and specified conditions are satisfied.
Common Properties
A statechart diagram is just a special kind of diagram and shares the same common
properties as do all other diagrams that is, a name and graphical contents that are a
projection into a model.
Contents
A statechart diagram may contain any and all features of a state machine.
Common Uses
When you model the dynamic aspects of a system, a class, or a use case, you'll
typically use statechart diagrams in one way.
A reactive object is typically idle until it receives an event. When it receives an event,
its response usually depends on previous events.
After the object responds to an event, it becomes idle again, waiting for the next
event.
For these kinds of objects, you'll focus on the stable states of that object, the events
that trigger a transition from state to state, and the actions that occur on each state
change.
Choose the context for the state machine, whether it is a class, a use case, or the
system as a whole.
Decide on the stable states of the object by considering the conditions in which the
object may exist for some identifiable period of time. Start with the high-level states
of the object and only then consider its possible substates.
Decide on the meaningful partial ordering of stable states over the lifetime of the
object.
Decide on the events that may trigger a transition from state to state. Model these
events as triggers to transitions that move from one legal ordering of states to
another.
Attach actions to these transitions (as in a Mealy machine) and/or to these states (as
in a Moore machine).
Consider ways to simplify your machine by using substates, branches, forks, joins,
and history states.
Check that all states are reachable under some combination of events.
Check that no state is a dead end from which no combination of events will transition
the object out of that state.
Trace through the state machine, either manually or by using tools, to check it against
expected sequences of events and their responses.
For example, below figure shows the statechart diagram for parsing a simple context-
free language, such as you might find in systems that stream in or stream out
messages to XML. In this case, the machine is designed to parse a stream of
characters that match the syntax
Forward engineering (the creation of code from a model) is possible for statechart
diagrams, especially if the context of the diagram is a class. For example, using the
previous statechart diagram, a forward engineering tool could generate the following
Java code for the class
MessageParser.
class MessageParser {
public
boolean put(char c) {
switch (state) {
case Waiting:
if (c == '<') {
state = GettingToken;
token = new StringBuffer();
body = new StringBuffer();
}
break;
case GettingToken :
if (c == '>')
state = GettingBody;
else
token.append(c);
break;
case GettingBody :
if (c == ';')
state = Waiting;
else
body.append(c);
return true;
}
return false;
}
StringBuffer getToken() {
return token;
}
StringBuffer getBody() {
return body;
}
private
final static int Waiting = 0;
final static int GettingToken = 1;
final static int GettingBody = 2;
int state = Waiting;
StringBuffer token, body;
}
UNIT-V
Components
You use components to model the physical things that may reside on a node, such as
executables, libraries, tables, files, and documents.
In the UML, all these physical things are modeled as components. A component is a
physical thing that conforms to and realizes a set of interfaces
This canonical notation permits you to visualize a component apart from any
operating system or programming language.
Using stereotypes, one of the UML's extensibility mechanisms, you can tailor this
notation to represent specific kinds of components.
Fig: Components
Names
Every component must have a name that distinguishes it from other components.
A component is typically drawn showing only its name, as in below figure. Just as
with classes, you may draw components adorned with tagged values or with
additional compartments to expose their details, as you see in the figure.
Similarities
Components are like classes
Both have names
Both may realize a set of interfaces
Both may participate in dependency, generalization, and association relationships
Both may be nested
Both may have instances
Both may be participants in interactions.
As below figure shows, the relationship between a component and the classes it
implements can be shown explicitly by using a dependency relationship. Most of the
time, you'll never need to visualize these relationships graphically. Rather, you will keep
them as a part of the component's specification.
All the most common component-based operating system facilities (such as COM+,
CORBA, and Enterprise Java Beans) use interfaces as the glue that binds components
together.
You then provide components that realize the interfaces, along with other
components that access the services through their interfaces.
This mechanism permits you to deploy a system whose services are somewhat
location-independent and, as discussed in the next section, replaceable.
As below figure indicates, you can show the relationship between a component and
its interfaces in one of two ways.
The first (and most common) style renders the interface in its elided, iconic form.
The component that realizes the interface is connected to the interface using an elided
realization relationship.
The second style renders the interface in its expanded form, perhaps revealing its
operations.
The component that realizes the interface is connected to the interface using a full
realization relationship. In both cases, the component that accesses the services of the
A component may conform to many import interfaces. Also, a component may both
import and export interfaces.
The fact that this interface lies between the two components breaks the direct
dependency between the components.
A component that uses a given interface will function properly no matter what
component realizes that interface. Of course, a component can be used in a context if
and only if all its import interfaces are provided by the export interfaces of other
components.
Kinds of Components
Three kinds of components may be distinguished.
Organizing Components
You can organize components by grouping them in packages in the same manner
in which you organize classes.
You can also organize components by specifying dependency, generalization,
association (including aggregation), and realization relationships among them.
Standard Elements
Identify the partitioning of your physical system. Consider the impact of technical,
configuration management, and reuse issues.
Model any executables and libraries as components, using the appropriate standard
elements. If your implementation introduces new kinds of components, introduce a
new appropriate stereotype.
If it's important for you to manage the seams in your system, model the significant
interfaces that some components use and others realize.
Identify the ancillary components that are part of the physical implementation of your
system.
For example, below figure builds on the previous figure and shows the tables, files,
and documents that are part of the deployed system surrounding the executable
animator.exe. This figure includes one document (animator.hlp), one simple file
(animator.ini), and one database table (shapes.tbl), all of which use the UML's
standard elements for documents, files, and tables, respectively.
Modeling an API
To model an API
Identify the programmatic seams in your system and model each seam as an
interface, collecting the attributes and operations that form this edge.
Expose only those properties of the interface that are important to visualize in the
given context; otherwise, hide these properties, keeping them in the interface's
specification for reference, as necessary.
Model the realization of each API only insofar as it is important to show the
configuration of a specific implementation.
Figure exposes the APIs of the executable in the previous two figures. You'll see four
interfaces that form the API of the executable: IApplication, IModels, IRendering,
and IScripts.
Depending on the constraints imposed by your development tools, model the files
used to store the details of all your logical elements, along with their compilation
dependencies.
If it's important for you to bolt these models to your configuration management and
version control tools, you'll want to include tagged values, such as version, author,
and check in/check out information, for each file that's under configuration
management.
As far as possible, let your development tools manage the relationships among these
files, and use the UML only to visualize and document these relationships.
For example, below figure shows some source code files that are used to build the
library render.dll from the previous examples. This figure includes four header files
(render.h, rengine.h, poly.h, and colortab.h) that represent the source code for the
specification of certain classes. There is also one implementation file (render.cpp)
that represents the implementation of one of these headers.
Deployment
A node is a physical element that exists at run time and represents a computational
resource, generally having at least some memory and, often, processing capability.
You use nodes to model the topology of the hardware on which your system
executes.
This canonical notation permits you to visualize a node apart from any specific
hardware. Using stereotypes one of the UML's extensibility mechanisms.
You can (and often will) tailor this notation to represent specific kinds of processors
and devices.
Figure: Nodes
Names
Every node must have a name that distinguishes it from other nodes.
A path name is the node name prefixed by the name of the package in which that
node lives.
A node is typically drawn showing only its name, as in below figure. Just as with
classes, you may draw nodes adorned with tagged values or with additional
compartments to expose their details.
Similarities
In many ways, nodes are a lot like components:
Both have names;
Both may participate in dependency, generalization, and association relationships
Both may be nested;
Both may have instances;
Both may be participants in interactions.
Components are things that participate in the execution of a system; nodes are
things that execute components.
Components represent the physical packaging of otherwise logical elements;
Codes represent the physical deployment of components.
This first difference is the most important. Simply put, nodes execute
components; components are things that are executed by nodes.
As below figure shows, the relationship between a node and the components it
deploys can be shown explicitly by using a dependency relationship. Most of the
time, you won't need to visualize these relationships graphically but will keep
them as a part of the node's specification.
Organizing Nodes
You can organize nodes by grouping them in packages in the same manner in which
you can organize classes and components.
You can also organize nodes by specifying dependency, generalization, and
association (including aggregation) relationships among them.
Connections
The most common kind of relationship you'll use among nodes is an association.
Fig: Connections
Because nodes are class-like, you have the full power of associations at your
disposal.
This means that you can include roles, multiplicity, and constraints.
As in the previous figure, you should stereotype these associations if you want to
model new kinds of connections for example, to distinguish between a 10-T Ethernet
connection and an RS-232 serial connection.
Consider duplicate locations for components. It's not uncommon for the same kind of
component (such as specific executables and libraries) to reside on multiple nodes
simultaneously.
Below figure takes the earlier diagrams and specifies the executable components that
reside on each node. This diagram is a bit different from the previous ones in that it is
an object diagram, visualizing specific instances of each node. In this case, the RAID
farm and kiosk instances are both anonymous and the other two instances are named
(c for the console and s for the server). Each processor in this figure is rendered with
an additional compartment showing the component it deploys. The server object is
also rendered with its attributes (processorSpeed and memory) and their values
visible.
Component Diagrams
Component diagrams are one of the two kinds of diagrams found in modeling the
physical aspects of object-oriented systems.
You use component diagrams to model the static implementation view of a system.
Component diagrams are not only important for visualizing, specifying, and
documenting component-based systems, but also for constructing executable systems
through forward and reverse engineering.
With the UML, you use component diagrams to visualize the static aspect of these
physical components and their relationships and to specify their details for
construction, as shown in figure
Common Properties
A component diagram is just a special kind of diagram and shares the same common
properties as do all other diagrams a name and graphical contents that are a
projection into a model. What distinguishes a component diagram from all other
kinds of diagrams is its particular content.
Contents
Common Uses
You use component diagrams to model the static implementation view of a system.
This view primarily supports the configuration management of a system's parts, made
up of components that can be assembled in various ways to produce a running
system.
When you model the static implementation view of a system, you'll typically use
component diagrams in one of four ways.
Either by forward or reverse engineering, identify the set of source code files of
interest and model them as components stereotyped as files.
Consider exposing a tagged value indicating such information as the version number
of the source code file, its author, and the date it was last changed. Use tools to
manage the value of this tag.
Model the compilation dependencies among these files using dependencies. Again,
use tools to help generate and manage these dependencies.
For example, below figure shows five source code files. signal.h is a header file.
Three of its versions are shown, tracing from new versions back to their older
ancestors. Each variant of this source code file is rendered with a tagged value
exposing its version number.
Identify the set of components you'd like to model. Typically, this will involve some
or all the components that live on one node, or the distribution of these sets of
components across all the nodes in the system.
Consider the stereotype of each component in this set. For most systems, you'll find a
small number of different kinds of components (such as executables, libraries, tables,
files, and documents). You can use the UML's extensibility mechanisms to provide
visual cues for these stereotypes.
For each component in this set, consider its relationship to its neighbors. Most often,
this will involve interfaces that are exported (realized) by certain components and
For example, below figure models part of the executable release for an autonomous
robot. This figure focuses on the deployment components associated with the robot's
driving and calculation functions. You'll find one component (driver.dll) that exports
an interface (IDrive) that is, in turn, imported by another component (path.dll).
driver.dll exports one other interface (ISelfTest) that is probably used by other
components in the system, although they are not shown here. There's one other
component shown in this diagram (collision.dll), and it, too, exports a set of
interfaces, although these details are elided: path.dll is shown with a dependency
directly to collision.dll.
Identify the classes in your model that represent your logical database schema.
Select a strategy for mapping these classes to tables. You will also want to consider
the physical distribution of your databases. Your mapping strategy will be affected
by the location in which you want your data to live on your deployed system.
Where possible, use tools to help you transform your logical design into a physical
design.
Below figure shows a set of database tables drawn from an information system for a
school. You will find one database (school.db, rendered as a component stereotyped
as database) that's composed of five tables: student, class, instructor, department, and
course (rendered as a component stereotyped as table, one of the UML's standard
elements). In the corresponding logical database schema, there was no inheritance, so
mapping to this physical database design is straightforward.
Consider the physical distribution of the components that may migrate from node to
node.
You can specify the location of a component instance by marking it with a location
tagged value, which you can then render in a component diagram (although,
technically speaking, a diagram that contains only instances is an object diagram).
If you want to model the actions that cause a component to migrate, create a
corresponding interaction diagram that contains component instances.
You can illustrate a change of location by drawing the same instance more than once,
but with different values for its location tagged value.
For example, below figure models the replication of the database from the previous
figure. We show two instances of the component school.db. Both instances are
anonymous, and both have a different value for their location tagged value. There's
also a note, which explicitly specifies which instance replicates the other.
For each component, identify the classes or collaborations that the component
implements.
Choose the target for each component. Your choice is basically between source code
(a form that can be manipulated by development tools) or a binary library or
executable (a form that can be dropped into a running system).
Reverse engineering (the creation of a model from code) a component diagram is not a
perfect process because there is always a loss of information.
Choose the target you want to reverse engineer. Source code can be reverse
engineered to components and then classes. Binary libraries can be reverse
engineered to uncover their interfaces. Executables can be reverse engineered the
least.
Using a tool, point to the code you'd like to reverse engineer. Use your tool to
generate a new model or to modify an existing one that was previously forward
engineered.
Using your tool, create a component diagram by querying the model. For example,
you might start with one or more components, then expand the diagram by following
relationships or neighboring components. Expose or hide the details of the contents
of this component diagram as necessary to communicate your intent.
For example, below figure provides a component diagram that represents the reverse
engineering of the ActiveX component vbrun.dll. As the figure shows, the
component realizes 11 interfaces. Given this diagram, you can begin to understand
the semantics of the component by next exploring the details of its interfaces.
Deployment diagrams are one of the two kinds of diagrams used in modeling the
physical aspects of an object-oriented system.
A deployment diagram shows the configuration of run time processing nodes and the
components that live on them.
You use deployment diagrams to model the static deployment view of a system.
For the most part, this involves modeling the topology of the hardware on which your
system executes.
Deployment diagrams are essentially class diagrams that focus on a system's nodes.
Deployment diagrams are not only important for visualizing, specifying, and
documenting embedded, client/server, and distributed systems, but also for managing
executable systems through forward and reverse engineering.
With the UML, you use deployment diagrams to visualize the static aspect of these
physical nodes and their relationships and to specify their details for construction, as
in below figure.
A deployment diagram is just a special kind of diagram and shares the same common
properties as all other diagrams a name and graphical contents that are a projection into a
model. What distinguishes a deployment diagram from all other kinds of diagrams is its
particular content.
Contents
Nodes
Dependency and association relationships
Like all other diagrams, deployment diagrams may contain notes and
constraints.
Deployment diagrams may also contain components, each of which must
live on some node.
Deployment diagrams may also contain packages or subsystems,
Common Uses
When you model the static deployment view of a system, you'll typically use deployment
diagrams in one of three ways.
Identify the devices and nodes that are unique to your system.
Provide visual cues, especially for unusual devices, by using the UML's extensibility
mechanisms to define system-specific stereotypes with appropriate icons. At the very
least, you'll want to distinguish processors (which contain software components) and
devices (which, at that level of abstraction, don't directly contain software).
Model the relationships among these processors and devices in a deployment
diagram. Similarly, specify the relationship between the components in your system's
implementation view and the nodes in your system's deployment view.
As necessary, expand on any intelligent devices by modeling their structure with a
more detailed deployment diagram.
For example, below figure shows the hardware for a simple autonomous robot. You'll
find one node (Pentium motherboard) stereotyped as a processor.
Identify the nodes that represent your system's client and server processors.
Highlight those devices that are germane to the behavior of your system. For
example, you'll want to model special devices, such as credit card readers, badge
readers, and display devices other than monitors, because their placement in the
system's hardware topology are likely to be architecturally significant.
Provide visual cues for these processors and devices via stereotyping.
For example, below figure shows the topology of a human resources system, which
follows a classical client/server architecture. This figure illustrates the client/server
split explicitly by using the packages named client and server. The client package
contains two nodes (console and kiosk), both of which are stereotyped and are
visually distinguishable. The server package contains two kinds of nodes (caching
server and server), and both of these have been adorned with some of the components
that reside on each. Note also that caching server and server are marked with explicit
multiplicities, specifying how many instances of each are expected in a particular
deployed configuration. For example, this diagram indicates that there may be two or
more caching servers in any deployed instance of the system.
Identify the system's devices and processors as for simpler client/server systems.
If you need to reason about the performance of the system's network or the impact of
changes to the network, be sure to model these communication devices to the level of
detail sufficient to make these assessments.
Pay close attention to logical groupings of nodes, which you can specify by using
packages.
Model these devices and processors using deployment diagrams. Where possible, use
tools that discover the topology of your system by walking your system's network.
If you need to focus on the dynamics of your system, introduce use case diagrams to
specify the kinds of behavior you are interested in, and expand on these use cases
with interaction diagrams.
Below figure shows the topology of a fully distributed system. This particular
deployment diagram is also an object diagram, for it contains only instances. You can
see three consoles (anonymous instances of the stereotyped node console), which are
There's only a modest amount of forward engineering (the creation of code from
models) that you can do with deployment diagrams.
For example, after specifying the physical distribution of components across the
nodes in a deployment diagram, it is possible to use tools that then push these
components out to the real world. For system administrators, using the UML in this
way helps you visualize what can be a very complicated task.
Reverse engineering (the creation of models from code) from the real world back to
deployment diagrams is of tremendous value, especially for fully distributed systems that
are under constant change.
You'll want to supply a set of stereotyped nodes that speak the language of your
system's network administrators, in order to tailor the UML to their domain. The
advantage of using the UML is that it offers a standard language that addresses
not only their needs, but the needs of your project's software developers, as well.
Choose the target that you want to reverse engineer. In some cases, you'll want to
sweep across your entire network; in others, you can limit your search.
Choose also the fidelity of your reverse engineering. In some cases, it's sufficient to
reverse engineer just to the level of all the system's processors; in others, you'll want
to reverse engineer the system's networking peripherals, as well.
Use a tool that walks across your system, discovering its hardware topology. Record
that topology in a deployment model.
Using your modeling tools, create a deployment diagram by querying the model.
For example, you might start with visualizing the basic client/server topology, then
expand on the diagram by populating certain nodes with components of interest that
live on them. Expose or hide the details of the contents of this deployment diagram as
necessary to communicate your intent.