Cruxly › Low-level design › Running the LLD Interview
Absorbing the Follow-Up
the requirement they add at minute 35
Open the interactive lessonPrompt: your parking lot design is on the board and defended. With ten minutes left the interviewer says:
"Now we want monthly pass holders who get a reserved spot, and electric vehicles that need a charging spot."
What happens to your model?
Why the follow-up is the real question
The first thirty-five minutes established whether you can produce a model. The last ten establish whether the model was load-bearing or decorative.
An interviewer adding a requirement is not moving the goalposts — they are running the only test that matters for a design: does it absorb change, and can you say precisely where the change lands?
There are three possible answers, and they are ranked:
- "It's a new implementation of an existing interface." Best. The seam you argued for is now paying.
- "It's a new field plus one changed method, here." Fine, and common. Name the method.
- "It breaks an invariant; here's what I'd change and what it costs." Also fine — if you identify which invariant. Honest structural revision beats pretending a design stretches further than it does.
The failure mode is a vague "yeah, I'd just add a class for that."
Electric vehicles — the easy one, and why
Charging is an attribute of a spot and a requirement of a vehicle. It does not touch the ticket lifecycle, the fee immutability rule, or ownership.
Spot: hasCharger: boolean Vehicle: needsCharging: boolean
and the fitting rule — which is already an interface, precisely because fitting was expected to vary — gains a clause:
class ChargingAwareFit implements FitPolicy { boolean fits(Vehicle v, Spot s) { if (v.needsCharging() && !s.hasCharger()) return false; return sizeFits(v.size(), s.size()); } }
This is answer type 1: a new implementation of a seam that already existed. Say that out loud — "this is exactly what FitPolicy was for" — because it retroactively justifies the design decision you made at minute fifteen, and the interviewer remembers making you justify it.
One honest caveat worth volunteering: charging introduces a resource that is consumed over time, not just occupied. If the follow-up is "and we bill for electricity," the fee strategy now needs a second input and FeeStrategy.compute changes shape. Naming the next crack before they find it is strong.
Monthly passes — the one that actually strains the model
A reserved spot breaks invariant 1 as originally stated, and it is worth being precise about how.
"A spot holds at most one open ticket" was about occupancy. A reservation means a spot can be unavailable without being occupied — the pass holder isn't here yet, but nobody else may take it. That is a third state the model does not have:
free → occupied
becomes
free → reserved → occupied ↑ | └──────────────────┘
The invariant has to be restated: a spot is in exactly one of {free, reserved, occupied}, and only a free spot can be claimed by a walk-in. That is a real revision, not a patch, and calling it a revision is the honest move.
What it costs:
FitPolicynow filters on state, not just size — it must not offer a reserved spot to a walk-in.- A pass holder arriving finds their reserved spot by identity, not by search. That is a different code path into
admit, soadmiteither branches or splits intoadmitWalkInandadmitPassHolder. Prefer the split: two short methods with different preconditions beat one method with a boolean parameter. - Fees: a pass holder's exit produces no per-hour charge. That is a new
FeeStrategyimplementation returning zero, not anif (passHolder) skipinside the hourly one. The seam holds. - Overstay: what if a pass holder's spot is taken by a walk-in due to a bug, or the pass expires mid-stay? Say that this needs a policy and that you would ask — you do not need to solve it in the last four minutes, but noticing it is the point.
How to answer under time pressure
Ten minutes, two requirements, and a whiteboard already full. The structure that works:
Take them separately and say which is harder, first. "Electric is a spot attribute and my fitting policy already handles it — thirty seconds. Passes are the interesting one, because they add a state my model doesn't have." This immediately shows you can rank difficulty, and buys your remaining time for the part that deserves it.
For the easy one: show it landing on an existing seam. Do not redesign anything. One class, one sentence.
For the hard one: name the broken invariant before proposing a fix. "This breaks 'at most one open ticket' because reserved-but-empty isn't representable" is worth more than a correct patch offered without the diagnosis. The diagnosis is the skill; the patch usually follows in a line or two.
Volunteer one thing you have not solved. Overstay handling, or billing for electricity. Ending on a precisely-named open question reads as engineering judgement. Ending on "yeah that should work" reads as hoping the bell rings.
How to say it in the interview
"Both of these are variation on axes I already have seams for — reservation touches the ticket lifecycle, charging is a spot attribute. Let me take them one at a time and say what breaks."
Checklist
- Ranked the two follow-ups by difficulty before answering either
- Showed the easy change landing on an interface that already existed
- Named the specific invariant the hard change breaks, before patching it
- Restated the invariant in its new form rather than quietly patching around it
- Chose two methods with different preconditions over one boolean parameter
- Handled the pass-holder fee as a strategy implementation, not a branch
- Volunteered one named unsolved problem rather than claiming completeness