Episode 9 — System Design / 9.1 — LLD Foundations

9.1.e — LLD Interview Approach

In one sentence: A structured approach to LLD interviews follows six steps — clarify requirements, identify entities, define classes, establish relationships, define methods, and handle edge cases — and the ability to execute this framework calmly under time pressure is what separates strong candidates from average ones.


Table of Contents


1. The 6-Step Framework

Every LLD interview question can be tackled with this framework:

┌─────────────────────────────────────────────────────────────────────┐
│                   LLD INTERVIEW FRAMEWORK                           │
│                                                                     │
│  ┌──────────────────────────────────────┐                           │
│  │ STEP 1: CLARIFY REQUIREMENTS (5 min)│                           │
│  │ Ask questions. Define scope.         │                           │
│  └──────────────┬───────────────────────┘                           │
│                 ▼                                                    │
│  ┌──────────────────────────────────────┐                           │
│  │ STEP 2: IDENTIFY ENTITIES (5 min)   │                           │
│  │ Find the nouns. List core objects.   │                           │
│  └──────────────┬───────────────────────┘                           │
│                 ▼                                                    │
│  ┌──────────────────────────────────────┐                           │
│  │ STEP 3: DEFINE CLASSES (10 min)     │                           │
│  │ Attributes, types, responsibilities. │                           │
│  └──────────────┬───────────────────────┘                           │
│                 ▼                                                    │
│  ┌──────────────────────────────────────┐                           │
│  │ STEP 4: ESTABLISH RELATIONSHIPS     │                           │
│  │ (8 min) Association, composition,    │                           │
│  │ inheritance, interface.              │                           │
│  └──────────────┬───────────────────────┘                           │
│                 ▼                                                    │
│  ┌──────────────────────────────────────┐                           │
│  │ STEP 5: DEFINE METHODS (10 min)     │                           │
│  │ Core operations. Signatures. Logic.  │                           │
│  └──────────────┬───────────────────────┘                           │
│                 ▼                                                    │
│  ┌──────────────────────────────────────┐                           │
│  │ STEP 6: HANDLE EDGE CASES (7 min)  │                           │
│  │ Error handling. Concurrency.         │                           │
│  │ Design patterns. Extensions.         │                           │
│  └──────────────────────────────────────┘                           │
└─────────────────────────────────────────────────────────────────────┘

2. Step 1 — Clarify Requirements

Never jump straight into design. The first 3–5 minutes should be spent asking clarifying questions to define the scope.

What to Clarify

CategorySample Questions
Core features"What are the must-have features? Should I focus on X or Y?"
Users/Actors"Who interacts with this system? Admin and regular users both?"
Scale"How many concurrent users? Thousands or millions?" (less relevant for LLD, but shows maturity)
Constraints"Is there a max limit on X? Do we need to handle multi-threading?"
Out of scope"Should I handle payments, or is that a separate service?"
Edge cases early"What happens if X fails? Should we support cancellation?"

Example: "Design a Parking Lot System"

Candidate: "Before I start, let me ask a few questions to clarify scope."

Q1: "What types of vehicles should we support? Just cars, or also 
     motorcycles and trucks?"
A:  "Cars, motorcycles, and trucks."

Q2: "Is there a single entrance/exit, or multiple?"
A:  "Multiple entrances and exits."

Q3: "Should the system handle payment?"
A:  "Yes — basic payment when exiting."

Q4: "Do we need different pricing for different vehicle types?"
A:  "Yes — motorcycles cheaper than cars cheaper than trucks."

Q5: "Should I handle a display board that shows available spots?"
A:  "Yes, that would be nice."

Q6: "Should I worry about concurrency — multiple cars entering 
     at the same time?"
A:  "Let's handle it at a basic level."

Why this matters: These questions narrow the problem from "vague parking lot" to a specific set of classes and features. Interviewers explicitly look for this.


3. Step 2 — Identify Entities

Scan the requirements and extract the nouns — these become your candidate classes.

Technique: The Noun Extraction Method

  1. Write down the requirement sentences.
  2. Underline every noun.
  3. Filter out duplicates and irrelevant nouns.
  4. Group related nouns.
