Scoping is a timed skill. Given "design a ride-sharing app," you have about five minutes to converge on a problem small enough to finish but rich enough to show depth. Here is a concrete procedure.
The 5-minute scoping procedure
Minute 1 — Restate and bound
Repeat the prompt in your own words and immediately propose a boundary: "I'll design the in-memory class model for matching a rider to a driver and managing a ride's lifecycle — not the maps service, payments gateway, or the distributed backend." Boundaries are subtractive; cutting scope is your most powerful move.
Minutes 2–3 — List functional requirements
Write 4–6 bullet points of must-have operations. Keep them as verbs the system performs:
- requestRide(rider, pickup, drop) - matchDriver(request) -> nearest / surge strategy - ride lifecycle: REQUESTED -> ASSIGNED -> ONGOING -> COMPLETED - computeFare(ride) -> pluggable pricing - (out of scope) live GPS, payment settlement, ratings
Minute 4 — Note non-functional drivers
One line each on the axes that will shape classes: concurrency (many riders matching at once), extensibility (new pricing/matching strategies), and what you're deliberately deferring.
Minute 5 — Pick the "happy path" to drive
Choose the one core flow you'll model end-to-end. Everything else is a follow-up. For ride-sharing that's request → match → ride lifecycle → fare. Announcing this focus keeps you from sprawling.
Heuristics for cutting scope fast
Anti-pattern: boiling the ocean
If you try to model GPS tracking, surge pricing, payments, ratings, and driver onboarding, you'll have a dozen empty class stubs and no working core at minute 40. A tight, complete slice with clean seams (interfaces where the deferred parts will plug in) demonstrates far more than broad, shallow coverage.