logoNEURAL COOK
SearchAll PostsTagsNotesAuthor
instagramtwitterfacebookyoutubelinkedinmailgithubrss
Copyright © 2026 All rights reserved.
•
VIKI
Built with Vikramaditya Singh
Built with
VIKI - A posts created with Next.js and Tailwind.css
About
Composition, Asociation & Aggregation
Database locking / atomic updates
The Four Pillars of OOP
60-Day LLD & Machine Coding Mastery Roadmap
Class Design
Advanced Class Design & Robust Architecture
Clean Code
Don't Repeat Yourself (DRY) Principle
Keep it Simple, Stupid (KISS) Principle
You Aren't Gonna Need It (YAGNI) Principle
Design Patterns
Design pattern
Problems
Design a Library Management System (LMS)
Design a Parking Lot
Vending Machine
SOLID
D : Dependency Inversion
I : The Interface Segregation Principle
The SOLID Foundation
L : The Liskov Substitution Principle
O : The Open/Closed Principle
S : The Single Responsibility Principle
UML
UML Activity Diagrams: Modeling Process and Workflow
UML Class Diagrams: Static Structure Modeling
Unified Modeling Language (UML): Comprehensive Guide
UML Sequence Diagrams: Modeling Dynamic Interactions
Use Case Diagrams: Functional Requirement Modeling
Low Level Design›problems

Design a Parking Lot

Design a multi-floor parking lot. Vehicles enter through entry gates, receive tickets, park in compatible available spots, and exit through exit gates. On exit, the system calculates the parking fee, collects payment, and makes the spot available again.

The design should be extensible, testable, and safe when multiple gates operate concurrently.

# Core requirements — must implement

  • Support motorcycles, cars, and trucks.
  • Support multiple floors and different spot sizes.
  • Find an available spot compatible with a vehicle.
  • Assign a spot and issue a unique parking ticket.
  • Prevent a vehicle from being parked twice.
  • Track entry time and exit time.
  • Calculate parking fees based on parking duration and vehicle type.
  • Process payment before completing exit.
  • Free the spot after successful checkout.
  • Handle a full parking lot and invalid tickets.
  • Provide availability by floor and spot type.

# Extended requirements — discuss if time permits

  • Multiple entry and exit gates.
  • Different spot-allocation strategies.
  • Configurable hourly, flat-rate, or dynamic pricing.
  • Electric-vehicle charging spots and accessible spots.
  • Reservations and temporary spot holds.
  • Different payment methods and payment failures.
  • Display boards and notifications.

# Non-functional requirements

  • Correctness: never assign one spot to two active tickets.
  • Consistency: a vehicle, active ticket, and occupied spot must agree.
  • Extensibility: new vehicle types and pricing policies should require minimal changes.
  • Testability: business logic should be testable without a database, real clock, or payment provider.
  • Concurrency safety: simultaneous entry requests must not claim the same spot.
  • Maintainability: each class should have a clear responsibility.
  • Performance: finding a spot and retrieving ticket state should avoid unnecessary full-lot scans where practical.

# Explicit assumptions

AreaAssumption for our solution
Spot compatibilityA larger spot can accommodate a smaller vehicle
Vehicle sizeMotorcycle < Car < Truck
ParkingOne vehicle occupies one spot
TicketOne active ticket per vehicle
PricingHourly rate varies by vehicle type; each started hour is charged
TimeEntry and exit timestamps use an injectable Clock
PaymentPayment must succeed before checkout is finalized
ReservationNot part of the initial implementation
PersistenceIn-memory storage for the machine-coding version
ConcurrencyAllocation and release must be atomic

# Solution

# Entities