Requirement:
"A parking lot has multiple floors. Each floor has parking spots of 
different sizes (small, medium, large). Vehicles (cars, motorcycles, 
trucks) enter through entrance panels and exit through exit panels. 
The system issues a parking ticket when a vehicle enters and 
calculates payment when the vehicle exits."

Extracted nouns:
  parking lot, floor, parking spot, size, vehicle, car, 
  motorcycle, truck, entrance panel, exit panel, 
  parking ticket, payment

Filtered entities (classes):
  ParkingLot, ParkingFloor, ParkingSpot, Vehicle (Car, Motorcycle, Truck),
  EntrancePanel, ExitPanel, ParkingTicket, Payment

Tips for Entity Identification

TipExplanation
Nouns = potential classesParkingLot, Vehicle, Ticket are all nouns
Verbs = potential methods"enters", "exits", "calculates" become methods on classes
Adjectives = potential enums/types"small, medium, large" becomes a SpotSize enum
"Types of X" = inheritance"cars, motorcycles, trucks" are types of Vehicle
Not everything is a class"size" might be an enum, not a class

4. Step 3 — Define Classes

For each entity, define its attributes (data it holds) and its responsibility (what it is supposed to do).

Template for Each Class

Class: [Name]
Responsibility: [One sentence — what this class is for]
Attributes:
  - field1: Type
  - field2: Type
Key methods:
  - method1(): ReturnType
  - method2(param): ReturnType

Example Classes for Parking Lot

enum VehicleType {
  MOTORCYCLE = "MOTORCYCLE",
  CAR = "CAR",
  TRUCK = "TRUCK",
}

enum SpotSize {
  SMALL = "SMALL",     // for motorcycles
  MEDIUM = "MEDIUM",   // for cars
  LARGE = "LARGE",     // for trucks
}

enum TicketStatus {
  ACTIVE = "ACTIVE",
  PAID = "PAID",
}
// Vehicle hierarchy (inheritance)
abstract class Vehicle {
  private licensePlate: string;
  private type: VehicleType;

  constructor(licensePlate: string, type: VehicleType) {
    this.licensePlate = licensePlate;
    this.type = type;
  }

  getLicensePlate(): string { return this.licensePlate; }
  getType(): VehicleType { return this.type; }
}

class Car extends Vehicle {
  constructor(licensePlate: string) {
    super(licensePlate, VehicleType.CAR);
  }
}

class Motorcycle extends Vehicle {
  constructor(licensePlate: string) {
    super(licensePlate, VehicleType.MOTORCYCLE);
  }
}

class Truck extends Vehicle {
  constructor(licensePlate: string) {
    super(licensePlate, VehicleType.TRUCK);
  }
}

Responsibility Check

For each class, verify: "Can I describe this class's responsibility in one sentence?"

ClassResponsibility
ParkingLotManages floors, entrances, exits, and coordinates the overall system
ParkingFloorManages a collection of parking spots on a single floor
ParkingSpotRepresents a single space that can hold one vehicle
VehicleRepresents a vehicle with a license plate and type
ParkingTicketRecords the entry of a vehicle — tracks time and payment
EntrancePanelHandles vehicle arrival and ticket issuance
ExitPanelHandles vehicle departure and payment processing

If a class has two unrelated responsibilities, split it.


5. Step 4 — Establish Relationships

Connect your classes using the correct relationship types from 9.1.c.

Relationship Decision for Parking Lot

RelationshipTypeReasoning
ParkingLot → ParkingFloorComposition (◆)Floors cannot exist without the lot
ParkingFloor → ParkingSpotComposition (◆)Spots cannot exist without the floor
ParkingSpot → VehicleAssociationSpot references a vehicle; vehicle exists independently
ParkingLot → EntrancePanelComposition (◆)Panels are part of the lot
ParkingLot → ExitPanelComposition (◆)Panels are part of the lot
ParkingTicket → VehicleAssociationTicket references the vehicle
Car → VehicleInheritance (▷)Car IS-A Vehicle

Draw the Diagram

                        ┌────────────────────┐
                        │    ParkingLot      │
                        ├────────────────────┤
                        │ - name: str        │
                        │ - address: str     │
                        ├────────────────────┤
                        │ + getAvailableSpots│
                        │ + isFull(): bool   │
                        └───┬────┬───┬───┬───┘
                     ◆ 1..* │    │   │   │ ◆ 1..*
          ┌────────────────┘    │   │   └──────────────┐
          │               ◆ 1..* ◆ 1..*               │
