Steps in LLD Interview
Introduction: The LLD Interview Process
Section titled “Introduction: The LLD Interview Process”When faced with an LLD interview problem, it’s crucial to follow a systematic approach. Jumping straight to code is a common mistake that leads to poor designs. Instead, follow these proven steps to create clean, maintainable solutions.
The LLD Interview Flow
Section titled “The LLD Interview Flow”Step 1: Clarify Requirements
Section titled “Step 1: Clarify Requirements”Before you start designing, make sure you understand the problem!
Why This Step Matters
Section titled “Why This Step Matters”Jumping to solutions without understanding requirements leads to:
- ❌ Missing important features
- ❌ Over-engineering
- ❌ Wrong assumptions
- ❌ Wasted time
What to Ask
Section titled “What to Ask”Functional Requirements:
- What are the core features?
- What are the use cases?
- What are the constraints?
Non-Functional Requirements:
- Scale requirements?
- Performance expectations?
- Availability needs?
Edge Cases:
- What happens in error scenarios?
- What are the boundary conditions?
Interviewer: “Design a Parking Lot System”
Good Questions to Ask:
- “What types of vehicles are supported?” (Car, Motorcycle, Truck)
- “How many spots are there?” (Fixed number or configurable?)
- “Do we need to track parking duration?” (For billing)
- “What happens when the lot is full?” (Reject or waitlist?)
- “Do we need different pricing for different vehicle types?”
- “Do we need to support multiple parking lots?”
Bad Approach:
- “I’ll assume cars only and 100 spots”
- “Let me start coding right away”
Visual: Clarification Process
Section titled “Visual: Clarification Process”Step 2: Identify Actors
Section titled “Step 2: Identify Actors”Actors are the users or external systems that interact with your system.
What Are Actors?
Section titled “What Are Actors?”Actors represent:
- Users - People who use the system
- External Systems - Other systems that interact with yours
- Administrators - People who manage the system
How to Identify Actors
Section titled “How to Identify Actors”Ask yourself:
- Who will use this system?
- What are their roles?
- What actions can they perform?
Actors:
- Driver - Parks and retrieves vehicles
- Admin - Manages parking lot (add spots, view reports)
- System - Automated processes (billing, notifications)
Visual: Actors in Parking Lot System
Section titled “Visual: Actors in Parking Lot System”Common Actors in Different Systems
Section titled “Common Actors in Different Systems”| System | Actors |
|---|---|
| Library Management | Librarian, Member, System |
| Restaurant | Customer, Waiter, Chef, Manager |
| ATM | Customer, Bank, System |
| Elevator | Passenger, Maintenance, System |
Step 3: Identify Entities
Section titled “Step 3: Identify Entities”Entities are the core objects/concepts in your system that have data and behavior.
What Are Entities?
Section titled “What Are Entities?”Entities represent:
- Core Objects - Main concepts in your system
- Data Holders - Objects that store information
- Business Objects - Objects that represent business concepts
How to Identify Entities
Section titled “How to Identify Entities”Look for:
- Nouns in the problem statement
- Things that have properties
- Objects that need to be tracked
- Concepts that have state
Entities:
- ParkingLot - The parking lot itself
- ParkingSpot - Individual parking spaces
- Vehicle - Cars, motorcycles, trucks
- Ticket - Parking ticket issued to driver
- Payment - Payment transaction
Visual: Entities in Parking Lot System
Section titled “Visual: Entities in Parking Lot System”Entity vs Actor
Section titled “Entity vs Actor”Key Difference:
- Actor = External user/system that interacts with your system
- Entity = Internal object/concept within your system
Example:
- Driver (Actor) uses ParkingLot (Entity)
- Admin (Actor) manages ParkingSpot (Entity)
Each class should have a single, well-defined responsibility (Single Responsibility Principle).
Why This Step Matters
Section titled “Why This Step Matters”Proper responsibility assignment leads to:
- ✔ Maintainable code - Easy to understand and modify
- ✔ Testable code - Easy to write unit tests
- ✔ Reusable code - Classes can be reused
- ✔ SOLID principles - Follows best practices
For each entity, ask:
- What does this entity do?
- What data does it hold?
- What operations does it perform?
ParkingLot Responsibilities:
- Manage parking spots
- Assign spots to vehicles
- Find available spots
- Release spots when vehicles leave
ParkingSpot Responsibilities:
- Track its own state (occupied/available)
- Know its type (car/motorcycle/truck)
- Know its location/ID
Ticket Responsibilities:
- Store entry time
- Store vehicle information
- Calculate parking duration
Payment Responsibilities:
- Process payment
- Calculate amount based on duration
- Store payment details
Visual: Responsibility Assignment
Section titled “Visual: Responsibility Assignment”Responsibility Checklist
Section titled “Responsibility Checklist”For each class, ensure:
- Single Responsibility - One reason to change
- Cohesive - Methods are related
- Focused - Not doing too much
- Clear Purpose - Easy to understand what it does
Step 5: Design Class Diagrams
Section titled “Step 5: Design Class Diagrams”Class diagrams show the structure of your system - classes, their attributes, methods, and relationships.
Class diagrams help you:
- Visualize structure - See how classes relate
- Identify relationships - Inheritance, composition, association
- Plan implementation - Know what to code
- Communicate design - Share your design with interviewer
Key Elements of Class Diagrams
Section titled “Key Elements of Class Diagrams”- Classes - With attributes and methods
- Relationships - Inheritance, composition, association
- Interfaces - Abstract contracts
- Access Modifiers - Public, private, protected
classDiagram
class ParkingLot {
-List~ParkingSpot~ spots
-int capacity
+parkVehicle(vehicle: Vehicle) Ticket
+unparkVehicle(ticket: Ticket) Payment
+findAvailableSpot(vehicleType: VehicleType) ParkingSpot
}
class ParkingSpot {
-String spotId
-VehicleType spotType
-boolean isOccupied
-Vehicle vehicle
+parkVehicle(vehicle: Vehicle) void
+unparkVehicle() Vehicle
+isAvailable() boolean
}
class Vehicle {
<<abstract>>
-String licensePlate
-VehicleType vehicleType
+getVehicleType() VehicleType
}
class Car {
+getVehicleType() VehicleType
}
class Motorcycle {
+getVehicleType() VehicleType
}
class Ticket {
-String ticketId
-DateTime entryTime
-Vehicle vehicle
-ParkingSpot spot
+calculateDuration() Duration
}
class Payment {
-String paymentId
-float amount
-DateTime paymentTime
-Ticket ticket
+processPayment() boolean
}
ParkingLot "1" *-- "many" ParkingSpot : contains
ParkingLot --> Ticket : creates
ParkingLot --> Payment : creates
Ticket --> Vehicle : references
Ticket --> ParkingSpot : references
Payment --> Ticket : references
Vehicle <|-- Car : extends
Vehicle <|-- Motorcycle : extends
ParkingSpot --> Vehicle : contains
Visual: Class Relationships
Section titled “Visual: Class Relationships”Step 6: Define Contracts & APIs
Section titled “Step 6: Define Contracts & APIs”Contracts define how classes interact - method signatures, interfaces, and API contracts.
Why Contracts Matter
Section titled “Why Contracts Matter”Well-defined contracts:
- Enable testing - Clear interfaces to mock
- Enable flexibility - Can swap implementations
- Document behavior - Clear what methods do
- Prevent errors - Compile-time checks
What to Define
Section titled “What to Define”- Method Signatures - Parameters, return types, exceptions
- Interfaces - Abstract contracts for classes
- API Contracts - If designing APIs, define endpoints
- Preconditions/Postconditions - What’s expected
Example: Parking Lot System Contracts
Section titled “Example: Parking Lot System Contracts”ParkingLot Interface:
class ParkingLot: def park_vehicle(self, vehicle: Vehicle) -> Ticket: """ Parks a vehicle and returns a ticket.
Args: vehicle: Vehicle to park
Returns: Ticket: Parking ticket with entry details
Raises: ParkingLotFullException: If no spots available InvalidVehicleException: If vehicle type not supported """ pass
def unpark_vehicle(self, ticket: Ticket) -> Payment: """ Unparks a vehicle and processes payment.
Args: ticket: Parking ticket
Returns: Payment: Payment transaction details
Raises: InvalidTicketException: If ticket is invalid """ passinterface ParkingLot { /** * Parks a vehicle and returns a ticket. * * @param vehicle Vehicle to park * @return Ticket Parking ticket with entry details * @throws ParkingLotFullException If no spots available * @throws InvalidVehicleException If vehicle type not supported */ Ticket parkVehicle(Vehicle vehicle) throws ParkingLotFullException, InvalidVehicleException;
/** * Unparks a vehicle and processes payment. * * @param ticket Parking ticket * @return Payment Payment transaction details * @throws InvalidTicketException If ticket is invalid */ Payment unparkVehicle(Ticket ticket) throws InvalidTicketException;}Payment Interface:
class PaymentProcessor: def process_payment(self, ticket: Ticket) -> Payment: """ Processes payment for parking.
Args: ticket: Parking ticket
Returns: Payment: Payment details
Raises: PaymentFailedException: If payment fails """ pass
def calculate_amount(self, ticket: Ticket) -> float: """ Calculates parking fee based on duration.
Args: ticket: Parking ticket
Returns: float: Amount to be paid """ passinterface PaymentProcessor { /** * Processes payment for parking. * * @param ticket Parking ticket * @return Payment Payment details * @throws PaymentFailedException If payment fails */ Payment processPayment(Ticket ticket) throws PaymentFailedException;
/** * Calculates parking fee based on duration. * * @param ticket Parking ticket * @return float Amount to be paid */ float calculateAmount(Ticket ticket);}Visual: API Contracts
Section titled “Visual: API Contracts”Step 7: Handle Edge Cases
Section titled “Step 7: Handle Edge Cases”Edge cases are scenarios that might not be obvious but are important to handle.
Why Edge Cases Matter
Section titled “Why Edge Cases Matter”Handling edge cases shows:
- Mature thinking - You consider all scenarios
- Production readiness - Real systems have edge cases
- Attention to detail - You think thoroughly
- Error handling - You plan for failures
Common Edge Cases
Section titled “Common Edge Cases”- Null/Empty Inputs - What if input is null or empty?
- Boundary Conditions - What if at limits?
- Concurrent Access - What if multiple users?
- Error Scenarios - What if something fails?
- Invalid States - What if system is in wrong state?
Example: Parking Lot System Edge Cases
Section titled “Example: Parking Lot System Edge Cases”Edge Cases to Handle:
-
Parking lot is full
- Return appropriate exception
- Don’t crash
-
Invalid vehicle type
- Validate vehicle type
- Return clear error message
-
Invalid ticket
- Validate ticket exists
- Check ticket hasn’t been used
-
Concurrent parking
- Handle race conditions
- Use locks/synchronization
-
Payment failure
- Handle payment errors
- Don’t release spot if payment fails
Visual: Edge Case Handling
Section titled “Visual: Edge Case Handling”Step 8: Code Implementation
Section titled “Step 8: Code Implementation”Finally, implement your design in code (or pseudo-code).
Implementation Guidelines
Section titled “Implementation Guidelines”- Follow your design - Implement what you designed
- Clean code - Readable, maintainable
- SOLID principles - Apply what you learned
- Design patterns - Use appropriate patterns
- Error handling - Handle edge cases
Example: Parking Lot System Implementation
Section titled “Example: Parking Lot System Implementation”from abc import ABC, abstractmethodfrom datetime import datetimefrom enum import Enumfrom typing import Optional, List
class VehicleType(Enum): CAR = "CAR" MOTORCYCLE = "MOTORCYCLE" TRUCK = "TRUCK"
class Vehicle(ABC): def __init__(self, license_plate: str): self.license_plate = license_plate
@abstractmethod def get_vehicle_type(self) -> VehicleType: pass
class Car(Vehicle): def get_vehicle_type(self) -> VehicleType: return VehicleType.CAR
class ParkingSpot: def __init__(self, spot_id: str, spot_type: VehicleType): self.spot_id = spot_id self.spot_type = spot_type self.is_occupied = False self.vehicle: Optional[Vehicle] = None
def park_vehicle(self, vehicle: Vehicle) -> None: if not self.is_available(): raise ValueError("Spot is already occupied") if vehicle.get_vehicle_type() != self.spot_type: raise ValueError("Vehicle type doesn't match spot type")
self.vehicle = vehicle self.is_occupied = True
def unpark_vehicle(self) -> Vehicle: if not self.is_occupied: raise ValueError("Spot is not occupied")
vehicle = self.vehicle self.vehicle = None self.is_occupied = False return vehicle
def is_available(self) -> bool: return not self.is_occupied
class Ticket: def __init__(self, ticket_id: str, vehicle: Vehicle, spot: ParkingSpot): self.ticket_id = ticket_id self.vehicle = vehicle self.spot = spot self.entry_time = datetime.now()
def calculate_duration(self) -> float: return (datetime.now() - self.entry_time).total_seconds() / 3600
class ParkingLot: def __init__(self, capacity: int): self.capacity = capacity self.spots: List[ParkingSpot] = [] self.tickets: dict[str, Ticket] = {}
def park_vehicle(self, vehicle: Vehicle) -> Ticket: # Find available spot spot = self._find_available_spot(vehicle.get_vehicle_type()) if not spot: raise ValueError("Parking lot is full")
# Park vehicle spot.park_vehicle(vehicle)
# Create ticket ticket_id = f"TICKET_{len(self.tickets) + 1}" ticket = Ticket(ticket_id, vehicle, spot) self.tickets[ticket_id] = ticket
return ticket
def unpark_vehicle(self, ticket_id: str) -> float: if ticket_id not in self.tickets: raise ValueError("Invalid ticket")
ticket = self.tickets[ticket_id] ticket.spot.unpark_vehicle()
# Calculate payment duration = ticket.calculate_duration() amount = duration * 10 # $10 per hour
del self.tickets[ticket_id] return amount
def _find_available_spot(self, vehicle_type: VehicleType) -> Optional[ParkingSpot]: for spot in self.spots: if spot.spot_type == vehicle_type and spot.is_available(): return spot return Noneimport java.time.LocalDateTime;import java.util.*;
enum VehicleType { CAR, MOTORCYCLE, TRUCK}
abstract class Vehicle { protected String licensePlate;
public Vehicle(String licensePlate) { this.licensePlate = licensePlate; }
public abstract VehicleType getVehicleType();}
class Car extends Vehicle { public Car(String licensePlate) { super(licensePlate); }
@Override public VehicleType getVehicleType() { return VehicleType.CAR; }}
class ParkingSpot { private String spotId; private VehicleType spotType; private boolean isOccupied; private Vehicle vehicle;
public ParkingSpot(String spotId, VehicleType spotType) { this.spotId = spotId; this.spotType = spotType; this.isOccupied = false; }
public void parkVehicle(Vehicle vehicle) { if (!isAvailable()) { throw new IllegalStateException("Spot is already occupied"); } if (vehicle.getVehicleType() != spotType) { throw new IllegalArgumentException("Vehicle type doesn't match spot type"); }
this.vehicle = vehicle; this.isOccupied = true; }
public Vehicle unparkVehicle() { if (!isOccupied) { throw new IllegalStateException("Spot is not occupied"); }
Vehicle parkedVehicle = vehicle; this.vehicle = null; this.isOccupied = false; return parkedVehicle; }
public boolean isAvailable() { return !isOccupied; }}
class Ticket { private String ticketId; private Vehicle vehicle; private ParkingSpot spot; private LocalDateTime entryTime;
public Ticket(String ticketId, Vehicle vehicle, ParkingSpot spot) { this.ticketId = ticketId; this.vehicle = vehicle; this.spot = spot; this.entryTime = LocalDateTime.now(); }
public double calculateDuration() { return java.time.Duration.between(entryTime, LocalDateTime.now()).toHours(); }}
class ParkingLot { private int capacity; private List<ParkingSpot> spots; private Map<String, Ticket> tickets;
public ParkingLot(int capacity) { this.capacity = capacity; this.spots = new ArrayList<>(); this.tickets = new HashMap<>(); }
public Ticket parkVehicle(Vehicle vehicle) { ParkingSpot spot = findAvailableSpot(vehicle.getVehicleType()); if (spot == null) { throw new IllegalStateException("Parking lot is full"); }
spot.parkVehicle(vehicle);
String ticketId = "TICKET_" + (tickets.size() + 1); Ticket ticket = new Ticket(ticketId, vehicle, spot); tickets.put(ticketId, ticket);
return ticket; }
public double unparkVehicle(String ticketId) { Ticket ticket = tickets.get(ticketId); if (ticket == null) { throw new IllegalArgumentException("Invalid ticket"); }
ticket.getSpot().unparkVehicle();
double duration = ticket.calculateDuration(); double amount = duration * 10; // $10 per hour
tickets.remove(ticketId); return amount; }
private ParkingSpot findAvailableSpot(VehicleType vehicleType) { return spots.stream() .filter(spot -> spot.getSpotType() == vehicleType && spot.isAvailable()) .findFirst() .orElse(null); }}Complete Process Flow
Section titled “Complete Process Flow”Visual Summary of All Steps
Section titled “Visual Summary of All Steps”graph TD
A[Problem Statement] --> B[1. Clarify Requirements]
B --> C[2. Identify Actors]
C --> D[3. Identify Entities]
D --> E[4. Assign Responsibilities]
E --> F[5. Design Class Diagrams]
F --> G[6. Define Contracts & APIs]
G --> H[7. Handle Edge Cases]
H --> I[8. Code Implementation]
Step-by-Step Checklist
Section titled “Step-by-Step Checklist”Use this checklist for every LLD interview:
- Step 1: Clarify requirements - Ask questions
- Step 2: Identify actors - Who uses the system?
- Step 3: Identify entities - What are the core objects?
- Step 4: Assign responsibilities - What does each class do?
- Step 5: Design class diagrams - Show relationships
- Step 6: Define contracts & APIs - Method signatures
- Step 7: Handle edge cases - Error scenarios
- Step 8: Code implementation - Write clean code
Next Steps: Deep Dive into Each Step
Section titled “Next Steps: Deep Dive into Each Step”Now that you understand the high-level process, let’s dive deep into each step:
Next: Identifying Actors & Entities →
This next guide will teach you how to systematically identify actors and entities with detailed examples and visual diagrams!
Summary
Section titled “Summary”Key Takeaways
Section titled “Key Takeaways”✔ Follow a systematic approach - Don’t jump to code
✔ Clarify requirements first - Ask questions
✔ Identify actors - Who uses the system?
✔ Identify entities - What are the core objects?
✔ Assign responsibilities - Single Responsibility Principle
✔ Design class diagrams - Visualize structure
✔ Define contracts - Clear interfaces
✔ Handle edge cases - Think about errors
✔ Implement cleanly - Follow your design
Remember
Section titled “Remember”LLD interviews are about demonstrating:
- Systematic thinking
- Clean design skills
- Communication ability
- Production-ready mindset
Master these steps, and you’ll excel in any LLD interview! 🚀