They represent domain concepts and maintain their own valid state.

  • ParkingLot
    • Owns or references the floors and provides a view of the parking facility. It can coordinate spot discovery through an allocation policy.
  • ParkingFloor
    • Groups the spots on one floor and can report floor-level availability or find compatible spots.
    • A separate class is justified because floors group spots and may have their own policies or reporting.
  • ParkingSpot
    • Owns its identifier, type and occupancy state. It enforces rules such as not assigning an already occupied spot and not releasing an empty one.
  • Vehicle
    • Holds vehicle identity, such as license plate, and its type.
    • Keep identity and vehicle facts here; don't make the vehicle responsible for finding spots or charging fees.
  • Gate
    • Represents an entry or exit gate. It may carry an ID, gate type and operational status.
    • The gate can request a parking operation, but ParkingLotService owns the workflow.
  • Ticket
    • Represents the driver's parking session and checkout reference: ticket ID, vehicle, spot, entry time, optional exit time and status.
    • The ticket is the authoritative record of that session in this design. It replaces the separate Parking entity.
  • Fee
    • A value object representing an amount and currency. For example, INR 240.00.
    • A fee is a calculated monetary value, not a payment transaction.
  • Payment
    • Records a payment attempt: ID, amount, status and provider transaction reference.
    • A ticket may have multiple payment attempts if the first attempt fails. Keep transaction history rather than overwriting every attempt into one record.

??? info "Composition" ParkingLot to ParkingFloor and ParkingFloor to ParkingSpot are composition relationships in this model: floors and spots belong to the facility structure.

# Services — application workflows

  • ParkingLotService
    • main orchestrator for entry and exit.
    • spot assignment
    • checkout orchestration
    • create and register a ticket
    • coordinate payment
  • PaymentService
    • Payment processing and outcome handling
  • FeeService
    • Fee calculation workflow

# Extension points

  • PricingStrategy
  • SpotAllocationStrategy
  • PaymentGateway

The central principle is that services coordinate, the entities protect domain state and strategies supply interchangeable policies.

??? info "SOLID principles applied" - Single Responsibility Principle (SRP) - A class should have one cohesive responsibility—more precisely, one primary reason to change. - ParkingSpot manages occupancy. - FeeService calculates fees. - PaymentService handles payment outcomes. - ParkingLotService coordinates the use case. - Open/Closed Principle (OCP) - The system should be open to new behavior but not require risky modifications to stable workflow code for every extension. OCP does not mean never modifying existing code. It means isolating likely variation behind appropriate extension points. - Adding weekend pricing should mean introducing a new pricing implementation or configuration, not repeatedly editing a large if/else block in checkout. - Liskov Substitution Principle (LSP) - Any implementation of an interface should honor its contract. - A PricingStrategy implementation must return a valid fee under the same agreed rules. - A payment gateway implementation must not silently claim success when payment failed. - Interface Segregation Principle (ISP) - Keep interfaces focused on what a caller actually needs. - A payment gateway should expose payment-related operations it shouldn't also require methods for finding spots or calculating parking duration. - Dependency Inversion Principle (DIP) - High-level workflows should depend on abstractions rather than concrete infrastructure implementations.Dependency injection supplies the chosen implementation to the service, often through its constructor. - PaymentService depends on PaymentGateway, not directly on one provider's SDK. - FeeService depends on PricingStrategy, not a hardcoded hourly calculator.

# Design Patterns

# Pattern 1: Strategy — choose interchangeable behavior

Use Strategy when the same operation can be performed by multiple algorithms or policies.

Pricing strategy

Without Strategy, the fee service can accumulate conditionals for hourly, weekend, subscription and promotional rules.

The strategy is resolved based on the applicable pricing policy, which could come from application configuration or a parking-lot-specific database configuration. ==A resolver or factory maps the policy to a PricingStrategy implementation, and FeeService uses that strategy through the common interface==. If pricing can vary by customer or time, the resolver incorporates those business rules. I would also define how policy changes affect active tickets, potentially recording a pricing-policy version when a session starts.

interface PricingStrategy {
    double calculateFee(int hours);
}
 
class HourlyPricingStrategy implements PricingStrategy {
    private final double ratePerHour;
  
    @Override
    public double calculateFee(int hours) {
        return hours * ratePerHour;
    }
}
 
class FlatRatePricingStrategy implements PricingStrategy {
    private final double flatRate;
 
    @Override
    public double calculateFee(int hours) {
        return flatRate;
    }
}
 