┌─────────▼────┐    ┌─────▼─────┐ ┌──▼───────────┐ ┌──▼───────────┐
│ ParkingFloor │    │ Entrance  │ │  ExitPanel   │ │<<interface>> │
├──────────────┤    │  Panel    │ ├──────────────┤ │ PaymentStrategy
│ - floorNum   │    ├───────────┤ │ + scanTicket │ ├──────────────┤
│ - spots[]    │    │ +getTicket│ │ + processExit│ │ +calculate() │
├──────────────┤    └───────────┘ └──────────────┘ └──────▲───────┘
│ +findAvail() │                                          ┆ impl
│ +parkVehicle │                                    ┌─────┴──────┐
└──────┬───────┘                                    │            │
       │ ◆ 1..*                               ┌────┴───┐  ┌────┴────┐
┌──────▼───────┐    ┌──────────────┐           │Hourly  │  │FlatRate │
│ ParkingSpot  │    │ ParkingTicket│           │Strategy│  │Strategy │
├──────────────┤    ├──────────────┤           └────────┘  └─────────┘
│ - spotId     │    │ - ticketId   │
│ - size: Size │    │ - entryTime  │
│ - isOccupied │    │ - exitTime   │
│ - vehicle?   │    │ - vehicle    │
├──────────────┤    │ - status     │
│ +park()      │    ├──────────────┤
│ +unpark()    │    │ +markPaid()  │
│ +canFit(v)   │    │ +getDuration │
└──────────────┘    └──────────────┘

6. Step 5 — Define Methods

Now implement the core logic. Focus on the most important operations — do not write every getter and setter.

Core Methods for Parking Lot

class ParkingSpot {
  private spotId: string;
  private size: SpotSize;
  private isOccupied: boolean;
  private vehicle: Vehicle | null;

  constructor(spotId: string, size: SpotSize) {
    this.spotId = spotId;
    this.size = size;
    this.isOccupied = false;
    this.vehicle = null;
  }

  canFitVehicle(vehicle: Vehicle): boolean {
    if (this.isOccupied) return false;

    // Size matching: motorcycle → SMALL+, car → MEDIUM+, truck → LARGE only
    const sizeOrder = { SMALL: 1, MEDIUM: 2, LARGE: 3 };
    const vehicleSizeNeeded: Record<VehicleType, SpotSize> = {
      MOTORCYCLE: SpotSize.SMALL,
      CAR: SpotSize.MEDIUM,
      TRUCK: SpotSize.LARGE,
    };

    const neededSize = sizeOrder[vehicleSizeNeeded[vehicle.getType()]];
    const spotSize = sizeOrder[this.size];

    return spotSize >= neededSize;
  }

  park(vehicle: Vehicle): void {
    if (this.isOccupied) throw new Error("Spot already occupied");
    if (!this.canFitVehicle(vehicle)) throw new Error("Vehicle too large for this spot");
    this.vehicle = vehicle;
    this.isOccupied = true;
  }

  unpark(): Vehicle {
    if (!this.isOccupied || !this.vehicle) throw new Error("Spot is empty");
    const vehicle = this.vehicle;
    this.vehicle = null;
    this.isOccupied = false;
    return vehicle;
  }

  getSpotId(): string { return this.spotId; }
  getSize(): SpotSize { return this.size; }
  getIsOccupied(): boolean { return this.isOccupied; }
}

class ParkingFloor {
  private floorNumber: number;
  private spots: ParkingSpot[];

  constructor(floorNumber: number, spots: ParkingSpot[]) {
    this.floorNumber = floorNumber;
    this.spots = spots;
  }

  findAvailableSpot(vehicle: Vehicle): ParkingSpot | null {
    return this.spots.find(spot => spot.canFitVehicle(vehicle)) ?? null;
  }

  getAvailableSpotCount(): number {
    return this.spots.filter(spot => !spot.getIsOccupied()).length;
  }

  getFloorNumber(): number { return this.floorNumber; }
}

class ParkingTicket {
  private ticketId: string;
  private vehicle: Vehicle;
  private spot: ParkingSpot;
  private entryTime: Date;
  private exitTime: Date | null;
  private status: TicketStatus;

