Overview
Step 5: walk the most important use cases through your objects, in order, as a sequence of method calls. This validates the class diagram: every call must be a method on the receiving class, data must come from its owner, and failure branches must have a clear handler.
In an interview, narrating 'the user calls BookingService.hold, which asks Show.hold, which checks each ShowSeat...' with a quick sequence sketch shows the design works end to end. It often reveals missing methods, misplaced responsibilities, and concurrency gaps before you write the full code.
Actors run through the play in order with props. Any missing prop or unclear cue shows up now, not on opening night.
When to use it
- After the class diagram, before or while coding.
- When the interviewer asks 'walk me through booking a ticket'.
- Debugging a design with unclear flows.
Where it shows up in interviews
Recognize it when: 'what happens when a user...?'
- Design a movie ticket system
- Design an ATM
- Design an elevator system
Where it is used in real software
Key flows are documented as sequence diagrams for review.
Production traces show the actual call sequence and timings.
Tests often mirror the walkthrough of the main flows.
Key terms
- Happy path
- The main successful flow.
- Failure branch
- Alternative flow when a step fails.
- Compensation
- Undo earlier steps after a failure (release hold).
- Atomic step
- Must happen without interference (hold seats).
How it works, step by step
- 1Pick 1-2 key use cases
Book seats; cancel booking.
- 2Write the call sequence
Caller -> method -> callee.
- 3Mark atomic sections
Hold must be all-or-nothing and synchronized.
- 4Add failure branches
Seat taken, payment failed, hold expired.
- 5Fix design gaps
Add missing methods or move responsibilities.
STEP 1holdSeats(user, show, [A5, A6]) -> Show.hold() atomically marks both seats held with expiry.
Gaps found during the walkthrough
Reviewing the book-seats flow
| Gap | Fix |
|---|---|
| Two holds could race | Show.hold synchronized; all-or-nothing |
| No release on payment failure | Add Show.release in the failure branch |
| Price computed in controller | Move to PricingStrategy |
| Hold expiry never checked | Hold.isExpired checked in confirm; background sweeper |
NOWGap: Two holds could race | Fix: Show.hold synchronized; all-or-nothing
Each gap became a small, targeted design change.
Implementation
public Booking book(String userId, String showId, List<String> seatIds) { Show show = shows.get(showId); // 1. load aggregate Hold hold = show.hold(seatIds, userId, clock.instant().plus(HOLD_TTL)); // 2. atomic hold (synchronized in Show) Money total = pricing.total(show, seatIds); // 3. pricing strategy boolean paid; try { paid = payments.charge(userId, total); // 4. external call outside any lock } catch (RuntimeException e) { show.release(hold); // failure branch: compensate throw e; } if (!paid) { show.release(hold); throw new PaymentDeclinedException(); } show.confirm(hold, clock.instant()); // 5. fails if hold expired Booking booking = new Booking(ids.next(), showId, userId, seatIds, total); bookings.save(booking); // 6. persist notifier.bookingConfirmed(booking); // 7. side effect last return booking;}Complexity and performance
Main + one failure.
High value.
Trade-offs
Narrate the main flow with key branches; skip trivial getters.
Sketch sequence arrows or write the orchestrating method directly; both validate the design.
Variants and related techniques
Formal notation of the same walkthrough.
Write the use case as a test, then implement.
Common mistakes
- Holding locks during payment calls.
Fix: Lock only for state changes; call external systems outside.
- No compensation on failure.
Fix: Release holds and reverse steps explicitly.
Interview questions
Walk me through booking a seat.
The service loads the show, which atomically holds the seats with an expiry; pricing computes the total; the payment gateway charges outside any lock; on failure the hold is released; on success the show confirms the hold (if not expired), a booking is saved, and a notification is sent.
Why do side effects like notifications come last?
So they only happen after the core state change succeeds; sending a confirmation for a booking that later fails would mislead the user.
Practice problems
| Problem | Difficulty | What it trains |
|---|---|---|
| Walk through an ATM withdrawal | Easy | Failure branches. |
| Walk through an elevator hall call | Medium | Dispatcher and car. |