enum PricingMode {
    HOURLY,
    FLAT_RATE
}
 
class PricingStrategyFactory {
 
    static PricingStrategy create(PricingMode mode) {
        switch (mode) {
            case HOURLY:
                return new HourlyPricingStrategy(50);
 
            case FLAT_RATE:
                return new FlatRatePricingStrategy(200);
 
            default:
                throw new IllegalArgumentException(
                    "Unsupported pricing mode: " + mode
                );
        }
    }
}
 
public class Main {
    public static void main(String[] args) {
 
        // Imagine this value came from configuration.
        PricingMode configuredMode = PricingMode.HOURLY;
 
        PricingStrategy strategy =
            PricingStrategyFactory.create(configuredMode);
 
        FeeService feeService = new FeeService(strategy);
 
        double fee = feeService.calculateFee(3);
 
        System.out.println("Parking fee: ₹" + fee);
    }
}

Spot allocation strategy

These strategies should share a clear contract: return a compatible, available candidate or indicate that none exists.

# Pattern 2: Factory — centralize object selection and creation

A Factory is useful when creating an object involves a selection rule or construction complexity.

Introduce one when object creation has meaningful logic, validation or configuration-dependent selection.

# Pattern 3: Dependency Injection — provide collaborators from outside

Dependency Injection (DI) is a technique, not the same thing as Factory or Strategy.

Benefits:

  • Unit tests can provide a fake pricing strategy or payment gateway.
  • The core workflow does not construct infrastructure-specific dependencies itself.
  • Configuration determines which implementation is used.

Constructor injection is often the simplest option. Avoid service classes that locate global dependencies or construct concrete providers internally.

# Pattern 4: Adapter — integrate an external payment provider

An external provider may expose APIs and data structures that don't match your application's payment contract. An Adapter translates that call into the provider-specific API and maps the provider's response into your own payment result.

# Pattern 5: Observer — when other components need updates

A display board at every entrance must automatically update whenever a vehicle enters or exits. So a component needs to react to state changes without being called directly by every entry and exit workflow.

interface AvailabilityObserver {
    void onAvailabilityChanged(
        String lotId,
        int availableSpots
    );
}
 
 
interface AvailabilityPublisher {
    void subscribe(AvailabilityObserver observer);
    void unsubscribe(AvailabilityObserver observer);
    void publishAvailability(
        String lotId,
        int availableSpots
    );
}

A DisplayBoard could implement AvailabilityObserver and update its displayed count when notified.

# Enums vs. polymorphism

ConceptDescription / When to UseDetails / Examples
Enum-based modelingGood fit when types mainly represent categories and differences are small, stable rules.Represent vehicle kinds with VehicleType (MOTORCYCLE, CAR, TRUCK) and spot kinds with SpotType.
PolymorphismUse when behavior genuinely differs across types.Use separate implementations for distinct behaviors.

!!! tip "Decision table"

| Situation | Prefer |
| :--- | :--- |
| A small set of stable categories | Enum |
| Different labels or basic attributes | Enum plus configuration |
| Multiple algorithms for the same operation | Strategy / polymorphism |
| Many growing conditional branches for changing behavior | Consider polymorphism |
| Different data and genuinely different lifecycle | Separate classes where justified |
| A type hierarchy with no meaningful behavioral differences | Usually avoid inheritance |

For this parking lot:

  • enum : VehicleType, SpotType, TicketStatus, PaymentStatus
  • interface : PricingStrategy, SpotAllocationStrategy

!!! Info "Common UML" - Realization — implements an interface - HourlyPricingStrategy ..|> PricingStrategy - Generalization — inheritance - SpecializedType --|> BaseType

# Concurrency

# Idempotent request

An idempotent request can be repeated without consequence, each entry request should have a unique request ID or idempotency key. Store the request and its result so a retry can return the original ticket rather than allocate another spot.

Request ID: ENTRY-8291
Vehicle: CAR-101
Gate: GATE-A

# Atomic spot claiming

If multiple gates must coordinate through a shared, authoritative source of parking-spot state. Each gate can handle requests independently, but two gates must never successfully assign the same spot to two vehicles.