  constructor(vehicle: Vehicle, spot: ParkingSpot) {
    this.ticketId = `TKT-${Date.now()}-${Math.random().toString(36).substring(7)}`;
    this.vehicle = vehicle;
    this.spot = spot;
    this.entryTime = new Date();
    this.exitTime = null;
    this.status = TicketStatus.ACTIVE;
  }

  markExit(): void {
    this.exitTime = new Date();
  }

  markPaid(): void {
    this.status = TicketStatus.PAID;
  }

  getDurationHours(): number {
    const end = this.exitTime ?? new Date();
    return (end.getTime() - this.entryTime.getTime()) / (1000 * 60 * 60);
  }

  getVehicle(): Vehicle { return this.vehicle; }
  getSpot(): ParkingSpot { return this.spot; }
  getTicketId(): string { return this.ticketId; }
  getStatus(): TicketStatus { return this.status; }
}

class ParkingLot {
  private name: string;
  private floors: ParkingFloor[];
  private activeTickets: Map<string, ParkingTicket>; // licensePlate → ticket

  constructor(name: string, floors: ParkingFloor[]) {
    this.name = name;
    this.floors = floors;
    this.activeTickets = new Map();
  }

  // Core operation: vehicle enters the lot
  enterVehicle(vehicle: Vehicle): ParkingTicket {
    // Find an available spot across all floors
    for (const floor of this.floors) {
      const spot = floor.findAvailableSpot(vehicle);
      if (spot) {
        spot.park(vehicle);
        const ticket = new ParkingTicket(vehicle, spot);
        this.activeTickets.set(vehicle.getLicensePlate(), ticket);
        return ticket;
      }
    }
    throw new Error("Parking lot is full — no suitable spot available");
  }

  // Core operation: vehicle exits the lot
  exitVehicle(licensePlate: string): ParkingTicket {
    const ticket = this.activeTickets.get(licensePlate);
    if (!ticket) throw new Error("No active ticket found for this vehicle");

    ticket.markExit();
    ticket.getSpot().unpark();
    this.activeTickets.delete(licensePlate);

    return ticket;
  }

  isFull(): boolean {
    return this.floors.every(floor => floor.getAvailableSpotCount() === 0);
  }

  getAvailableSpotCount(): number {
    return this.floors.reduce(
      (total, floor) => total + floor.getAvailableSpotCount(), 0
    );
  }
}

7. Step 6 — Handle Edge Cases

This step separates good candidates from great ones. Proactively identify potential issues.

Edge Cases for Parking Lot

Edge CaseHow to Handle
Lot is fullenterVehicle() throws an error. Display board shows "FULL".
Vehicle already parkedCheck activeTickets before allowing entry
Invalid ticket / lost ticketCharge maximum rate; require manual verification
Concurrent entryTwo cars try to park in the same spot simultaneously — use locking
Vehicle type mismatchTruck tries to park in a small spot — canFitVehicle() rejects it
Payment failureGate does not open; retry payment or escalate to attendant
Power outagePersist ticket data to database, not just in-memory
Midnight boundaryDuration calculation handles date rollover correctly

Mentioning Design Patterns

At this stage, mention patterns you would apply:

┌──────────────────────────────────────────────────────────────────┐
│            DESIGN PATTERNS TO MENTION                            │
│                                                                  │
│  Strategy Pattern  → Different payment calculation strategies    │
│                      (hourly, flat rate, weekend rate)           │
│                                                                  │
│  Singleton Pattern → ParkingLot instance (only one lot)         │
│                                                                  │
│  Factory Pattern   → Creating Vehicle subclasses based on type  │
│                                                                  │
│  Observer Pattern  → Notify display boards when spot count      │
│                      changes                                    │
│                                                                  │
│  State Pattern     → ParkingSpot states (Available, Occupied,   │
│                      Reserved, Maintenance)                     │
└──────────────────────────────────────────────────────────────────┘

8. Time Management in a 45-Minute Interview

