Limited time: AI code review, hints, mock interviews, whiteboard analysis, and all Pro features are unlocked. Enroll
⏱️ 7 min read

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


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:

Filtering: Remove nouns that are:

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:


Step 5: Decide What to Build First – 30 Seconds

Priority order:

  1. Models first – Vehicle, Slot, Floor, Ticket, Receipt (just data, no logic)
  2. Core service – ParkingLot.park() and unpark() – the happy path
  3. Supporting services – BillingService, ParkingStrategy
  4. Main/Driver – Demo that shows it working
  5. 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

  1. β€œWalk me through your design approach.” – Describe this process: nouns for entities, verbs for responsibilities, relationships for structure, pattern recognition for design.

  2. β€œ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.

  3. β€œ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.

  4. β€œ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

Free system design + DSA prep. If it helped you crack an interview, consider supporting.

SensAI SensAI
Beta
Listening...
Tap mic to stop voice mode

Shape what we build next

Every piece of feedback is read by the team and directly influences our roadmap.

What type of feedback?

Install SystemCraft

Add to your home screen for instant access, offline reading, and a distraction-free experience.

Offline reading Faster loads No browser tabs App-like feel

Unlock AI Features

One click to activate - no payment, no credit card. Just sign in and you're in.

AI code review and hints
SensAI chat assistant
AI mock interviews
Whiteboard analysis
100% free during early access