Course Content
Object-Oriented Design Interview
14 sections · 29 lessons
Movie Ticket Booking: requirements and the ShowSeat model
The parking lot saved concurrency for the last five minutes. A cinema booking system puts it at the centre, and adds a modelling trap with a clear right answer. This lesson covers the prompt, the questions and requirements, and the one distinction the whole design rests on: the difference between a seat and a seat for one show.
Why this problem is different from the parking lot
In the parking lot, concurrency was the last five minutes. Here it is the point. Two people selecting seat H12 for the 7 pm show at the same moment is not an edge case — it is the normal operating condition of a booking system on a Friday evening, and an interviewer will spend a third of the round on it.
The second difference is that this problem has a modelling trap with a right answer. Most first attempts book a Seat. The correct model books a ShowSeat. Finding the objects, below, explains why, and if your attempt made this error, that diff alone is worth the forty-five minutes.
The five questions that change the model
1. "One cinema, or a chain across cities?" A chain adds City and Cinema above the screen, and makes search a real feature. Assume a chain with a small number of cities — it costs two classes and makes the design more interesting.
2. "Assigned seating or general admission?" Assigned seating is the whole problem. General admission reduces it to a counter and removes the interesting part. Assume assigned.
3. "How long is a seat held while the user pays?" This is the question that produces the state machine. If seats are held, there is a hold state and an expiry, and expiry is a design decision (Extensions). Assume a hold of five to ten minutes; ten is common in real systems, and any specific number should be a configuration value rather than a constant in the code.
4. "Is payment in scope?" Take it as an interface: PaymentGateway.charge(amount, method) returning success or failure. The interesting part is not the charge; it is what happens to the held seats when it fails or never returns.
5. "Can a booking be cancelled or refunded?" Changes the state machine's tail. Assume cancellation allowed until thirty minutes before the show, refunds out of scope.
Assumptions this lesson makes
- A chain: several cities, several cinemas per city, several screens per cinema.
- Assigned seating with seat types (regular, premium, recliner) at different prices.
- Seats are held for ten minutes while payment completes; the hold duration is configurable.
- Payment is an external interface that can succeed, fail, or time out.
- One application process with many threads; a shared relational database exists behind a repository interface.
Requirements
Functional requirements
1. Browse cities, cinemas, and shows for a given movie and date2. View the seat map for a show, with each seat's current status3. Hold one or more seats for a user, for a fixed window4. Take payment and confirm the booking5. Release held seats when payment fails or the hold expires6. Cancel a confirmed booking before a cut-offRequirement 5 is the one candidates leave out, and it is the one the interviewer is waiting for. A system that only handles the happy path leaks seats: every abandoned checkout removes a seat from sale permanently.
Non-functional requirements
N1. The same seat must never be sold twice. Not "rarely". Never. This is a correctness requirement, not a performance one, and it is the reason this problem exists.
N2. A held seat must return to sale if payment does not complete. Two failure paths: the user abandons the page, and the payment gateway never responds.
N3. The seat map must load fast for a large screen. A 300-seat auditorium with a few hundred people watching the same popular show means the seat-map read is the hottest operation in the system.
N4. Adding a pricing rule must not modify booking code. Same reasoning as the parking lot pricing.
What is cut
CUT (named, not forgotten)- Recommendations, ratings, reviews- Loyalty points and gift cards- Refund processing and accounting- Food and beverage ordering- Seat map rendering, layout editing, and the admin tools that create showsSay it: "I'll assume shows and seat layouts already exist — an admin created them. I'm modelling the booking path."
The number that shapes the design
One popular show on release day: a 300-seat screen, and perhaps a few thousand people attempting to book in the first minutes. That means:
- Read-heavy on the seat map, write-light on bookings. Roughly a hundred views per booking, so caching the map matters and correctness on the write path matters more.
- Contention is concentrated, not spread. Everyone wants the same twenty middle seats for the same show, so a lock over a whole show is a real bottleneck while a lock per seat is not.
That second observation is what makes the locking discussion in Preventing double booking, in code concrete rather than theoretical.
Finding the objects
This is the part with the insight. Everything else in the section follows from getting one distinction right.
The candidate nouns
City, cinema, screen, auditorium, show, movie, seat, seat type, booking, ticket, payment, user, price, hold.
The distinction that carries the problem
Ask: what does a user actually book?
Not seat H12. Seat H12 exists whether or not anyone is watching a film — it is a physical chair bolted to a floor, and it will be there for ten years. What a user books is seat H12 for the 7 pm show of a specific film on a specific date.
Those are two different things and they need two classes:
1public class Seat { // physical, permanent2 private final String id; // "H12"3 private final int row;4 private final int number;5 private final SeatType type; // REGULAR, PREMIUM, RECLINER6 private final Screen screen;7}89public class ShowSeat { // per-show, bookable10 private final Seat seat;11 private final Show show;12 private SeatStatus status; // AVAILABLE, HELD, BOOKED13 private Money price; // this show's price for this seat14 private String heldBy; // user id, null unless held15 private Instant holdExpiresAt; // null unless held16}Why this is not pedantry. Put status on Seat and a single physical chair has one status across every show in the day. Booking H12 for the 7 pm show marks it booked for the 10 pm show too. That bug is not subtle and it is fatal, and it is what a model without ShowSeat produces.
ShowSeat also gives price a home. The same chair is ₹200 on Tuesday morning and ₹450 on Friday night. Price belongs to the seat-in-a-show, not to the chair.
The rest of the model
| Class | Its one-sentence job |
|---|---|
City | Groups cinemas for search |
Cinema | One physical venue in a city, holding screens |
Screen | One auditorium, holding the permanent seat layout |
Movie | Title, duration, language, certification |
Show | One screening: a movie, on a screen, at a start time |
Seat | One physical chair and its type |
ShowSeat | One seat's availability and price for one show |
Booking | One user's set of show-seats, its status, and its payment |
Payment | An attempt to charge for a booking |
User | Whoever is booking |
Ten classes is at the upper end of what fits in forty-five minutes, which is why City and Cinema are thin — two fields and a list each. Say that out loud: "City and Cinema are mostly there for search; I'll keep them thin and spend the time on the booking path."
Where the money lives
Booking holds the total and a list of ShowSeats. It does not compute prices — a PricingStrategy does, taking the show and the seat type, so a weekend surcharge or a matinee discount is a new class (The seven patterns that actually appear).