┌────────────────────────────────────────────────────────────────┐
│         45-MINUTE LLD INTERVIEW TIME ALLOCATION               │
│                                                                │
│  0:00 ─────  5:00  │ Step 1: Clarify Requirements (5 min)    │
│  ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  │
│                                                                │
│  5:00 ───── 10:00  │ Step 2: Identify Entities (5 min)       │
│  ░░░░░░░░░░████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  │
│                                                                │
│ 10:00 ───── 20:00  │ Step 3: Define Classes (10 min)         │
│  ░░░░░░░░░░░░░░░░░░████████████████░░░░░░░░░░░░░░░░░░░░░░░  │
│                                                                │
│ 20:00 ───── 28:00  │ Step 4: Relationships (8 min)           │
│  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████████░░░░░░░░░░░░  │
│                                                                │
│ 28:00 ───── 38:00  │ Step 5: Methods + Code (10 min)         │
│  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████████████░  │
│                                                                │
│ 38:00 ───── 45:00  │ Step 6: Edge Cases + Wrap Up (7 min)    │
│  ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░████  │
│                                                                │
└────────────────────────────────────────────────────────────────┘

Time Management Tips

TipWhy
Do NOT skip Step 13 minutes of clarification saves 10 minutes of redesigning
Set a mental checkpoint at 20 minBy 20 minutes, you should have classes defined and be starting relationships
Code the happy path firstGet the main flow working before adding error handling
Talk while you writeSilence makes interviewers nervous — narrate your thought process
If stuck, move onSpend too long on one class? Move to relationships and come back
Save 5 min for edge casesMentioning edge cases shows senior-level thinking

9. Common Mistakes

MistakeImpactFix
Jumping straight to codeMisses requirements, needs redesign laterAlways start with clarifying questions
Too many classesOvercomplicates the design, runs out of timeStart with 4–6 core classes, expand only if asked
Too few classesEverything in one God classIf a class has 10+ methods, split it
Ignoring encapsulationAll fields publicDefault to private; add getters only where needed
Using inheritance everywhereRigid, brittle hierarchyFavor composition; use inheritance only for clear "is-a"
Not using interfacesTight coupling between classesDefine interfaces for anything with multiple implementations
Perfect code syndromeSpends 30 min writing perfect syntaxPseudocode is fine; focus on DESIGN, not syntax
Not talkingInterviewer cannot evaluate your thinkingNarrate every decision and trade-off
Ignoring the interviewerMissing hints they are droppingWatch for "what about X?" — it is a hint, not a question
No edge casesShows junior-level thinkingProactively raise 3–5 edge cases at the end

10. Example Walkthrough — Parking Lot System

Let us walk through the full 6-step framework for "Design a Parking Lot System" as if we are in a live interview.

Step 1: Clarify (minutes 0–5)

"I want to make sure I understand the requirements correctly.

1. Vehicle types: cars, motorcycles, trucks — confirmed.
2. Multiple floors with different spot sizes.
3. Multiple entrances and exits.
4. System issues a ticket on entry, calculates payment on exit.
5. Display board showing available spots per floor.
6. Different pricing per vehicle type.

Let me list what I consider IN scope and OUT of scope:
  IN:  Vehicle management, spot assignment, ticketing, payment calc
  OUT: Actual payment gateway integration, mobile app, reservations

Does this sound right?"

Step 2: Identify Entities (minutes 5–10)

"Let me identify the core entities from these requirements:

Entities:
  - ParkingLot        — the system itself
  - ParkingFloor      — a level in the lot  
  - ParkingSpot       — individual parking space
  - Vehicle           — abstract, with Car/Motorcycle/Truck subtypes
  - ParkingTicket     — issued on entry, used on exit
  - EntrancePanel     — where vehicles enter
  - ExitPanel         — where vehicles exit and pay
  - DisplayBoard      — shows available spots

Enums:
  - VehicleType       — MOTORCYCLE, CAR, TRUCK
  - SpotSize          — SMALL, MEDIUM, LARGE  
  - TicketStatus      — ACTIVE, PAID

Step 3: Define Classes (minutes 10–20)

(Draw class boxes on whiteboard with attributes and key methods — as shown in Steps 3-5 above)

Step 4: Relationships (minutes 20–28)

(Draw the class diagram with arrows, diamonds, and multiplicity — as shown in Step 4 above)

Step 5: Methods (minutes 28–38)

(Write the core methods: enterVehicle, exitVehicle, findAvailableSpot, canFitVehicle, calculatePayment)

