Teaching
670 S '05
 
Lectures
Lecture 1
Lecture 2
Lecture 3
Lecture 4
Lecture 5
Lecture 6
Lecture 7
Lecture 8
Lecture 9
Lecture 10
Lecture 11
Lecture 12
Lecture 13

Lecture 11: Sequence Diagrams, The Observer Pattern

Sequence Diagrams

When you describe a story (use case), you often need to discuss the creation of objects, a sequence of method calls, call backs, and so on. So far we have used plain English to do that, with lists when needed.

If you need to discuss such things with customers or co-developers, you should use a graphical notation, because it is good for illustrating the sequencing of creations and method calls.

UML provides several notations for this purpose. Collectively, they are called Interaction Diagrams. We will use sequence diagrams.

The Basics of Sequence Diagrams

The first concept of a sequence diagram is a vertical line, called an object life line: A sequence diagram consists of objects and object life lines:

         Die      GameAdmin                       Player 
          |           |                              |
          |           |                              |
          |           |                Turn          |
          |           |                 |            |
          |           |                 |            |
          |           |                 _            |
          |           |                              |

These vertical placement often indicate when objects come about and when they cease to be relevant. That is, the lines represent the life spans of objects.

Calling a method---also known as sending a message---is represeted with a horizontal arrow plus appropriate annotations:


         Die      GameAdmin                       Player 
          |           |                              |
          |           |  t = new                     |
          |           | ------------> Turn           |
          |           |                 |            |
                                       ...          ...
          |           |                 |    roll()  |
          |           |                 | <--------- |
          |           |                 _            |
          |           |                              |

The first arrow, labeled with "t = new", denotes the act of creating an instance of Turn. The GameAdmin uses new to do so and the result is labeled t. The second arrow, labeled with "roll()", indicates that Player may call the roll method during an interaction with a Turn.

An interaction may also specify that an object hands over a reference to another object. For example, before the Player can access the Turn, the GameAdmin must actually hand over the Turn to the Player:


         Die      GameAdmin                       Player 
          |           |                              |
          |           |  t = new                     |
          |           | ------------> Turn           |
          |           |                 |            |
          |           | takeTurn(t)     |            |
          |           | ---------------------------> |
          |           |                 |            |
                                       ...          ...
          |           |                 |    roll()  |
          |           |                 | <--------- |
          |           |                 _            |
          |           |                              |

A First Example: The Story of Silly

Let's look at the stories in the "Silly Game":

Story 1: Registering players

Main creates and then registers players with the server.


 player registration: 
 --------------------

   Main                Server 
    |                   |
    | p = new()         |
    | ------------------------------->  Player 
    |                   |                |
    | registerPlayer(p) |                |
    | ----------------> |                |
    |                   |                |

Story 2: Taking a turn

The server plays rounds until there are no more active players.

For each round, the server grants each player a turn. The player can tell the turn to roll the dice or to skip, but only one of three actions is valid. If the player object does more with this turn, it is recorded as a cheater and eliminated from the tournament.

Here is one scenario: the player rolls the die.


 playing a turn (1) 
 ------------------

  Server               Player                           Die
    |                   |                               |
    | t = new()         |                               |
    | ------------------------------> Turn              |
    |                   |               |               |
    | takeTurn(t)       |               |               |
    | ----------------> |               |               |
    |                   |  roll()       |               |
    |                   | ------------> |               |
    |                   |               | d = roll()    | 
    |                   |               | ------------> |
    |               record(d)           |               |
    | <-------------------------------- |               |
    |                   |               |               |
    |  return           |               |               |
    | < - - - - - - - - |              --- the turn ceases
    |                   |                   to matter   |
    |                   |                               |
    |                   |                               |


The player can also just skip a turn.


 playing a turn (2) 
 ------------------

  Server               Player                          
    |                   |                              
    | t = new()         |                              
    | ------------------------------> Turn             
    |                   |               |              
    | takeTurn(t)       |               |              
    | ----------------> |               |              
    |                   |  skip()       |              
    |                   | ------------> |              
    |               record(0)           |              
    | <-------------------------------- |           
    |                   |               |              
    |  return           |               |              
    | < - - - - - - - - |              --- the turn ceases
    |                   |                   to matter   
    |                   |                               
    |                   |                               

Story 3: Game's up

When there is at most one player left, the GameAdmin ends with the administrator informing everyone who the winner was.


 the end of the game
 -------------------

  Server               Player                          
    |                   |                              
    |                   | 
    | inform(winner)    | 
    | ----------------> | 
    |                   |
    |                   |
   ---                 ---

Note that both the server and the player cease to be relevant.

The Observer Pattern

Suppose we wish to inform the other players of the decisions and actions that a player takes during a turn. Clearly the GameAdmin is in the proper position to do so. The Turn informs the GameAdmin of all actions, and thus the GameAdmin knows when things change and when the other players need to be informed.

A look in GoF suggests the Observer pattern. The players are the observers here and the administrator is the subject. Every time when one player rolls the die or skips a turn, the administrator can notify the remaining players of this action.

Here is a picture:


 playing a turn (1) 
 ------------------

  Server               Player                          Die   OtherPlayer
    |                   |                               |     |     
    | t = new()         |                               |     |     
    | ------------------------------> Turn              |     |     
    |                   |               |               |     |     
    | takeTurn(t)       |               |               |     |     
    | ----------------> |               |               |     |     
    |                   |  roll()       |               |     |     
    |                   | ------------> |               |     |     
    |                   |               | d = roll()    |     |     
    |                   |               | ------------> |     |     
    |               record(d)           |               |     |     
    | <-------------------------------- |               |     |  
    |                   |               |               |     |     
    |  return           |               |               |     |     
    | < - - - - - - - - |              --- the turn ceases |
    |                   |                   to matter   |     |     
    |                   |                               |     |     
    | notify(String result)                             |     |     
    x ------------------------------------------------------->|
    |                   |                               |     |     
    |                   |                               |     |     

The notification happens after the turn is over. Alternatively, the administrator could also inform OtherPlayer while the turn is still going on. Since observers may launch additional inquiries, it is important to make sure that the notification goes out when the internal data structures are stable.

Bibliography

  • Fowler, Scott. UML Distilled. Addison-Wesley, 1997.
  • Gamma, Helm, Johnson, Vlissides: Design Patterns: Elements of Reusable Object-Oriented Software. Addison-Wesley, Reading MA 1995.
  • Presentation

    Presenters: John V., Dan S.

    Readers: Tung (moderator), Chris Lambert (second reader), Eric B. (secretary)


    last updated on Tue Jun 9 22:03:19 EDT 2009generated with PLT Scheme