Showing which objects talk to which β and therefore how coupled the design is.
π Where this lives: when a debugger shows you a stack trace forty frames deep, you are reading an interaction diagram after the fact. The difference is that a stack trace tells you what happened once, at run time, after the design was fixed; an interaction diagram lets you see the shape of the collaboration before committing to it β and notice that one object is talking to nine others, which is a coupling problem you can still fix cheaply. Search "sequence diagram design review coupling".
The two interaction diagrams
UML provides two INTERACTION DIAGRAMS that show the same
information with different emphasis. Both illustrate how objects
collaborate to fulfil a responsibility, and both are drawn from
the system operations and contracts of analysis.
COMMUNICATION DIAGRAM (formerly COLLABORATION DIAGRAM in
UML 1.x β the syllabus's term)
Objects are arranged as a GRAPH, connected by links, with
messages written along the links and NUMBERED to show
sequence.
β shows the STRUCTURE of the collaboration β who is connected
to whom β at a glance
β compact; good for a small number of objects with many
messages
β makes COUPLING VISIBLE: an object with many links is
highly coupled, and you can see it immediately
β the sequence must be read from numbers, which is harder
β poor for long sequences
SEQUENCE DIAGRAM
Objects are lifelines across the top, time runs DOWN the page,
messages are arrows between lifelines.
β the ORDER is immediately obvious
β handles long interactions, loops, alternatives and
concurrency well (with frames)
β the dominant choice in practice
β says less about structure β you must trace arrows to see
how coupled an object is
THEY ARE SEMANTICALLY EQUIVALENT: a tool can generate one from
the other. THE CHOICE IS ABOUT WHAT YOU WANT THE READER TO
NOTICE β order, or structure.
NOTATION β COMMUNICATION DIAGRAM:
ββββββββββββββββββββββ 1: find(no)
β :RecordPayment β βββββββββββββββββββββββΆ ββββββββββββββββ
β Handler β β :Application β
ββββββββββββββββββββββ β Repository β
β β ββββββββββββββββ
β β 2: recordPayment(amt, m, o)
β βΌ
β ββββββββββββββββ 2.1: Β«createΒ»(amt, m, o)
β β :Application β ββββββββββββββββββββββΆ ββββββββββββ
β ββββββββββββββββ β :Payment β
β ββββββββββββ
β 3: create(payment)
βΌ
ββββββββββββββββββ
β :ReceiptFactoryβ
ββββββββββββββββββ
THE ELEMENTS:
:ClassName an instance (anonymous)
name:ClassName a named instance
a link (plain line) the connection permitting messages
1:, 2:, 2.1: sequence numbering; nesting uses dots,
so 2.1 happens during 2
Β«createΒ» a stereotype marking instance creation
*[i := 1..n] iteration over a collection
[condition] a guard on a conditional message
msg() : ReturnType a return value
NOTATION β SEQUENCE DIAGRAM, the same collaboration:
:Handler :Repository :Application :Payment :ReceiptFactory
β β β β β
β find(no) β β β β
ββββββββββββββββΆβ β β β
ββ - - - - - - -β app β β β
β recordPayment(amt, m, o) β β β
ββββββββββββββββββββββββββββββΆβ β β
β β β Β«createΒ» β β
β β ββββββββββββββΆβ β
ββ - - - - - - - - - - - - - -β payment β β
β create(payment) β β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββΆ
ββ - - - - - - - - - - - - - - - - - - - - - - - - - - - -β
ADDITIONAL SEQUENCE-DIAGRAM NOTATION:
ACTIVATION BAR a tall thin rectangle on a lifeline
showing the object is active
FRAMES operators framing a region:
loop [cond] repetition
alt [c1]/[c2] mutually exclusive alternatives
opt [cond] an optional region
par parallel regions
ref a reference to another interaction
β on a lifeline object destruction
a self-message an arrow returning to the same lifeline
Reading a collaboration for design quality
THE MOST VALUABLE USE OF THESE DIAGRAMS IS NOT DOCUMENTATION β
it is DIAGNOSIS. A drawn collaboration exposes design problems
that are invisible in a class diagram.
PROBLEM 1 β THE GOD CONTROLLER (high fan-out)
:IssueLicenceHandler sends messages to nine objects:
Repository, Application, Payment, LicenceNumberPool,
Printer, AuditWriter, PoliceGateway, SmsSender, Dashboard
THE DIAGNOSIS: fan-out 9, which from the design heuristics
topic gives structural complexity S = 9Β² = 81. The handler
knows about everything, so any change touches it, and it
cannot be tested without nine collaborators.
THE FIX: the invariant/reaction split from the control styles
topic β the handler does the transactional core (allocate,
record, audit) and publishes an event; printing, notification
and the dashboard subscribe. Fan-out falls to 4, S = 16, a
5-fold reduction.
PROBLEM 2 β THE MESSAGE CHAIN (a train wreck)
handler β application.getApplicant()
.getDistrict()
.getFeeSchedule()
.getRate(category)
THE DIAGNOSIS: the handler now depends on Applicant, District
AND FeeSchedule, though it was only given an Application. Any
change to the shape of that chain breaks the handler. This
violates the LAW OF DEMETER (the "don't talk to strangers"
principle): an object should only send messages to itself,
its own fields, its method parameters, and objects it
creates.
THE FIX: `application.feeDue()` β ask the object you have for
what you want, and let it delegate internally. One dependency
instead of four.
PROBLEM 3 β THE ANAEMIC COLLABORATION
handler β application.getStatus()
handler β if (status == APPROVED) β¦
handler β application.setStatus(ISSUED)
THE DIAGNOSIS: the handler is making the decision using the
Application's data. That is the anaemic domain model from the
previous topic, visible in the interaction as a get/decide/set
pattern.
THE DIAGNOSTIC PATTERN TO LOOK FOR: any sequence of
get β compute β set on the SAME object means the behaviour
belongs in that object.
THE FIX: `application.issue(officer)`.
PROBLEM 4 β TOO MANY LAYERS CROSSED
A UI object sending a message directly to a Repository skips
the domain, which means the business rules were bypassed. The
layering rule from the previous topic is a statement about
which arrows may appear in an interaction diagram β and the
diagram is where a violation becomes visible.
A QUANTIFIED COMPARISON of two candidate designs for the same
operation:
criterion design A design B
ββββββββββββββββββββββββββββββββββββββββββββββββββ
objects involved 9 5
messages sent 14 8
handler fan-out 9 4
S = fan_outΒ² 81 16
deepest chain 4 1
collaborators needed
to unit test the
handler 9 2
ββββββββββββββββββββββββββββββββββββββββββββββββββ
THE LAST ROW IS THE ONE THAT MATTERS DAILY. A handler needing
nine collaborators requires nine test doubles per test, so
the tests are long, brittle and rarely written. A handler
needing two is testable in a few lines. INTERACTION DESIGN
DETERMINES TESTABILITY, which is the same conclusion the
development-cycle topic reached about the Clock parameter.
Worked: designing a collaboration from a contract
THE FULL METHOD, applied to `issueLicence(applicationNo)`.
THE CONTRACT (from analysis):
PRE the Application exists; status is APPROVED; the fee is
paid
POST a Licence was created with a unique number;
the Licence was associated with the Application;
status became ISSUED;
a StatusChange was created and associated;
no other Application was modified
STEP 1 β START WITH THE CONTROLLER, which receives the system
operation:
:IssueLicenceHandler receives issueLicence(no)
STEP 2 β FOR EACH POSTCONDITION, ASK "WHO HAS THE INFORMATION
NEEDED TO DO THIS?" (this is the Information Expert reasoning
of the next topic, applied):
"a Licence with a UNIQUE number was created"
β who knows which numbers are used? Not the Application β
uniqueness is system-wide. A LicenceNumberPool (or a
sequence in the repository) is the expert.
β :LicenceNumberPool.allocate() : LicenceNo
"the Licence was associated with the Application"
β the Application holds the reference, so it should create
or receive it
β :Application.issue(licenceNo, officer) : Licence
"status became ISSUED and a StatusChange was created"
β the Application owns its status and its history
β inside issue(), the Application does both. It is the
only object that can enforce "no status change without
a history entry", so THE INVARIANT LIVES INSIDE IT.
"no other Application was modified"
β satisfied by construction: only one Application receives
a message
STEP 3 β DRAW IT:
:IssueLicenceHandler
1: app := find(no) βββΆ :ApplicationRepository
2: no := allocate() βββΆ :LicenceNumberPool
3: lic := issue(no, officer)βββΆ :Application
3.1: Β«createΒ» :Licence
3.2: Β«createΒ» :StatusChange
4: save(app) βββΆ :ApplicationRepository
5: return lic
STEP 4 β CHECK THE FAILURE PATHS from the elaborated use case:
pool exhausted (5a) β allocate() throws; nothing else has
happened yet, so the minimal
guarantee "no number consumed
without an issuance" holds ONLY IF
allocation happens before any
commit. THE ORDER OF MESSAGES 2 AND
3 IS A CORRECTNESS DECISION, not a
stylistic one.
concurrent issuance (5d) β save() fails on a version
conflict; the transaction rolls
back; the allocated number is lost
unless the pool is transactional.
β THE DIAGRAM RAISES A QUESTION THE
CONTRACT DID NOT: is a gap in
licence numbers acceptable? The
business must answer. If not, the
pool must participate in the same
transaction.
STEP 5 β READ THE METHODS OFF THE DIAGRAM:
IssueLicenceHandler.handle(no, officer) : Licence
ApplicationRepository.find(no) / .save(app)
LicenceNumberPool.allocate() : LicenceNo
Application.issue(licenceNo, officer) : Licence
FOUR OBJECTS, FIVE MESSAGES, fan-out 3 for the handler. And
step 4 surfaced a business question that neither the use case
nor the contract had asked β which is the argument for
drawing the interaction rather than going straight to code.
The get/decide/set pattern is the most reliable smell to look for in an interaction diagram. When a controller asks an object for its data, makes a decision, and writes the result back, the decision belongs inside that object β and the diagram makes it visible in a way that reading the code rarely does.
π Go further: the Law of Demeter has a memorable positive formulation β "tell, don't ask". Rather than asking an object for its state and deciding what to do, tell it what you want accomplished and let it decide. Applied consistently it eliminates message chains, keeps invariants inside objects, and produces the rich domain model of the previous topic almost as a side effect. It also has a clear limit: query methods and read models legitimately ask, because reporting genuinely needs data out. Knowing where the principle stops is as useful as knowing it. Search "tell don't ask law of demeter".
π‘ Exam angle: distinguish the communication (collaboration) diagram from the sequence diagram β same semantics, different emphasis: structure versus order β with the strengths and weaknesses of each. Know the notation for both: instances (:Class, name:Class), links, sequence numbering with dotted nesting, Β«createΒ», iteration and guards for communication diagrams; lifelines, activation bars and the loop / alt / opt / par frames for sequence diagrams. Be ready to draw either from a use case or contract, and to critique a collaboration for high fan-out, message chains (Law of Demeter) and layer violations.
Syllabus points
Collaboration (communication) diagram (drawing)
Create a free account to tick topics off, take notes as you read, watch the video lessons and get a day-by-day study plan built around your exam date.