The 5-Minute Design Sketch
The first 10 minutes of a machine coding round determine whether youβll finish. A structured approach to identifying classes, relationships, and patterns saves you from refactoring mid-round. This page gives you a repeatable process.
Why this matters: Candidates who jump straight to code often paint themselves into a corner by minute 30, then spend the remaining time restructuring. Five minutes of design prevents an hour of regret.
Prerequisites
- Machine Coding Round β the format and grading criteria
- UML Class Diagrams β the notation youβll use
The Process
flowchart LR
A["1. Nouns<br/>Identify entities"]:::client
B["2. Verbs<br/>Identify actions"]:::service
C["3. Relationships<br/>Who owns whom"]:::data
D["4. Patterns<br/>Spot the design patterns"]:::client
E["5. Code<br/>Start building"]:::service
A --> B
B --> C
C --> D
D --> E
classDef client fill:#4c3a5e,stroke:#818cf8,color:#e2e8f0
classDef service fill:#1a3a2a,stroke:#4ade80,color:#e2e8f0
classDef data fill:#3b3520,stroke:#fbbf24,color:#e2e8f0
Step 1: Extract Nouns (Entities) β 2 Minutes
Read the problem statement and underline every noun. These are your candidate classes.
Example problem: βDesign a parking lot with multiple floors. Each floor has slots for different vehicle types (car, bike, truck). Users can park and unpark vehicles. The system generates a ticket on entry and a receipt with billing on exit.β
Nouns extracted:
- Parking Lot
- Floor
- Slot
- Vehicle (Car, Bike, Truck)
- Ticket
- Receipt
- User (probably not a class β just the caller)
Filtering: Remove nouns that are:
- Primitive values (name, id, amount β these are fields, not classes)
- Duplicates (car/bike/truck are vehicle types, not separate classes)
- Out of scope (user authentication, payment gateway)
Result: 5-7 core entities is the sweet spot.
Step 2: Extract Verbs (Responsibilities) β 1 Minute
Verbs tell you what each entity does and what services you need.
| Verb | Who does it | Class/Service |
|---|---|---|
| Park | System | ParkingLot.park() |
| Unpark | System | ParkingLot.unpark() |
| Generate ticket | System | Ticket created in park() |
| Calculate billing | BillingService | BillingService.calculate() |
| Find available slot | Strategy | ParkingStrategy.findSlot() |
Step 3: Map Relationships β 1 Minute
Sketch on paper (or in your head):
// Relationships become fields and constructor parameters:
public class ParkingLot {
private List<Floor> floors; // ParkingLot OWNS floors (composition)
private ParkingStrategy strategy; // ParkingLot USES strategy (dependency)
private BillingService billing; // ParkingLot USES billing (dependency)
}
public class Floor {
private int floorNumber;
private List<Slot> slots; // Floor OWNS slots (composition)
}
public class Slot {
private SlotType type;
private Vehicle vehicle; // Slot REFERENCES vehicle (association)
private boolean available;
}
public class Ticket {
private Vehicle vehicle; // Ticket REFERENCES vehicle
private Slot slot; // Ticket REFERENCES slot
private Instant entryTime;
}
# Same relationships in Python
class ParkingLot:
def __init__(self, floors: list[Floor], strategy: ParkingStrategy, billing: BillingService):
self._floors = floors # owns
self._strategy = strategy # uses
self._billing = billing # uses
class Floor:
def __init__(self, floor_number: int, slots: list[Slot]):
self.floor_number = floor_number
self._slots = slots # owns
class Slot:
def __init__(self, slot_type: SlotType):
self.type = slot_type
self.vehicle: Vehicle | None = None # references
self.available = True
class Ticket:
def __init__(self, vehicle: Vehicle, slot: Slot):
self.vehicle = vehicle # references
self.slot = slot # references
self.entry_time = datetime.now()
// Same pattern in C++
class ParkingLot {
vector<unique_ptr<Floor>> floors_; // owns (unique_ptr = composition)
shared_ptr<ParkingStrategy> strategy_; // uses (shared_ptr = dependency)
BillingService* billing_; // uses (raw ptr = non-owning ref)
};
class Floor {
int floorNumber_;
vector<Slot> slots_; // owns (by value = composition)
};
class Slot {
SlotType type_;
Vehicle* vehicle_ = nullptr; // references (raw ptr = association)
bool available_ = true;
};
Step 4: Spot Patterns β 1 Minute
Look for these triggers in the problem statement:
| Trigger Phrase | Pattern to Consider |
|---|---|
| βMultiple types of Xβ or βdifferent strategiesβ | Strategy |
| βStates: idle, active, doneβ or lifecycle | State |
| βNotify when X happensβ | Observer |
| βUndo/redoβ or βtransaction historyβ | Command |
| βContains groups of groupsβ or tree structure | Composite |
| βOptional add-onsβ or layered behavior | Decorator |
| βCreate objects based on typeβ | Factory |
| βMany optional fieldsβ | Builder |
For our parking lot example:
- βDifferent allocation strategiesβ -> Strategy pattern for slot finding
- βDifferent vehicle typesβ -> Enum (not a pattern β just VehicleType.CAR, BIKE, TRUCK)
- βBillingβ -> Could be Strategy if multiple pricing models exist, otherwise just a service
Step 5: Decide What to Build First β 30 Seconds
Priority order:
- Models first β Vehicle, Slot, Floor, Ticket, Receipt (just data, no logic)
- Core service β ParkingLot.park() and unpark() β the happy path
- Supporting services β BillingService, ParkingStrategy
- Main/Driver β Demo that shows it working
- Edge cases and polish β Validation, exceptions, if time permits
The Complete Sketch (What Youβd Write on Paper)
Entities: ParkingLot, Floor, Slot, Vehicle, Ticket, Receipt
Enums: VehicleType (CAR, BIKE, TRUCK), SlotType (SMALL, MEDIUM, LARGE)
Relationships:
ParkingLot --owns--> Floor[] --owns--> Slot[]
Slot --refs--> Vehicle (nullable)
Ticket --refs--> Vehicle, Slot, entryTime
Services:
ParkingStrategy (interface): findSlot(floors, vehicleType) -> Slot
- NearestFirstStrategy
BillingService: calculate(ticket) -> Money
Patterns: Strategy (parking allocation)
Build order: models -> ParkingLot.park/unpark -> billing -> main
This takes 5 minutes. Then you code for 75 minutes with a clear plan.
Common Traps in the Design Phase
| Trap | Impact | How to Avoid |
|---|---|---|
| Designing for 20 minutes | No working code | Cap at 10 min max, then code |
| Skipping design entirely | Refactoring at minute 40 | Spend at least 5 min on paper |
| Over-designing edge cases | Core path never finishes | Build happy path first |
| Adding unnecessary patterns | Wasted time on abstractions | Apply Rule of Three |
| Modeling the user | Users are callers, not domain objects | Donβt model what calls your API |
When to Use vs When to Avoid This Process
| Use This Full Process When | Shortcut When |
|---|---|
| Problem has 5+ entities | Problem is simple (2-3 classes) |
| Multiple patterns needed | Itβs clearly just one pattern (all State) |
| Youβre unfamiliar with the domain | Youβve solved this type before |
| Interviewer expects design discussion first | βJust start coding, weβll discuss laterβ |
Interview Questions
-
βWalk me through your design approach.β β Describe this process: nouns for entities, verbs for responsibilities, relationships for structure, pattern recognition for design.
-
βWhy did you start with models?β β Models are the stable core. Services and patterns may change, but Vehicle and Slot wonβt. Building models first gives you something to work with immediately.
-
βHow do you decide what to skip?β β Ask: βIs this needed for the core demo?β If no, skip it. Mention it as a βwith more timeβ improvement.
-
βWhatβs your typical class count?β β 6-10 classes for a well-designed machine coding solution. Fewer means God classes. More means over-engineering.
See It in Action
| This approach is applied to every problem: Parking Lot | Vending Machine | Elevator | Splitwise |