What You'll Learn in This Hour:
What a sequence diagram is
How to apply a sequence diagram
How to model the creation of an object
How to work with some UML 2.0 additions to sequence diagrams
Where sequence diagrams fit in the big picture of the UML
The state diagrams you learned about in the last hour zoom in on a single object. They show the changes an object goes through.
The UML enables you to expand your field of view and show how an object interacts with other objects. In this expanded field of view, you'll include an important dimension—time. The key idea here is that interactions among objects take place in a specified sequence, and the sequence takes time to go from beginning to end. When you create a system, you specify the sequence, and you use the UML sequence diagram to do it.
The sequence diagram consists of objects represented in the usual way (as named rectangles with the name underlined), messages represented as solid-line arrows, and time represented as a vertical progression.
The objects are laid out near the top of the diagram from left to right. They're arranged in any order that simplifies the diagram.
Extending downward from each object is a dashed line called the object's lifeline. Along the lifeline is a narrow rectangle called an activation. The activation represents an execution of an operation the object carries out. The length of the rectangle signifies the activation's duration. Duration, and time in general, are represented in a rough, ordinal way. This means that each dash in a lifeline usually doesn't stand for a specific unit of time but is intended to give a general sense of duration. Figure 9.1 shows an object, lifeline, and activation.
A message that goes from one object to another goes from one object's lifeline to the other object's lifeline. An object can also send a message to itself—that is, from its lifeline back to its own lifeline.
UML represents a message as an arrow that starts at one lifeline and ends at another. The shape of the arrowhead shows what type of message it is. In UML 1.x, three arrowhead shapes were available. UML 2.0 has eliminated one of those shapes and, to my way of thinking, cut down on confusion. I'll explain the messages, and then show you what UML 2.0 has eliminated.
One type of message is a call. This is a request from the object sending the message to the object receiving the message. The request is for the receiver to carry out one of its (the receiver's) operations. Usually, this entails the sender waiting for the receiver to carry out that operation. Because the sender waits for the receiver (that is, “synchs up” with the receiver), this message is also referred to as synchronous.
UML signifies this message type with a filled arrowhead at the end of a solid line. It's typically the case that a call involves a return message from the receiver, although modelers often omit the symbol for the return message. The symbol for the return message is an open-stick arrowhead with a dashed line. Figure 9.2 shows these symbols.
Another kind of message is asynchronous. With this one, the sender transfers control to the receiver and doesn't wait for the operation to complete. The symbol for this message is an open-stick arrowhead, as Figure 9.3 shows.
The diagram represents time in the vertical direction: Time starts at the top and progresses toward the bottom. A message that's closer to the top occurs earlier in time than a message that's closer to the bottom.
Thus, the sequence diagram is two-dimensional. The left-to-right dimension is the layout of the objects, and the top-to-bottom dimension shows the passage of time.
Figure 9.4 shows the essential symbol set of the sequence diagram, with the symbols working together. The objects are laid out across the top. Each object's lifeline is a dashed line extending downward from the object. A solid line with an arrowhead connects one lifeline to another and represents a message from one object to another.
In order to bring this important UML tool to life, we'll apply it to some examples. As we do so, you'll have the opportunity to work with some object-oriented concepts that form the basis for sequence diagrams. I'll also be going back into classes, so it might seem that I'm digressing. I'm not. Trust me.
You might be familiar with the kind of car key that allows you to remotely lock and unlock a car. It also lets you open the car's trunk. If you have one of these keys, you know what happens when you push the “lock” button. The car locks itself, and then it blinks its lights and beeps to let you know it's finished locking its doors.
Let's capture all this in a class diagram. Figure 9.5 shows the relationships among the CarOwner
, Car
, and CarKey
classes, as well as some other concepts.
The Car
processes a message from the key and causes the appropriate behavior to take place.
Notice a couple of things about this diagram. In the CarKey
class, I've shown the signature of getButtonPress()
. This operation works with a button name (“lock,” “unlock,” or “openTrunk”). The idea is that the Car
receives a message from the CarKey
, processes that message, and implements the operation corresponding to the name of the pressed button.
The diagram also shows the two signals BlinkLights
and Beep
. You model a signal as a class with the keyword «signal»
added. The dependency arrows between Car
and each signal show that the Car
sends these signals. Once again, the UML has no symbol for send, so you add the keyword «send»
to the dependency arrow.
Note that the CarOwner
class shows something you haven't seen before in a class icon—the two occurrences of the «signal»
keyword. These show you that CarOwner
is capable of receiving these signals. The signals don't request the CarOwner
to do anything. Because the Car
(the sender) isn't making a request when it sends those signals, it certainly isn't waiting for the CarOwner
to do anything. Hence, the sequence diagram uses the asynchronous message symbol to model signals.
The class diagram in Figure 9.5 is a static view of the little world of the CarOwner
, CarKey
, Car
, and the two signals. A sequence diagram provides a dynamic view. How? By showing the messages that pass from one of these entities to another.
Start by drawing three objects. One object is an instance of CarOwner
, another is an instance of CarKey
, and the third is an instance of Car
. Lay them out across the top of the diagram and drop a lifeline from each one, as in Figure 9.6.
Next, add the arrows to model messages that go from lifeline to lifeline, as in Figure 9.7. The first message (the one highest in the vertical dimension) is a request from CarOwner
to CarKey
. The request is for CarKey
to implement its getKeyPress()
operation, registering the button the CarOwner
has pressed (generically referred to as b). The stick arrowhead indicates that CarOwner
is transferring control to CarKey
.
CarKey
then sends a message to Car
, calling on Car
to implement its processKeyMessage()
operation, depending on the specified button. After it processes the message from CarKey
, Car
sends itself a message to implement the operation that corresponds to the pressed button. Note the expression in brackets. That's a guard condition, which you just saw in Hour 8, “Working with State Diagrams.” It's the UML's way of saying “if.” So if the pressed button was “lock,” the Car sends itself a request to carry out the lock()
operation. Then Car
sends its two signals to CarOwner
. The first message and the signals are examples of the two usages of the stick arrowhead.
This example shows one use of a sequence diagram—modeling the interactions in a domain defined by a class diagram. The next example shows another context for applying sequence diagrams.
Let's move on to an example with a little more complexity. You'll recall that in Hour 6, “Introducing Use Cases” and Hour 7, “Working with Use Case Diagrams,” you read about the use cases of a soda machine. Remember also that a use case is a name for a collection of scenarios.
The sequence diagram is useful for modeling the scenarios of a use case. In this example, you'll model scenarios of the “Buy soda” use case.
You'll begin with a class diagram, as you did in the preceding example. The class diagram will model the entities that make up a soda machine. To keep it simple, assume three components—a front, a register, and a dispenser. Engineers who make a living designing and building soda machines, of course, have a different idea of the number of components, but these components will do for this example.
In your model of the soda machine, the front
Accepts selections and cash
Displays prompts like “Out of selection” and “Use correct change”
Receives change from the register and makes it available to the customer
Returns cash
Receives a can of soda from the dispenser and makes it available to the customer
The register
Gets the customer's input (that is, the selection and the cash) from the front
Updates its cash reserve
Checks for change
The dispenser
Checks the availability of a selection
Releases a can of soda
Assume the soda machine is an aggregation of these three components. Figure 9.8 shows the class diagram.
Let's model the best-case scenario of the “Buy soda” use case: The customer inserts the correct change, and the customer's selection is available. The sequence goes like this:
The customer inserts the money into the money slot in the front of the machine and makes a selection.
The money travels to the register, which updates itself.
Because this is the best-case scenario, an availability check reveals the soda is in stock, and the register has the dispenser release the soda to the front of the machine.
Figure 9.9 shows the sequence diagram that models these steps.
This is just one scenario in this use case. In another scenario, the customer's selection might be sold out. Figure 9.10 shows a sequence diagram that models the sold-out scenario.
Here's another scenario. Suppose the customer does not insert the correct amount of change? Figure 9.11 shows the sequence diagram for that one.
Finally, suppose the customer does not insert the correct change, and the soda machine is out of change? The sequence diagram for that scenario is in Figure 9.12.
So far, you've put just one scenario into a sequence diagram. When you do this, you create an instance sequence diagram.
If you include all of a use case's scenarios when you draw a sequence diagram, you create a generic sequence diagram. Let's put all our scenarios into one diagram.
We need some way of indicating conditions; one condition necessitates the messages in one scenario, another condition necessitates others. Recall from the example with cars and car keys that UML provides the guard condition to indicate if. This is just a bracketed statement for a condition that has to be in place to follow one path rather than another. For example, to show that an object sends a message only if the selected soda is sold out, preface that message with [sold out]
.
The guard conditions provide essentially the same information as the return messages. For example, [sold out]
lets you know that a selection is unavailable, just as the “Sold Out” return message does. For this reason, you can remove the return messages. Keeping them around would make the diagram cumbersome.
One more idea and you'll be ready to take the plunge into a generic sequence diagram. You want to be able to show that if you fully follow one scenario's sequence of messages to its conclusion, the transaction is over, and that the remaining messages are related to other scenarios. To do this, you preface the final message in each scenario with «transaction over»
.
Figure 9.13 incorporates these ideas.
Follow the diagram from top to bottom. It starts with the customer requesting the Front
to accept his or her cash and selection. Next, the Front
asks the Register
to get the customer's input. If the cash is greater than the price of the soda, the Register
checks its cash reserve for change. If no change is available, the Register
has the Front
return the customer's cash and then has the Front
display a prompt that says “Use Correct Change.” The transaction is over.
Next on the Register
's lifeline, you're in effect looking at a different scenario. The Register
has the Dispenser
check for the availability of the customer's selection.
If it's sold out, the Register
asks the Front
to display a prompt that says “Sold Out” and then has the Front
return the customer's cash. Once again, the transaction is over.
Moving down the Register
's lifeline, you see that if the transaction continues, the Register
updates its cash reserve according to the cash and the price. If the cash is greater than the price, the Register
has the Front
receive the change. Then the Register
asks the Dispenser
to release the selected soda, the Dispenser
requests the Front
to receive the soda, and the transaction (happily) is over.
Are you getting the idea that behind every use case lurks one or more sequence diagrams? If so, you probably understand why a sequence diagram is a valuable thing.
As you'll see in Hour 11, “Working with Activity Diagrams,” UML 2.0 offers an alternative way to combine sequence diagrams. It's called an Interaction Overview Diagram. Stay tuned.
A few years ago, telecommunications giant Ericsson demonstrated a technology that enables customers to use their cell phones to buy from soda machines. A commercial during a recent Super Bowl telecast portrayed this technology in action. How would you model this interaction in a sequence diagram? What would you have to add?
Let's begin once again with a class diagram. Figure 9.14 is an expansion of Figure 9.8. Through a wireless connection, the CellPhone
interfaces to the Front
. The Front
is smarter than before and now has the ability to process information from the Customer
. In this version it acquires an additional capability—the real focus here: It creates a transaction record of the interaction between the customer and the soda machine. The machine uses this record to charge the customer's credit card for the soda. Your sequence diagram has to visualize the creation of the transaction record.
Figure 9.14. Expanding the class diagram from Figure 9.8 to show a cell phone as an interface to a soda machine.
On to the sequence diagram. We'll work with the best-case scenario: The customer keys his or her credit card information into the cell phone and sends it to the Front
. The Front
processes the information and displays an “Approved” prompt to the Customer
. The Customer
keys a selection into the cell phone, which sends it to the Front
. In this version of the soda machine, the Front
processes the information and communicates directly with the Dispenser
to check availability and to instruct the Dispenser
to release the soda. The rest of the scenario is just like the original best-case scenario in the twentieth-century soda machine, except for the creation of the TransactionRecord
.
Figure 9.15 presents the sequence diagram. All the objects are across the top, except the TransactionRecord
object. Why? Because it's not one of the objects that exists at the beginning of the sequence. You show its creation by positioning it in the vertical dimension according to when it's created. Another aspect of modeling object–creation is the «create»
keyword you put on the message sent from the creator object to the created object. (Because the Register isn't involved in this sequence, it doesn't appear in the diagram.)
Figure 9.15. A sequence diagram that models the best-case scenario of using a cell phone as an interface to a soda machine.
While we're on the subject of object creation, we should also talk about object destruction. To show an object being destroyed, you place a large, bold X at the bottom of its lifeline, as in Figure 9.16. The left-hand part of the figure shows an object destroying itself (perhaps because a certain amount of time has passed). The right-hand part of the figure shows that an object can instruct another object to destroy itself. It does this by sending a message whose label is a «destroy»
keyword.
UML 2.0 adds a useful touch to sequence diagrams. You can now frame a sequence diagram by surrounding it with a border and adding a compartment in the upper left corner. The compartment contains information that identifies the diagram.
One of the pieces of information is an operator, an expression that describes the type of diagram inside the frame. For a sequence diagram, the operator is sd
. Figure 9.17 shows our generic sequence diagram framed in the UML 2.0 style. Along with the operator, the compartment contains the name of the interaction (BuySoda
) the diagram depicts.
The framing concept is helpful because you can apply it in a number of ways. Here's an example:
If you're creating instance sequence diagrams for the scenarios in a use case, you'll notice a fair amount of duplication from diagram to diagram. Framing gives you a quick and easy way to reuse part of one sequence diagram in another. You draw a frame around part of the diagram, label the frame's compartment, and just insert the frame with a label (but without the messages and lifelines) into the new diagram. This particular framed part is called an interaction occurrence. Its operator is ref
.
Figure 9.18 shows the frame around part of the best-case scenario. The framed part is the interaction occurrence that handles the delivery of the soda. Figure 9.19 shows how to reuse that interaction occurrence in the incorrect change scenario.
An interaction occurrence is a special case of an interaction fragment—UML 2.0's generic name for a piece of a sequence diagram. You can combine these interaction fragments in various ways. The operator indicates the type of combination. To show a combination, frame the entire set of fragments, and use a dotted line as a border between adjoining interaction fragments.
The two types of combinations I think will be the most widely used are denoted by the alt
operator and by the par
operator.
In the alt
combination, each fragment is an alternative and can proceed only under certain conditions. Guard conditions indicate which fragment can take place. Figure 9.20 shows this type of combination in the generic sequence diagram.
Figure 9.20. In the alt type of combined interaction fragments, each fragment is an alternative and proceeds only under certain conditions.
In contrast with the ref
operator, the idea here is clarity rather than reuse. If you compare Figure 9.20 with Figure 9.17, you'll see that the guard conditions in the fragments eliminate the need for some of the guard conditions on the messages. In my view, this clarifies the generic diagram and makes it easier to follow.
In the par
combination, the combined fragments work in parallel and don't interfere with one another. For example, suppose your soda machine works extremely efficiently: It returns the customer's change and delivers the selection at the same time. This necessitates that several events happen together. Figure 9.21 shows what I mean.
Figure 9.21. In the par type of interaction fragment combination, the fragments work in parallel and don't interfere with one another.
Before UML 2.0 introduced the par
operator, it was difficult to show parallel events on a sequence diagram.
You can now add one more diagram to your big picture of the UML. Because it deals with the behaviors of objects, the sequence diagram goes under the Behavioral Elements category. Figure 9.22 updates your growing picture.
The UML sequence diagram adds the dimension of time to object interactions. In the diagram, objects are laid out across the top, and time proceeds from top to bottom. An object lifeline descends from each object.
An arrow that connects one lifeline to another represents a message that one object sends another. A message's location in the vertical dimension represents the time of its occurrence within the sequence. Messages that occur early are close to the top of the diagram, and messages that occur late are close to the bottom. A narrow rectangle on an object's lifeline represents an activation——an execution of one of that object's operations. An object executes an operation in response to a message it receives.
A use case diagram can show either an instance (one scenario) of a use case, or it can be generic and incorporate all of a use case's scenarios. Generic sequence diagrams often provide opportunities to represent if statements. Enclose each condition for an if statement in square brackets.
When a sequence includes the creation of an object, you represent the newly created object in the usual way. Its position in the vertical dimension represents the time it's created.
UML 2.0 adds some useful techniques for sequence diagrams. They involve framing the entire diagram and framing fragments of the diagram. Framing the fragments is helpful for reuse and for clarifying certain aspects of the diagram.
The sequence diagram looks like it might be useful for more than just system analysis. Can I use it to show interactions in an organization? | |
A1: | Yes, you can. The objects can be principal players, and the messages can be simple transfers of control. |
Sometimes a sequence involves recursion. How can I represent recursion in a sequence diagram? | |
A2: | To represent recursion, show an object sending a message to itself. On the activation, superimpose a smaller activation. Show the arrowhead pointing to that smaller activation. |
You mentioned that the brackets in a guard condition are UML's way of saying if. Can I also show while in some way? | |
A3: | Yes you can. Another way of thinking about while is that it's if repeated many times. From Hour 4, “Working with Relationships,” remember that UML uses the asterisk to represent many. So in UML, “*[ ]” means while. |
Before each sequence diagram, you started with a class diagram. Do I always have to do this? | |
A4: | It's a good idea. If you model the classes first, you'll know which messages an object can receive. |
Now that you've stepped back and taken a long view of object interactions, step up to the plate, answer a few questions, and do a couple of exercises to firm up your knowledge of sequence diagrams. You'll find the answers in Appendix A, “Quiz Answers.”
General Hint: Start these exercises by creating a class diagram for each one.
3.138.175.180