Module 03 · Design notation · Lesson 2 of 4
Sequence diagrams
How objects collaborate over time in one use case: lifelines, synchronous and asynchronous messages, returns, and frames for alternatives and loops, plus the design flaws a sequence diagram reveals that a class diagram hides.
Why it matters
A class diagram can look perfectly reasonable while the design behind it is broken: a rule checked in two places, an object that has to call five others to do anything, a transaction that spans a network call. Those problems only show up when you trace a real use case through the objects in order. A sequence diagram is that trace on paper, and it is the fastest way to check that responsibilities are where you think they are.
The idea
A sequence diagram shows the participants in one scenario across the top, each with a vertical lifeline, and the messages between them as horizontal arrows ordered top to bottom in time. An activation bar on a lifeline shows when that participant is busy handling a call.
The notation you need
| Element | Drawn as | Means |
|---|---|---|
| Participant | Box at the top with a dashed lifeline | An object or component in this scenario |
| Synchronous message | Solid line, filled arrowhead | A call that waits for a result |
| Asynchronous message | Solid line, open arrowhead | Fire and forget: an event published, a job enqueued |
| Return | Dashed line back | The result or exception of a call; often omitted when obvious |
| alt frame | Box labelled alt with sections split by a dashed line and guards | If/else: one section runs depending on the condition |
| opt frame | Box labelled opt with one guard | An optional step |
| loop frame | Box labelled loop with a condition | Repeat for each item or while a condition holds |
What a sequence diagram reveals
- 1
Misplaced responsibilities
If the service asks the hold for its start time and duration and computes expiry itself, the arrow pattern shows it: the logic belongs in Hold (tell, don't ask). - 2
Chatty collaboration
A participant that sends ten messages to another to do one job usually means the boundary is in the wrong place. - 3
Ordering bugs
Did we mark the seat as sold before payment succeeded? The vertical order makes the sequence explicit. - 4
Transactions and side effects
Drawing where the transaction starts and ends shows when a network call or email happens inside it, which usually it should not. - 5
Missing failure paths
Adding an alt frame for each failure forces the question of what happens when the payment is declined or the hold has expired.
Sketching one quickly
Pick one use case and its happy path. List participants left to right in the order they are first called. Draw the calls top to bottom. Then add one alt frame for the most important failure. In an interview, narrating the same sequence in words ("the service asks the hold if it has expired, then charges the gateway with an idempotency key, then tells the booking to confirm") is often enough; draw it when the flow has branches or asynchronous steps that are easier to see than to hear.
Trade-offs
Sequence diagrams are excellent for one scenario and poor for showing all possibilities; trying to capture every branch in one diagram makes it unreadable. They also go stale quickly as code changes, so keep them for design discussions and for the few critical flows worth documenting, not for every method.
In an interview
After the class diagram, walk the most important use case: "Let me trace confirm booking: the controller calls BookingService.confirm, which loads the hold, asks it whether it has expired, charges the payment gateway with the hold id as idempotency key, then tells the booking to confirm and saves it in one transaction; if the charge is declined, the hold is released." That trace is the strongest evidence the model works.
Check yourself
While sketching the checkout sequence, you notice the order is marked as paid and the confirmation email is sent before the payment gateway call returns. What has the diagram revealed?