Will There Ever Be More Than One?
A second test for whether something deserves to be a class, plus how the actual user journey decides which side of a relationship holds the reference.
Each class becomes a table in a real database, and that fact alone hands over a second, faster test for the same question the last post just answered: does this candidate actually deserve to be a class?
The Other Test: Will There Ever Be More Than One?
Ask how many rows that table would actually have. A parking lot management system's ParkingLot table has many rows, one per real parking lot it manages. A tic-tac-toe app's Game table has many rows too, one per game ever played.
Now run the same question on BookMyShow itself: how many rows would that table hold? Exactly one, forever. There's only ever one BookMyShow.
A table that can only ever have one row was never really tracking many instances of a recurring thing, and tracking many instances of a recurring thing is the entire reason a class needs its own table in the first place. That's the same conclusion the last post reached by hunting for attributes, just arrived at from a different angle. Whenever a candidate class feels shaky, asking "will there ever be more than one of these?" settles it faster than checking for attributes from scratch.
Physical Structure Gives Way to the User Journey
City, Theatre, Auditorium, Seat, and Show came from walking the physical structure. The next batch of classes comes from walking the core user journey instead: a user books a ticket, for a specific show, and paying for it needs payment information. That's User, Ticket, and Payment, three more classes, all pulled straight from that one flow.
Not everything that comes up while thinking through a journey belongs in the class diagram, though. Checking whether a user meets an age requirement is real logic this system needs, but it's behavior, something a service method does, not a fact any class needs to store permanently.
Let the Actual Use Case Decide Which Side Holds a Relationship
Two questions came up while filling in attributes, and both resolve the same way: a relationship belongs wherever the real usage pattern actually needs it, not automatically on both sides.
The first: City already holds a list of its theatres. Should Theatre also hold a reference back to its city? Only if the code genuinely needs to go from a theatre straight to its city often enough to justify it.
If that direction is rare, skip it and use a join when it's needed instead of storing the same relationship twice. A single reference is generally easier to reason about than a list, so when only one direction matters, that's the one worth keeping.
The second is less obvious. It's tempting to give Auditorium a currentShow field, since the two are clearly related. But trace the actual journey: does a user ever start from an auditorium and look up its show?
No. Someone browses a show first, and only then finds out which auditorium it's playing in. The reference belongs on Show, pointing at the auditorium it runs in, not the other way around.
Nobody in the actual user journey ever starts from an auditorium to find its show.
Every real path goes from a show to the auditorium it's playing in, never the reverse.
Sometimes a "Simple" Attribute Earns Its Own Class
A theatre's address could just be a string, and for BookMyShow, that's exactly what it is. But the same field, in a different system, might need to be its own class entirely, holding a house number, a street, a pincode, a phone number, the way Amazon needs an address with that much structure to actually ship something.
Whether something becomes a class or stays a plain field is still the same test from before: does this system need to store real structure about it, or just display it as-is? For BookMyShow, an address is just something to print on a page. For a delivery system, it's something to route a driver by.
The Same Enum-vs-Class Test, Run Twice, Two Different Answers
An auditorium supports a set of features: 2D, 3D, Dolby Atmos, Dolby Vision. That list looks a lot like seat types did earlier, so it's worth running the exact same test again: is this list fixed platform-wide, or can individual theatres invent their own?
Here the answer flips. BookMyShow needs a closed, known set of features so its own filter UI can work, letting someone click "3D" and see only shows that support it. A theatre can't invent a feature BookMyShow's filters don't know about.
So AuditoriumFeature is an enum, while SeatType, decided earlier, is a full class, because theatres genuinely can name their own seat tiers.
Same test, same shape of question, opposite answer, because the two things behave differently in the real system. Worth re-running the test every time, never assuming the last answer carries over.
Keep reading