Chapter 7: Object Design and Interaction Diagrams
Source files used: Lecture 7 - Object Design Interaction Diagrams.
A focused guide to object design and UML interaction diagrams for the COMP302 Midterm 1. It covers static vs dynamic modeling, CRC cards, and the notation of sequence and communication diagrams, including how to draw a diagram from Java code. Guide 6 set the layers; this guide designs how the objects inside them collaborate, starting from the system operations of Guide 5.
Roadmap: 1 OOA/D and UP → 2 Inception and Requirements → 3 Use Cases → 4 Domain Models → 5 SSDs and Contracts → 6 Logical Architecture → 7 Interaction Diagrams
On to Object Design
How Do Developers Design Objects?
- Code: design while coding, from a mental model straight to code.
- Draw, then code: sketch some UML on a whiteboard or in a UML CASE tool, then switch to coding in an IDE.
- Only draw: a tool generates everything from the diagrams (still with text code attached to the UML elements).
The drawing overhead should be worth the effort, so the lecture promotes lightweight drawing before coding.
Agile Modeling and UML CASE Tools
Agile modeling aims to reduce drawing overhead:
- model to understand and communicate, not to document,
- use whiteboards (10 in a room, not 2), markers, digital cameras, and printers to capture “UML as sketch”,
- model with others,
- create several models in parallel: five minutes on a wall of interaction diagrams, then five minutes on a wall of related class diagrams.
UML CASE tools are still useful: choose one that integrates with the IDE, code, then reverse engineer the code to see a UML big picture. Wall sketching and a CASE tool are complementary. For a 3-week iteration, spend a few hours or at most one day near the start drawing UML for the hard, creative parts of the design, then switch to coding.
Static vs Dynamic Modeling
| Dynamic models | Static models | |
|---|---|---|
| UML diagrams | interaction diagrams (sequence, communication), state machine diagrams, activity diagrams | class diagrams, package diagrams, deployment diagrams |
| What they design | the logic and behavior of the code: the method bodies | packages, class names, attributes, method signatures (not method bodies) |
The lecture calls the dynamic models the more interesting, difficult, and important diagrams to create.
Key Insight: The dice game from Guide 1 shows both: a class diagram (DiceGame with play(), Die with faceValue and roll()) is static; the sequence diagram of play() calling roll() is dynamic.
Object Design Skill Over UML Notation Skill
Knowing how to think and design in objects is more valuable than knowing UML notation. While drawing, the real questions are:
- What are the responsibilities of the object?
- Who does it collaborate with?
- What design patterns should be applied?
Drawing UML is a reflection of design decisions. Fundamental object design needs principles of responsibility assignment and design patterns (the course’s later topics).
CRC Cards
Class Responsibility Collaboration (CRC) cards are a popular text-oriented modeling technique: paper index cards, one card per class, listing the class’s responsibilities on the left and its collaborators on the right.
+---------------------------------+---------------------+
| Drawing | (collaborators) |
|---------------------------------| |
| Holds Figures. | Figure |
| Accumulates updates, refreshes | DrawingView |
| on demand. | DrawingController |
+---------------------------------+---------------------+
Interaction Diagrams
Two Kinds
UML interaction diagrams illustrate how objects interact via messages; they are used for dynamic object modeling.
- Sequence diagrams use a fence format: each new object is added to the right.
- Communication diagrams use a graph or network format: objects can be placed anywhere.
| Type | Strengths | Weaknesses |
|---|---|---|
| sequence | clearly shows the sequence or time ordering of messages; large set of detailed notation options | forced to extend to the right when adding new objects; consumes horizontal space |
| communication | space economical; flexibility to add new objects in two dimensions | more difficult to see the sequence of messages; fewer notation options |
From Code to Diagram
The lecture’s first example. Legend for every diagram in this guide: : is a lifeline (dashed in UML), [ ] is an execution specification (activation) bar, o-- is a found message, ---> is a synchronous message, <- - - is a reply, and - - -> is a creation message.
public class A {
private B myB = new B(); // myB exists before doOne() is ever called
public void doOne() {
myB.doTwo(); // first message
myB.doThree(); // second message
}
}
:A myB : B
: :
o--doOne()---->[ ] :
[ ] doTwo() :
[ ]---------------->[ ]
[ ] doThree() :
[ ]---------------->[ ]
: :
The same interaction as a communication diagram:
doOne()
-------->+-----+
| :A |
+-----+
| 1: doTwo() |
| 2: doThree() v
+---------+
| myB : B |
+---------+
Sequence Diagram Notation
Lifeline Boxes
| Lifeline label | Meaning |
|---|---|
:Sale | an unnamed instance of class Sale |
s1 : Sale | a named instance |
«metaclass» Font | the class Font itself (an instance of a metaclass), for static calls |
sales: ArrayList<Sale> | an instance of ArrayList parameterized to hold Sale objects |
sales[ i ] : Sale | one Sale selected from the sales collection |
x : List | an object typed by an interface (legal in UML 2, not in UML 1.x) |
A singleton object (only one instance can exist, accessed through the Singleton pattern) is marked with a 1 in the upper right corner of its lifeline box.
Messages, Found Messages, and Activation Bars
- The starting message is a found message, drawn with an opening solid ball: the sender is not specified, not known, or the message comes from a random source.
- A typical synchronous message is a solid line with a filled arrowhead.
- The execution specification bar (activation bar) shows the focus of control: the operation is on the call stack.
Replies and Returns
There are two ways to show a return result:
- the message syntax
returnVar = message(parameter), or - a reply (return) message: a dashed line at the end of the activation bar.
:Register :Sale
: :
o--doX()---->[ ] :
[ ] d1 = getDate() :
[ ]---------------------->[ ]
[ ] getDate() :
[ ]---------------------->[ ]
[ ] aDate [ ]
[ ]< - - - - - - - - - - -[ ]
: :
Messages to Self
A message from an object to itself (to this) is drawn with a nested activation bar:
:Register
:
o--doX()-->[ ]
[ ]---+ clear()
[ ]<--+ (nested bar on :Register)
:
Creating and Destroying Instances
Creation uses a dashed line (UML-mandated) with a create(...) message, and the new object’s box is placed at its creation “height”:
:Register :Sale
: :
makePayment(cashTendered) :
o--------->[ ] :
[ ] makePayment(cashTendered) :
[ ]-------------------------->[ ]
[ ] [ ] create(cashTendered)
[ ] [ ]- - - - - - - - - - - ->:Payment
[ ] [ ] authorize() :
[ ] [ ]-------------------------->[ ]
: : :
public class Sale {
private Payment payment;
public void makePayment(Money cashTendered) {
payment = new Payment(cashTendered); // the create message
// ...
}
}
Explicit destruction is shown with a «destroy» stereotyped message and a large X ending the lifeline. Use it in languages without garbage collection, or to stress that an object is no longer usable (such as a closed database connection).
Exam Trap #1: Drawing creation as a normal solid message to a box at the top of the diagram. A created object’s box starts at the creation height, and the create arrow is dashed.
Frames: loop, opt, alt
UML uses frames (regions or fragments of the diagram) for conditional and looping constructs. A frame has an operator (label) and a guard (conditional clause).
| Frame | Meaning | Lecture example |
|---|---|---|
loop [guard] | repeat the fragment while the guard is true | loop [more items] around enterItem |
loop(n) | repeat n times | nested inside an opt frame |
opt [guard] | conditional message: execute only if the guard is true | opt [color = red] around calculate |
alt [guard] / [else] | mutually exclusive alternatives (if/else), separated by a dashed line | [x < 10] calculate on :B, [else] calculate on :C |
sd Name / ref Name | a named diagram, and a reference to it | AuthenticateUser |
:Foo :Bar
: xx() :
:------------------------->:
+------:--------------------------:---+
| opt [color = red] : |
| : calculate() : |
| :------------------------->: |
+------:--------------------------:---+
: yy() :
:------------------------->:
Frames can be nested (an opt frame containing a loop(n) frame). The older UML 1 notation for a conditional message puts the guard on the message itself: [ color = red ] calculate.
Iteration Over a Collection
UML has no official idiom for sending the same message to every member of a collection; the lecture shows two alternatives.
- Explicit: a
loop [i < lineItems.size]frame, a lifelinelineItems[i] : SalesLineItem(the[i]is a selector expression), and an action boxi++on the Sale lifeline. - Implicit: a plain
loopframe aroundst = getSubtotal()tolineItems[i] : SalesLineItem.
Both describe this code:
public class Sale {
private List<SalesLineItem> lineItems = new ArrayList<SalesLineItem>();
public Money getTotal() {
Money total = new Money();
Money subtotal = null;
for (SalesLineItem lineItem : lineItems) {
subtotal = lineItem.getSubtotal(); // one getSubtotal message per item
total.add(subtotal);
}
return total;
}
}
Relating Diagrams: sd and ref
An interaction occurrence is a reference to an interaction within another interaction. It simplifies a diagram by factoring out a portion. Two related frames create it:
- a frame around an entire sequence diagram, tagged sd and a name, such as
sd AuthenticateUser, - a frame tagged ref in another diagram, which refers to that named diagram; this is the actual interaction occurrence. It covers the same lifelines as the sd diagram (for example, :B and :C).
Messages to Classes (Static Methods)
A static method call is a message to a lifeline labeled as a class, more precisely an instance of a metaclass. In Java, all classes are instances of class Class; in .NET, of class Type.
:Foo «metaclass» Calendar
: :
o--doX()-->[ ] :
[ ] locales = getAvailableLocales() :
[ ]---------------------------------->[ ]
: :
public void doX() {
Locale[] locales = Calendar.getAvailableLocales(); // static call on Calendar
}
Polymorphic Messages and Cases
Polymorphism is fundamental to OO design. One approach: draw the polymorphic message to the abstract superclass or interface object and stop there; then draw a separate diagram for each concrete case, each starting with a found polymorphic message.
:Register :Payment {abstract}
: :
o--doX()---->[ ] :
[ ] authorize() :
[ ]---------------------->[ ] stop here: no further detail
: :
:DebitPayment :Foo
: :
o--authorize()-->[ ] :
[ ] doA() :
[ ]---------------->[ ]
[ ] doB() :
[ ]---------------->[ ]
: :
:CreditPayment :Bar
: :
o--authorize()-->[ ] :
[ ] doX() :
[ ]---------------->[ ]
: :
Here Payment is an abstract superclass with an abstract authorize(); CreditPayment and DebitPayment implement it.
Asynchronous vs Synchronous Calls
- A synchronous (blocking) call is a filled arrowhead; the caller waits.
- An asynchronous call does not wait for a response and does not block. It is drawn with a stick (open) arrowhead. Asynchronous calls start new threads in Java and .NET: think of
Thread.start(which callsRunnable.run) as the asynchronous starting point. - An active object runs on and controls its own thread, such as a
Clockthat implementsRunnable. It is drawn with double vertical lines on the left and right of its box; the same notation marks an active class.
public class ClockStarter {
public void startClock() {
Thread t = new Thread(new Clock());
t.start(); // asynchronous: ends up calling Clock.run()
System.runFinalization(); // example follow-on message
}
}
Exam Trap #2: Using the same arrowhead for every message. Filled arrowhead: synchronous. Stick arrowhead: asynchronous. Dashed line: reply or creation.
Communication Diagram Notation
Links and Messages
- A link is a connection path between two objects: a form of navigation or visibility between them. Formally, it is an instance of an association.
- There can be only one link between two objects. All messages, in both directions, flow along that same link.
- Each message has a message expression and a small arrow showing its direction.
- A sequence number shows the order of messages in the current thread of control.
- A message to self is drawn as a link from the object back to itself.
1: makePayment(cashTendered) -->
2: foo() -->
+------------+ +-------+
| : Register |--------------------------------------| :Sale |
+------------+ +-------+
<-- 2.1: bar()
Message Numbering
- The first message is not numbered (msg1 is unnumbered).
- Messages sent while handling an incoming message are nested: prepend the incoming message’s number. Inside message 1, the messages are 1.1, 1.2, …; inside message 2, they are 2.1, 2.2, …
The lecture’s example, in order: msg1 (to :A), 1: msg2 (A to B), 1.1: msg3 (B to C), 2: msg4 (A to C), 2.1: msg5 (C to B), 2.2: msg6 (C to D).
Creation, Conditions, and Iteration
| Situation | Communication diagram syntax |
|---|---|
| creation | 1: create(cashier) to :Sale (read as a constructor call); or mark the new object :Sale {new}; or use «create» 1: make(cashier) for a less obvious name |
| conditional message | 1 [color = red] : calculate (sent only if the clause is true) |
| mutually exclusive paths | 1a [test1] : msg2 and 1b [not test1] : msg4; their nested messages are 1a.1 and 1b.1; a later 2: msg6 runs after either path |
| iteration | 1 * [i = 1..n] : num = nextInt (a * plus an optional iteration clause) |
| iteration over a collection | 1 * [i = 1..n] : st = getSubtotal to lineItems[i] : SalesLineItem; or the less precise 1 * : st = getSubtotal |
| static method | 1: locs = getAvailableLocales to «metaclass» Calendar |
| polymorphism | separate diagrams for each concrete case, as in sequence diagrams |
| asynchronous call | stick arrow, as in sequence diagrams (2: run to an active :Clock) |
Exam Trap #3: Numbering the first message 1:, or numbering nested messages flat. The incoming message is unnumbered, and nested calls inherit their parent’s number.
WRONG: 1: fnA, 2: fnB, 3: fnX, 4: fnY, 5: fnC, 6: fnZ
CORRECT: fnA, 1: fnB, 1.1: fnX, 1.2: fnY, 2: fnC, 2.1: fnZ
Exam-Style Practice Problems
Problem 1: Sequence Diagram From Code
Question: The Fall 2024 Midterm 1 study sheet: draw the sequence diagram for this code, starting from a call to fnA on an object of class A (include all participating objects).
public class A {
private B myB = new B();
public void fnA() {
int p;
p = myB.fnB();
myB.fnC();
}
}
public class B {
private C myC = new C();
public int fnB() {
myC.fnX();
return myC.fnY();
}
public void fnC() {
myC.fnZ();
}
}
Answer:
:A myB : B myC : C
: : :
o--fnA()------>[ ] : :
[ ] p = fnB() : :
[ ]---------------->[ ] :
[ ] [ ] fnX() :
[ ] [ ]---------------->[ ]
[ ] [ ] fnY() :
[ ] [ ]---------------->[ ]
[ ] fnC() : :
[ ]---------------->[ ] :
[ ] [ ] fnZ() :
[ ] [ ]---------------->[ ]
: : :
myBandmyCare created when A and B are constructed, beforefnAruns, so no create messages appear.p = fnB()shows the return value; a dashed reply line from myB is an equivalent option.- fnX and fnY are nested inside fnB’s activation; fnZ is nested inside fnC’s.
Problem 2: Sequence Diagram With Creation
Question: (Study sheet) Draw the sequence diagram for a call to the startGame method of a computer game object, which creates a new game session object and calls startGameSession on it; that in turn creates a new Level object and calls initializeLevel on it.
Answer:
:ComputerGame
:
o--startGame()-->[ ]
[ ] create()
[ ]- - - - - - - ->:GameSession
[ ] startGameSession() :
[ ]-------------------->[ ]
[ ] [ ] create()
[ ] [ ]- - - - - - - - - >:Level
[ ] [ ] initializeLevel() :
[ ] [ ]-------------------->[ ]
: : :
Each new object’s box sits at the height of its dashed create message, and :Level is created by :GameSession, not by :ComputerGame.
Problem 3: Convert to a Communication Diagram
Question: Redraw Problem 1 as a communication diagram.
Answer:
fnA()
------>+-----+
| :A |
+-----+
| 1: p = fnB() |
| 2: fnC() v
+---------+
| myB : B |
+---------+
| 1.1: fnX() |
| 1.2: fnY() |
| 2.1: fnZ() v
+---------+
| myC : C |
+---------+
One link per pair of objects; all messages between them ride on that link.
Problem 4: Static vs Dynamic
Question: (Study sheet) What is the difference between static and dynamic modeling?
Answer: Dynamic models (sequence, communication, state machine, activity diagrams) design behavior: the logic of method bodies. Static models (class, package, deployment diagrams) design definitions: packages, class names, attributes, and method signatures, but not method bodies.
Common Exam Traps
1. Creation Drawn as a Normal Message
WRONG: :Payment box at the top, solid arrow "new Payment()"
CORRECT: dashed create(...) arrow ending at the :Payment box,
drawn at its creation height
Why: The dashed line for creation is UML-mandated.
2. Creating Objects That Already Exist
WRONG: fnA diagram starts with create(myB) and create(myC)
CORRECT: myB and myC already exist (field initializers), so fnA starts the messages
Why: The diagram starts at the found message; earlier construction is not part of it.
3. Missing Nesting of Activation Bars
WRONG: fnX drawn from :A to myC after fnB
CORRECT: fnX drawn from myB to myC, inside myB's fnB activation
Why: The sender of a message is the object whose method makes the call.
4. Forgetting the Found Message
WRONG: the diagram begins with :A sending fnB()
CORRECT: o--fnA()--> :A, then :A sends fnB()
Why: The starting message (found message, solid ball) is where the interaction begins.
5. Communication Numbering
WRONG: 1: fnA, 2: fnB, 3: fnX
CORRECT: fnA (unnumbered), 1: fnB, 1.1: fnX
Why: The first message is unnumbered, and nesting is shown by prepending the parent number.
6. Two Links Between the Same Objects
WRONG: one link line per message between :Register and :Sale
CORRECT: a single link; all messages flow along it
Why: There can be only one link between two objects.
7. Polymorphism in One Giant Diagram
WRONG: authorize() to :Payment, then both doA/doB and doX on one diagram
CORRECT: stop at :Payment {abstract}; one more diagram per concrete subclass
Why: Each concrete case starts with its own found polymorphic message.
8. Static Calls to an Instance
WRONG: :Calendar receives getAvailableLocales()
CORRECT: «metaclass» Calendar receives getAvailableLocales()
Why: A static method belongs to the class, an instance of a metaclass.
9. Synchronous vs Asynchronous Arrowheads
WRONG: run() to the active :Clock drawn with a filled arrowhead (caller waits)
CORRECT: run() drawn with a stick arrowhead (asynchronous: the caller goes on)
Why: An asynchronous call does not block the caller.
10. UML Notation Over Design
WRONG: "Good object design = perfect UML notation."
CORRECT: "Good object design = good responsibilities, collaborations, and patterns."
Why: The lecture says object design skill matters more than UML notation skill.
Final Tips for the Midterm
- Trace the code before drawing: list the calls in order (here fnA, fnB, fnX, fnY, fnC, fnZ) and note who sends each one.
- Draw the four basics every time: found message, lifeline boxes with
name : Class, activation bars, and dashed creates. - Show returns one consistent way:
p = fnB()on the message, or a dashed reply line. - Know the frames: loop, opt, alt (with [else]), and sd/ref.
- Number communication diagrams correctly: unnumbered first message, then 1, 1.1, 1.2, 2, 2.1.
- Explain static vs dynamic modeling in one breath: structure and signatures vs behavior and method bodies.
Good luck on the midterm! You’ve got this.