“Design a parking lot.” Forty-five minutes, a shared editor, and a requirement that changes at minute 40.
Most of what happens in those forty-five minutes is barely scored. Two or three moves decide the result, and they are worth knowing before you walk in.
By the end you will be able to:
- Say what goes into the round and what must come out of it.
- Tell this round apart from the three other design rounds it is confused with.
- Recognize which of six problem shapes you have been handed.
- Budget the clock, and know at any minute whether you are behind.
- Name the single question the whole round hangs off.
Nothing here assumes another chapter, and every term of art is defined the first time it appears.
Start with the words in the title
An object is a bundle of data together with the operations allowed on that data. A parking Spot holds whether it is occupied, and it offers the operations that occupy it and free it. The data and the operations travel together.
A class is the template describing one kind of object. An object is one filled-in copy made from that template. Spot is the class; the spot on level 2 in row C is an object.
Object-oriented design (OOD) is the act of deciding which classes exist and which one is responsible for each decision the system has to make.
So “design a parking lot” is really asking two questions. When a car arrives, which object decides where it goes? And which object decides what it costs?
The one thing being scored
The round measures whether the boundaries you draw between objects survive the next requirement.
Not whether you can recite the four pillars. Not whether you know twenty-three patterns. The interviewer has a change in their pocket — “now add electric-vehicle bays” — and the whole score is whether you answer it by adding a class or by editing six of them.
Both of those phrases — the pillars, the patterns — name real things, so pin them down now.
The four pillars are the textbook summary of object-oriented programming:
| Pillar | In plain words |
|---|---|
| Encapsulation | An object hides how it stores its data and exposes only operations |
| Abstraction | A caller depends on what an operation promises, not on how it is carried out |
| Inheritance | One class reuses and specialises another |
| Polymorphism | Several kinds of object answer the same call, each in their own way |
The twenty-three patterns are the named, reusable design solutions catalogued in the 1994 book Design Patterns — Strategy, Observer, Factory and the rest. Five of them appear later in this chapter with a one-line definition each.
Both are worth knowing. Neither is what is being scored.
That is the entire game. Everything below is what follows from it.
What goes in, and what comes out
Before any method, fix the shape of the exchange. Candidates lose this round by producing the wrong artifact more often than by producing a bad one.
What goes in
Three things arrive, in this order:
- One sentence of prompt — “design a parking lot”, “design an elevator” — deliberately underspecified.
- Your own clarifying questions, which fill in what the prompt left out.
- One requirement change, prepared by the interviewer in advance and delivered around minute 40, as the coding block ends and the last block of the clock opens.
What comes out
Three things, and all three are expected:
- A class diagram — a box per class listing its data and its operations, with lines showing which class knows about which.
- 60-150 lines of code that actually runs.
- Three sentences pricing the interviewer’s change in files — what is new, what is untouched, and what it costs you.
Those three sentences sound like this, for the electric-vehicle change: “EV bays are a new SpotType value and a new FeeModel subclass. ParkingLot and Ticket are untouched. The cost is that the pricing rule now lives in a second file, so reading the whole fee flow means opening two.”
The round in six lines
The whole scoring model fits in six rows, and the last row is where most candidates lose.
| Dimension | This round |
|---|---|
| What you produce | A class diagram plus 60-150 lines of running code |
| What you win on | A requirement change your design absorbs without editing existing classes |
| What you lose on | A design where one class knows everything, or where the classes are empty and one service does all the work |
| The unit of scale | Number of files touched per requirement change. Not QPS, not GB |
| Correctness means | An invariant holds across a method call, and the asserts you wrote pass |
| Where candidates lose | Naming patterns instead of naming the change each pattern makes cheap |
Four terms in that table are load-bearing and are used throughout this track:
- QPS — queries per second, the count of requests a service handles each second.
- GB — gigabytes of stored data. QPS and GB are the currency of a different round, and neither is measured here.
- Invariant — a statement about your objects that must be true before and after every operation. “A spot holds at most one vehicle” is the parking-lot invariant. Naming it early tells you which object is allowed to change what.
- Assert — a line of code that states an expected result and crashes the program if it is false. That is how a forty-five-minute design proves it works without a test framework.
The sentence to say in minute two
Say this out loud in the first two minutes: “I want to find the thing that will change most often, because that is where the interface goes.”
It is the sentence the round is built around, and most candidates never say it.
An interface here means a small contract — a named set of operations with no code behind them — that several different classes can each fulfil in their own way. The code that calls the interface never learns which one it got.
Putting an interface at the point of expected change is what lets tomorrow’s requirement arrive as a new class instead of as an edit. In the parking lot, the fee rule changes every quarter and the “does this vehicle fit this spot” rule has not changed in ten years. So FeeModel is an interface and the fit check is a plain method.
The words this round uses
Every trade has vocabulary that gets said at speed, and this round is no exception. Skim these once now and come back when a term bites.
Core vocabulary
| Term | In plain words |
|---|---|
| Class / object | The template, and one filled-in copy of it |
| Interface vs implementation | The interface is the promise — the operation names and what they return. The implementation is one particular way of keeping that promise. Callers depend on the promise, so the implementation can be swapped |
| Encapsulation | The object owns its data and no one reaches in. You call spot.occupy(car); you do not write spot.vehicle = car from outside |
| Coupling | How much one class must know about another’s internals. Low coupling means you can change one without opening the other |
| Cohesion | How well the things inside one class belong together. High cohesion means every field and method serves the same job |
| Composition vs inheritance | Composition means one object holds another and delegates work to it. Inheritance means one class is a special case of another and reuses its code. Composition is swappable at runtime; inheritance is fixed when you write the class |
| Invariant | The statement that must never be false, such as one vehicle per spot |
| Cardinality | The count on each end of a relationship: one lot has one-or-more levels, a spot has zero-or-one vehicle |
| Design pattern | A named, recurring solution shape. Naming one is worth little; naming the change it makes cheap is worth a lot |
| UML | Unified Modeling Language, the standard drawing notation for class diagrams — the boxes, the arrows, and the little diamonds on the arrows |
The five patterns this chapter names
Five patterns appear by name in later sections. One sentence each is enough for now.
| Pattern | What it does | Where you meet it here |
|---|---|---|
| Strategy | Puts a varying rule behind an interface, so a new rule is a new class | The thermostat’s ControlPolicy, and the parking lot’s fee model |
| State | Gives an object a different behaviour per lifecycle phase, by making each phase its own class | The state-machine problem shape: vending machine, elevator |
| Factory | One place that decides which concrete class to build from some input | Building the right Spot subtype from a size code |
| Observer | Lets objects register to be told when something changed, so the thing that changed does not need to know who cares | The feed-of-events shape: logger, notification service |
| Composite | Treats a single item and a group of items through the same interface | A file and a folder both answering size() |
SOLID
One acronym will be said at you at some point, so have it ready. SOLID is a five-item checklist for class design, one letter each.
| Letter | Principle | In plain words |
|---|---|---|
| S | Single responsibility | A class should have one reason to change |
| O | Open/closed | Adding behaviour should mean adding code, not editing code that already works |
| L | Liskov substitution | Anywhere the base class works, a subclass must work too, without the caller noticing |
| I | Interface segregation | Several small interfaces beat one large one, so nobody depends on operations they never call |
| D | Dependency inversion | The class holding the policy depends on an interface; the concrete implementation is handed in from outside |
Reciting it scores nothing. The rubric below is looking for the consequences, and 03 — OOP Fundamentals derives all five from code that fails without them.
Two abbreviations on the invite
OOD is object-oriented design. LLD is low-level design. In practice they name the same round, and the difference is only how much code you are expected to type.
Which round is this
Four different interviews get called “the design round”, and answering one with another’s material is the most expensive mistake available. This repo has a framework chapter for each of the four, because they have four different scoring sheets.
The four sheets, side by side
One row settles it: “the decisive question” alone tells you which sheet the interviewer is holding.
| Dimension | OOD / LLD (this track) | Classic system design (sd 03) | ML system design (ml-sd 01) | Agent design (Design Interview Playbook) |
|---|---|---|---|---|
| The artifact | A class diagram and running code | A topology and a data model | A target definition and an operating point | A control loop and its guards |
| The decisive question | What changes next, and who owns it | Read:write ratio | Where the label comes from | Calls per task |
| Unit of cost | Files edited per change | Storage, egress, fan-out | Feature fetch | Inference tokens |
| Scale of the answer | One process, one machine | A fleet | A pipeline | A loop |
| Typical failure | Lists classes, shows no consequence | Draws first, counts never | Models first, labels never | Agent first, workflow never |
The other three columns’ vocabulary
You need these only to feel the contrast, so one line each. None of them is scored in an OOD round.
| Term | Round it belongs to | In plain words |
|---|---|---|
| Topology | Classic system design | The picture of which servers and stores talk to which |
| Read:write ratio | Classic system design | How many reads a system serves for each write it accepts. It decides that round’s architecture the way “what changes next” decides this one |
| Egress | Classic system design | Data leaving your network, which you are billed for |
| Fan-out | Classic system design | One write copied to many places |
| Operating point | ML system design | The threshold a machine-learning model is run at, trading false alarms against misses |
| Feature fetch | ML system design | Looking up that model’s inputs at the moment a request arrives |
| Inference tokens | Agent design | The chunks of text a large language model is billed by, so a loop that calls the model four times per task costs four times one call |
| Control loop | Agent design | The cycle that round is built around: call the model, read what it asked for, run that tool, feed the result back in, then decide whether to go round again |
| Guards | Agent design | The limits that stop that loop running away — a cap on iterations, a list of actions that require a human, a ceiling on spend |
The one-line boundary
The system design round asks which machine the data lives on. The OOD round asks which object owns the decision.
They are not a hard round and an easy round. They are different questions, and answering an OOD prompt with QPS numbers reads exactly as badly as answering a system design prompt with class diagrams.
What to scope out in your first minute
Two things you will not be asked for here: capacity estimates and network topology. Say so, and say it early. A parking-lot OOD answer that budgets for 4,000 requests per second has spent its clock on the wrong axis.
If the interviewer wants that, they will say “and now it is a distributed service across 500 garages.” That is the moment to switch tracks and pull in sd 03.
The round-agnostic behaviours — narrate your thinking, state assumptions and move, never bluff, self-correct immediately — are covered once in the Design Interview Playbook and are assumed here.
The honest part: this is a coding interview wearing a design hat
Knowing which round you are in settles the content. The format is settled by the invitation, and it decides how the clock splits between drawing and typing — and whether “it runs” is a courtesy or the bar.
Read the invite
If it says LLD, machine coding, low-level design, or object-oriented design, and the format is a shared editor, you will be judged on code that runs. The design discussion is the first fifteen minutes of a coding round.
Three formats exist. The table below tells you which one you are in from a detail on the invite, and how much of the clock each one gives to typing.
| Format | How to tell | Where the clock goes | What “done” means |
|---|---|---|---|
| Shared editor / LLD | CoderPad, HackerRank, “bring your laptop” | ~15 min design, ~30 min code | It executes, with a main that exercises it |
| Whiteboard OOD | No editor mentioned, on-site loop | ~25 min design, ~20 min code sketch | Interfaces and one real method, on the board |
| Machine coding (2 hrs) | Common at India-based orgs and some fintechs | 20 min design, 100 min build | A CLI or test suite the interviewer runs |
Three names in that table, unpacked. CoderPad and HackerRank are shared-editor products with a language runtime attached, so the interviewer can press run. A main is the entry point that exercises your classes when the file is executed. A CLI is a command-line interface — a text menu the interviewer drives by typing.
All three formats score the same design decisions. They differ only in how much of the code you have to actually produce, and the shared-editor version is now the common case. That has one blunt consequence:
Do not write pseudocode in a round that has an interpreter open. If
python3 main.pyis one keystroke away and you never press it, the interviewer assumes it does not run. Press it.
What “runs” means
Here is the whole bar, in one file. It is a thermostat: a temperature target, a rule for deciding heat/cool/off, and three asserts proving the rule. Watch for two things — the rule lives in its own class, and the file ends by checking itself.
from abc import ABC, abstractmethod
from dataclasses import dataclass
from enum import Enum
class Mode(Enum):
HEAT = "heat"
COOL = "cool"
OFF = "off"
@dataclass(frozen=True)
class Reading:
celsius: float
class ControlPolicy(ABC):
@abstractmethod
def decide(self, reading: Reading, target: float) -> Mode: ...
class Deadband(ControlPolicy):
"""Do nothing inside +/- width of target, so the compressor does not thrash."""
def __init__(self, width: float) -> None:
self.width = width
def decide(self, reading: Reading, target: float) -> Mode:
if reading.celsius < target - self.width:
return Mode.HEAT
if reading.celsius > target + self.width:
return Mode.COOL
return Mode.OFF
@dataclass
class Thermostat:
target: float
policy: ControlPolicy
def tick(self, reading: Reading) -> Mode:
return self.policy.decide(reading, self.target)
t = Thermostat(target=20.0, policy=Deadband(width=0.5))
assert t.tick(Reading(19.0)) is Mode.HEAT
assert t.tick(Reading(20.2)) is Mode.OFF
assert t.tick(Reading(21.0)) is Mode.COOL
print("thermostat ok")
The three asserts trace the three branches. With a target of 20.0 and a width of 0.5, the deadband runs from 19.5 to 20.5: 19.0 is below it so the answer is HEAT, 20.2 is inside it so the answer is OFF, and 21.0 is above it so the answer is COOL.
The five Python devices in that file
The same five recur in every chapter of this track, so read them once here.
Enum— a closed, named set of constants.Modecan only ever be heat, cool or off. No stray strings.@dataclass— a class whose fields are declared once and whose constructor and equality check are generated for you.frozen=True— makes the dataclass immutable. That turnsReadinginto a value object: a small thing whose whole identity is its contents, compared by what it holds rather than by which copy it is. Two readings of 19.0 °C are the same reading, and nothing can mutate one after construction.ABCand@abstractmethod—ABCis short for abstract base class, a class that cannot be instantiated and exists to declare the interface.@abstractmethodmarks an operation every subclass must supply. Together they are howControlPolicystates a promise with no code behind it.- Dependency injection —
Deadbandis passed into theThermostatrather than created inside it. The caller chooses the collaborator, so a different policy needs no edit toThermostat.
The same thing, drawn
Four boxes, three arrows. The one that matters is the solid arrow from Thermostat to ControlPolicy — that is the seam where tomorrow’s requirement arrives.
classDiagram
class Thermostat {
+float target
+tick(Reading) Mode
}
class ControlPolicy {
<<interface>>
+decide(Reading, float) Mode
}
class Deadband {
+float width
}
class Reading {
+float celsius
}
Thermostat "1" --> "1" ControlPolicy : injected
ControlPolicy <|.. Deadband : implements
Thermostat ..> Reading : uses
Every mark there is UML notation, and it is worth decoding once because the same marks recur in every chapter of this track.
- The boxes. Each box is a class, with its data listed above its operations.
+marks what is public — visible to other classes. <<interface>>. LabelsControlPolicyas a promise with no implementation.- The solid arrow with
"1"at each end. One thermostat holds a reference to exactly one policy. The labelinjectedrecords that it was handed in by the caller. - The dashed arrow with the hollow triangle,
<|... Reads implements:Deadbandis one way of keepingControlPolicy’s promise. - The plain dashed arrow,
..>. Reads uses:Thermostatmentions aReadingin a method signature but does not keep one.
What is present, and what is deliberately absent
The file has an enum, an abstract policy, a value object, one class with one real method, and three asserts that state the behaviour. That is the shape of a passing answer — the domain changes, the shape does not.
Now note what is missing: no getters, no setters, no ThermostatManager, no AbstractPolicyFactoryBuilder.
- Getters and setters are one-line methods that only read or write a single field. A class made of them is a public field with extra ceremony.
ThermostatManageris the placeholder name for a class that does everything and owns nothing.AbstractPolicyFactoryBuilderis the parody of pattern-stacking.
Their absence is deliberate, and interviewers notice it.
The one design move already in it
The deadband is a separate object because of what the interviewer says next: “now support a schedule that overrides the target overnight”, or “now add a smart mode that learns”.
Both of those are a new ControlPolicy and zero edits to Thermostat.
Now imagine decide had been an if/elif chain inside Thermostat.tick. Both changes become edits to the class that also owns the target, the sensor wiring, and the display. Same feature, three times the blast radius.
The 45-minute shape
The forty-five minutes divide into six blocks, and each block lands something different on the interviewer’s notepad. The method inside each block belongs to the next chapter; what matters here is knowing at any minute whether you are behind.
The right-hand column is what actually lands on the notepad — not what you said, but what they wrote.
| Block | Minutes | Clock | What lands on the interviewer’s notepad |
|---|---|---|---|
| Clarify and scope | 5 | 0-5 | Whether your questions change the design |
| Actors and use cases | 5 | 5-10 | Whether you found the operations before the nouns |
| Objects and relationships | 10 | 10-20 | The diagram, with cardinalities |
| The 2-3 decisions | 5 | 20-25 | The pattern, and the change it makes cheap |
| Code the core | 15 | 25-40 | Whether it runs |
| Extend | 5 | 40-45 | Whether the design absorbs the change |
5 + 5 + 10 + 5 + 15 + 5 = 45
Two terms from the second row. An actor is anyone or anything that starts an operation, which includes the non-humans: a clock, a sensor, a scheduled cleanup job. A use case is one such operation described end to end, with the condition that must hold before it may run — “park a vehicle, given that a spot of a fitting size is free”.
The check you run against yourself
Twenty of those forty-five minutes are code and extension. So: if you are at minute 25 and have not typed a class, you are behind. The recovery is to stop drawing and start typing.
The per-block method, the sub-budgets, and what to cut when you are behind are in 02 — A Framework For The OOD Interview.
The first block carries the whole design
Every class diagram is a set of assumptions with boxes attached. That fee rules will change and matching rules will not. That vehicle sizes are a closed list of three. That one spot holds one vehicle.
Get one of those wrong and you do not get a tweak, you get the wrong classes.
Which assumptions to simply declare, which to spend a question on, and the sentence that buys you the right to proceed are in The five assumptions every object model rests on.
The last block is not a formality
The extension question is the round. Everything before it exists to set up a design that can answer it in one sentence.
Weak and strong, in the same eight moments
Put a weak and a strong candidate in the same room — same prompt, same forty-five minutes — and they diverge at eight specific moments. The difference is not vocabulary — the strong column says what follows from each choice, and the weak column stops at the noun.
| Moment | Weak | Strong |
|---|---|---|
| Opening | Starts listing classes | “Who uses this, and what is the one operation that has to be right?” |
| Clarifying | “How many levels?” then never uses the answer | “Can one spot fit two motorcycles? That decides whether occupancy is a boolean or a count” |
| Nouns | Every noun becomes a class | “Size is an enum, Ticket is a class because it has a lifecycle, Color is an attribute” |
| Diagram | Every arrow is a plain line | Composition for owned-lifetime, aggregation for shared, with cardinalities on both ends |
| Patterns | “I would use Strategy, Factory, and Observer” | “Strategy here, because the fee rule changes quarterly and the fit rule does not” |
| Code | 200 lines of getters and setters | The interface plus the one method where the decision lives |
| Concurrency | “We would add a lock” | Names the two threads, the interleaving, and the line the lock goes on |
| Extension | “That would be easy to add” | “New FeeModel subclass, zero edits to ParkingLot, and the cost is that reading the pricing flow now takes two files” |
Three of those rows use words that only pay off if they are precise.
The diagram row — composition vs aggregation. Draw composition when the part cannot outlive the whole: delete the level and its spots go with it. Draw aggregation when the whole merely holds parts that survive it: delete the lot and the monthly-pass holders still exist. The distinction is a claim about deletion, not about how you spelled the field. The arrow notation is derived in Relationships and what the arrows claim.
The concurrency row. A thread is one independently running sequence of steps inside your process. An interleaving is one specific ordering in which two threads’ steps could land. A lock is the flag that forces one thread to wait so a group of steps happens without interruption. The strong answer names all three, in that order.
The code row. “The interface plus the one method” means you show the promise and the single place where the real decision is made — Deadband.decide in the thermostat above — not the twenty methods around it.
The last row is the whole rubric compressed. A pattern with no named cost is a pattern nobody has actually used, and interviewers who have shipped code hear the difference immediately.
What the interviewer is actually holding
The interviewer walks in with three things prepared, in priority order — and knowing the order tells you what to protect when the clock goes bad.
-
A requirement change. Prepared in advance, and delivered around minute 40 — the boundary between the coding block and the Extend block on the clock. That is why volunteering it yourself at minute 40 beats waiting to be asked at minute 41. It is chosen to hit the seam in the obvious design: the joint where a naive model has spread one decision across several classes. In a parking lot it is EV bays or monthly passes; in an elevator it is a service mode; in a vending machine it is refunds.
-
A concurrency question. Concurrency means two things happening at once inside your program, so their steps can interleave. “Two cars arrive at the last spot at the same time.” “Two users buy the last seat.” The answer is never “add a lock” — it is which object owns the lock, what its scope is, and what the failing interleaving looks like without it (04, decision 3).
-
A “why not the simpler thing” question. “Why is that an interface and not a function?” “Why is
Spotnot just a boolean array?” Sometimes the honest answer is that the simpler thing is correct, and saying so scores.
Everything else — naming, package layout, whether you used @dataclass — is noise they will not remember.
What this round is not
Just as important as what the round rewards is what it ignores. Five habits carried in from other interviews cost minutes here that the rubric does not pay for.
| Not this | Because |
|---|---|
| A UML exam | Nobody is checking whether you drew a hollow diamond. They are checking whether the lifetime claim it makes is true |
| A pattern quiz | Naming a pattern is one point; naming the change it makes cheap is three (the Design Interview Playbook makes the same point about architectures) |
| A capacity exercise | One process. If a number matters here it is a cardinality, like “3 entrances”, not a throughput |
| A database schema | Tables come up only if persistence was in scope. Model the objects; mention the mapping in one sentence |
| A LeetCode problem | The data structures are trivial on purpose. A hash map from spot id to spot is the whole algorithm |
The terms those rows lean on, row by row:
- Hollow diamond / filled diamond (row 1) — the UML symbols for aggregation and composition respectively, drawn at the owning end of the line. Drawing the wrong one is a minor slip. But claiming that spots survive the deletion of their level when they do not is a design error, and that is the part being read.
- Throughput (row 3) — how much traffic per second a system carries. It belongs to the system design round.
- Persistence and schema (row 4) — persistence means storing data so that it outlives the running program; a schema is the table-and-column layout a database stores it in.
- Hash map (row 5) — a lookup table from key to value with constant-time access. LeetCode is the algorithm-drilling site whose habits mislead here.
The last row deserves a warning. The algorithmic content of an OOD problem is deliberately near zero, which means every minute you spend optimizing a lookup is a minute not spent on the thing being scored. If you catch yourself thinking about a heap — the structure that keeps the smallest item cheap to find — ask first whether a dict and a list would fail, and say the answer out loud.
The prompt space is small
The round is learnable in a weekend for one reason: almost every prompt is one of six shapes, and recognizing the shape in the first minute tells you where the hard part is before you have modelled anything.
| Shape | Prompts | The hard part |
|---|---|---|
| Resource allocation | Parking lot, hotel booking, seat reservation, locker | Matching rule, pricing rule, and the race for the last unit |
| State machine | Vending machine, elevator, order lifecycle, ATM | Illegal transitions, and where the transition table lives |
| Rules engine | Chess, tic-tac-toe, blackjack, card games | Separating move legality from move execution from win detection |
| Hierarchy / traversal | File system, org chart, comment threads | Composite, and recursion that does not blow the stack |
| Ledger | Splitwise, ATM, wallet, inventory | Money as integers, and an operation that is atomic or absent |
| Feed of events | Logger, notification service, display board | Observer, ordering, and what a slow subscriber does to the producer |
Each row names its hard part in one term, so unpack them once.
- Race (row 1) — two operations reading the same value and both acting on it, so the last unit gets sold twice.
- State machine (row 2) — an object with a small set of named states and a fixed table of which moves between them are legal. An unpaid ticket may be paid; a paid one may not be paid again.
- Composite (row 4) — lets a folder and a file answer the same call, so traversal code does not branch. Recursion that blows the stack is a deep tree walked by a function that calls itself once per level until the interpreter gives up.
- Money as integers (row 5) — storing 5.00 as 500 cents, because binary floating-point cannot represent 0.10 exactly and the errors accumulate. Atomic means the whole operation happens or none of it does, never half.
- Observer (row 6) — the registration mechanism from the pattern table above. A slow subscriber is a listener that takes so long the producer is stuck waiting for it, which is the reason the notification path usually needs a queue.
Two of the six put money or a shared resource under concurrent access, and those are the ones where “add a lock” is not an answer. Practice those first: the allocation shape in 04, then any state machine.
Scoring rubric
The sheet itself, dimension by dimension, is worth grading your own practice attempts against before someone else does. Score yourself a row at a time; the strong column is a sentence you should be able to say out loud.
| Dimension | Weak | Strong |
|---|---|---|
| Scoping | Starts modelling immediately | Names what is in and what is explicitly out, in one sentence |
| Questions | Trivia with no consequence | Each question is followed by the fork its answer creates |
| Object selection | One class per noun | Triages nouns into classes, enums, value objects, and attributes, with a reason |
| Relationships | Undirected lines | Correct composition / aggregation / association with cardinalities |
| Decisions | Names three patterns | Names one or two, each tied to a specific expected change, each with its cost |
| Code | Pseudocode, or 200 lines of accessors | Runs, has asserts, shows the method where the design lives |
| Concurrency | “Add a lock” | The interleaving, the invariant it breaks, and where the lock goes |
| Extension | “That is easy” | Which file is new, which files are untouched, and why the design made that true |
| Restraint | Interfaces everywhere | Refuses at least one abstraction, on the grounds that nothing is going to vary |
Four rows need their vocabulary spelled out:
- Object selection —
Readingin the thermostat was the model value object, and most nouns turn out to be one, which is the whole point of the row. - Relationships — an association is the weakest of the three relationship kinds. One class holds a reference to another and claims nothing about owning it.
- Code — accessors is the collective name for getters and setters. Pseudocode is code-shaped prose that no interpreter will accept. Both are ways of filling a screen without making a decision.
- Restraint — the strong answer here is a refusal said out loud: “I am not putting
Spotbehind an interface. There is one kind of spot, and a size enum covers the variation. If a spot ever needs its own behaviour, that is when the interface earns its keep.”
The dimension that decides the loop — the full day of interviews the round sits inside — is “Extension.” It is the only one where the strong answer requires having maintained something you designed.
Cheat sheet
For the ten minutes before the interview: everything above, compressed into the moves themselves, in clock order.
| Moment | The move |
|---|---|
| Minute 0 | Restate the ask and name what you are excluding (payments, persistence, distribution) |
| Minute 1 | “I am going to look for what changes most often, because that is where the interface goes” |
| Clarifying | Ask only questions whose answer changes a class boundary or a cardinality |
| Nouns | Triage: class, enum, value object, or attribute. Not every noun is a class |
| Diagram | Every arrow carries a cardinality; composition means the part dies with the whole |
| Patterns | One sentence: the change it makes cheap, and the cost you accept |
| Minute 25 | Stop drawing. Type |
| Code | Interface plus the one method that carries the decision. Asserts, not comments |
| Concurrency | Name the two threads and the interleaving before naming the lock |
| Minute 40 | Volunteer an extension before they ask, and say which files stay untouched |
| Any abstraction | If you cannot name the second implementation, do not write the interface |
Next: 02 — A Framework For The OOD Interview — the six steps, the assumptions your class structure rests on and which of them are worth a question, the noun triage that keeps the class list honest, and the failure modes that sink otherwise-correct designs.
The vocabulary those steps assume in depth — encapsulation, the Liskov substitution principle (a subclass must be usable anywhere its base class is, without the caller noticing), coupling, and why Singleton (one globally reachable instance) is usually wrong — is 03 — OOP Fundamentals.