Approach A: In-memory, single application instance

The availability check and state change happen as one synchronized operation for that spot.

ParkingSpot {
  public synchronized boolean tryOccupy(Vehicle vehicle) {
      if (status != SpotStatus.AVAILABLE) {
          return false;
      }
  
      if (!canFit(vehicle)) {
          return false;
      }
  
      this.currentVehicle = vehicle;
      this.status = SpotStatus.OCCUPIED;
      return true;
  }
}

Approach B: Database-backed, multiple application instances

If multiple application use a shared database do an atomic conditional update.

UPDATE parking_spot
SET status = 'OCCUPIED',
    vehicle_id = :vehicleId
WHERE spot_id = :spotId
  AND status = 'AVAILABLE';

For claiming one spot, a conditional update is often enough. You don't need to lock an entire parking floor or parking lot.

!!! tip "Pessimistic vs Optimistic Locking" Pessimistic locking assumes conflict is likely and locks a row while the transaction works with it. It can be useful for short, multi-row operations, but increases waiting and deadlock risk.

Optimistic locking assumes conflicts are less common. A version check detects concurrent changes; the loser retries. It is useful when conflicts are infrequent, but repeated contention can lead to many retries.

The spot claim and ticket creation should generally be in one database transaction

BEGIN TRANSACTION
 
  Verify vehicle has no active ticket
  Claim a compatible spot atomically
  Create active ticket
  Store entry request result
 
COMMIT

If ticket creation fails, roll back the spot claim. If the active-ticket uniqueness constraint rejects the transaction, roll back the claim as well.

# Availability counters and display boards

After the transaction commits, publish an availability event. Display boards and other subscribers update their views.

The transactional outbox pattern is useful: ==write an event record in the same transaction as the state change, then publish it asynchronously==. This avoids the failure where the spot update commits but the process crashes before publishing its event.

# Verification

RequirementHow it’s handled
Support motorcycles, cars, and trucksVehicleType defines vehicle categories; Vehicle stores the type and license plate.
Multiple floors and different spot sizesParkingLot contains floors; ParkingFloor manages spots of different types and sizes.
Find a compatible available spotSpotAllocationStrategy selects a candidate; ParkingSpot validates and claims it.
Assign a spot and issue a unique ticketParkingLotService claims the spot and creates a unique Ticket in one transaction.
Prevent duplicate parkingCheck for an active ticket and enforce a database uniqueness constraint per vehicle.
Track entry and exit timesTicket stores entryTime and finalized exitTime.
Calculate fees by duration and vehicle typeFeeService uses PricingStrategy and ticket duration to calculate the fee.
Process payment before exitPaymentService processes payment; checkout completes only after confirmed success.
Free the spot after checkoutParkingLotService closes the ticket and releases the spot transactionally.
Availability by floor and spot typeParkingFloor and ParkingSpot provide counts; AvailabilityService can aggregate them.
Multiple entry and exit gatesGate identifies each gate; all gates use the shared ParkingLotService.
Different spot-allocation strategiesSpotAllocationStrategy supports implementations such as nearest spot and best fit.
Configurable hourly, flat-rate, or dynamic pricingPricingPolicy stores configuration; PricingStrategyResolver selects the applicable strategy.
EV charging and accessible spotsParkingSpot stores features; SpotCompatibilityPolicy checks vehicle and eligibility requirements.
Reservations and temporary holdsReservationService manages reservations and expiring holds, coordinating with spot availability.
Different payment methods and failuresPaymentService uses PaymentGateway adapters and tracks payment status, retries, and uncertain outcomes.
Display boards and notificationsAvailability changes are published to observers or event consumers that update boards and send notifications.
PreviousDesign a Library Management System (LMS)NextVending Machine
CONTENTS
Core requirements — must implementExtended requirements — discuss if time permitsNon-functional requirementsExplicit assumptionsSolutionEntitiesServices — application workflowsExtension pointsDesign PatternsEnums vs. polymorphismConcurrencyIdempotent requestAtomic spot claimingAvailability counters and display boardsVerification