Step 6: Edge Cases + Wrap Up (minutes 38–45)

"Let me address some edge cases and extensions:

1. CONCURRENCY: Two cars arriving simultaneously — I would use a
   mutex/lock on spot assignment to prevent double-booking.

2. FULL LOT: enterVehicle() checks availability first. Display
   board updates via Observer pattern.

3. LOST TICKET: Charge the maximum daily rate. Require license
   plate lookup from security camera logs.

4. PRICING FLEXIBILITY: I used a Strategy pattern for payment
   calculation so we can swap pricing models (hourly, flat, 
   weekend) without changing the core logic.

5. EXTENSIBILITY: If we want to add reserved/VIP spots, I would 
   add a SpotStatus enum (AVAILABLE, OCCUPIED, RESERVED, 
   MAINTENANCE) and a ReservedSpot subclass.

6. PERSISTENCE: In production, I would persist tickets and spot
   state to a database rather than keeping them in memory.

Full Sequence Diagram for Enter Vehicle

  ┌──────┐   ┌──────────┐   ┌───────────┐   ┌──────────┐   ┌──────────┐
  │Driver│   │Entrance  │   │ParkingLot │   │  Floor   │   │  Spot    │
  └──┬───┘   │ Panel    │   └─────┬─────┘   └────┬─────┘   └────┬─────┘
     │       └────┬─────┘         │               │              │
     │            │               │               │              │
     │ arrives    │               │               │              │
     │───────────►│               │               │              │
     │            │               │               │              │
     │            │ enterVehicle  │               │              │
     │            │ (vehicle)     │               │              │
     │            │──────────────►│               │              │
     │            │               │               │              │
     │            │               │ findAvailable │              │
     │            │               │ Spot(vehicle) │              │
     │            │               │──────────────►│              │
     │            │               │               │              │
     │            │               │               │ canFit       │
     │            │               │               │ Vehicle(v)   │
     │            │               │               │─────────────►│
     │            │               │               │              │
     │            │               │               │  true        │
     │            │               │               │◄─ ─ ─ ─ ─ ─ │
     │            │               │               │              │
     │            │               │    spot       │              │
     │            │               │◄─ ─ ─ ─ ─ ─ ─│              │
     │            │               │               │              │
     │            │               │           park(vehicle)      │
     │            │               │─────────────────────────────►│
     │            │               │               │              │
     │            │               │ create ticket │              │
     │            │               │───┐           │              │
     │            │               │   │           │              │
     │            │               │◄──┘           │              │
     │            │               │               │              │
     │            │   ticket      │               │              │
     │            │◄─ ─ ─ ─ ─ ─ ─│               │              │
     │            │               │               │              │
     │  ticket +  │               │               │              │
     │  gate opens│               │               │              │
     │◄─ ─ ─ ─ ─ │               │               │              │
     │            │               │               │              │

11. Key Takeaways

  1. Follow the 6-step framework religiously — it prevents you from getting lost and gives you a clear structure to fill time productively.
  2. Clarify first — 3–5 minutes of questions saves 10+ minutes of redesign. Interviewers expect and reward this.
  3. Nouns become classes, verbs become methods — this extraction technique works for every LLD problem.
  4. Draw the class diagram before writing code — it forces you to think about relationships and prevents a tangled design.
  5. Talk constantly — the interviewer cannot read your mind. Narrate every decision: "I am using composition here because rooms cannot exist without the building."
  6. Mention design patterns — even naming them shows awareness. "I would use Strategy pattern for pricing" earns points.
  7. Edge cases show seniority — proactively raising concurrency, error handling, and extensibility demonstrates production experience.
  8. Time management is critical — set mental checkpoints. If you are still clarifying requirements at minute 10, you are behind.
  9. Do not aim for perfection — a solid design with 6 well-structured classes beats a half-finished design with 15 classes.

Explain-It Challenge

Pick any LLD problem (elevator system, food delivery app, chess game) and practice the 6-step framework out loud, speaking to an imaginary interviewer. Time yourself for 45 minutes. Record yourself if possible — watching the replay reveals habits you did not notice.


Previous → 9.1.d — UML Diagrams

← Back to 9.1 — LLD Foundations (README)