Class Design
What is this?
These problems ask you to model a small real-world thing in code — a bank, a coffee machine — where the operations themselves are easy but the organization is the whole game. It is like drawing the floor plan of a building before anyone moves in: where does each responsibility live, and how do the rooms connect? Nobody grades your speed here; they grade whether your design is clean, safe, and easy to extend when a new feature shows up.
💡 Fun fact: "Validate before you mutate" isn't just interview advice — it's the backbone of how real banks process transfers. A money move that half-completes is a genuine financial incident, which is why production systems treat the whole operation as all-or-nothing.
🔓 The 2 problems in this chapter are free. Sign in with Google or Microsoft to start solving.
Core idea: These problems have no clever algorithm — the operations are trivial. What's tested is how you model the domain: clean classes, a single source of truth, validating before you mutate, and a design where adding a new case is data, not a rewrite. Get the shape right and the code almost writes itself.
What's actually being graded
Not: "what's the fastest algorithm?"
But: "is this design correct, safe, and extensible?"
- Correctness & safety — never leave the system in a half-valid state. Validate fully, then mutate. A half-applied transfer is a financial incident.
- Single source of truth — centralize rules (e.g. one
_valid_accounthelper) instead of copy-pasting checks into every method, where they drift and develop off-by-ones. - Separation of concerns — split responsibilities so each class has one job; the orchestrator coordinates them.
- Extensibility — adding a drink / account type / rule should be registering data, not editing core logic.
The two problems
- Design a Bank System — transfer/deposit/withdraw with invariants (valid account range, sufficient funds). The lesson: centralize validation, validate before mutating, and express
transferas validated withdraw-then-deposit. The "algorithm" is nothing; the discipline is everything. - Design a Coffee Machine — model Inventory, Recipe (as data), and a Machine that mediates.
dispense= check availability, then deduct atomically. Adding a drink is a new recipe entry, not new branching. This is the open-ended OOP question where the interviewer watches your clarifying questions and your class boundaries.
The design checklist
| Principle | In practice |
|---|---|
| Validate before mutate | check all preconditions, then apply; never partially |
| Single source of truth | one validation/rule method reused everywhere |
| Separation of concerns | distinct classes, each one job; orchestrator wires them |
| Data over code | new cases are registered, not hard-coded |
| Clear API contracts | what does each method return on failure? (False vs raise) |
The insight: in class design the win is legibility and safety. State the invariants, put each rule in exactly one place, and make the common extension (a new account/drink/rule) a one-line data change.
📓 Draw it yourself
- Class diagram. Sketch the Coffee Machine as
Machine → Inventory + {Recipe}and trace adispensethat checks inventory, then deducts. - Validate-then-mutate. For the Bank, draw a transfer: validate both accounts + funds first, then move money — show the rejected path leaving balances untouched.
Snap photos and embed them with the /host-diagrams skill.
Key takeaways
- No algorithm — it's modeling. Clean classes, clear responsibilities, safe mutations.
- Validate before mutating; never leave half-applied state (especially money).
- One source of truth for each rule; don't scatter validation.
- Make extension data, not code — new drinks/accounts shouldn't touch core logic.
- Why interviewers use these: they reveal whether you can model a domain and write maintainable, safe code — the day-job skill algorithms don't test.
Order: Design a Bank System → Design a Coffee Machine.