DEV Community

Srishti Prasad
Srishti Prasad

Posted on

πŸš– Designing an Uber/Ola-like Ride Booking System (LLD + UML Approach)

When I started practicing Low-Level Design, I realized that jumping directly into drawing UML diagrams often leads to messy, confusing designs.

So instead, I followed a step-by-step approachβ€”breaking the system into components, understanding flow, and then translating that into a clean UML.

Here’s how I approached designing a simplified Uber/Ola system.

🎯 Problem Statement

Design a ride-booking system that can:

Create a trip (source β†’ destination)
Match a driver
Calculate price
Support extensibility (new pricing logic, ride types, etc.)

Step 1: Identify Core Components & Actors

Start simple. Who are the main actors?

Rider β†’ requests a trip
Driver β†’ fulfills the trip

These are the foundation of the system. Everything else builds around them.

Step 2: Define Features & Assumptions

To avoid overcomplicating early design, I made a few assumptions:

Each driver has one vehicle
One rider books one trip at a time
We focus only on trip creation flow

πŸ‘‰ This helps narrow scope and focus on correctness over completeness.

Step 3: Outline the Logical Flow (Client Perspective)

Instead of jumping into classes, I first defined the end-to-end flow from client side:

Rider enters source, destination, rideType
        ↓
RideBookingSystem receives request
        ↓
RideService orchestrates flow
        ↓
RideFactory β†’ creates Bike / Auto / Cab
        ↓
StrategyMgr β†’ selects pricing & matching strategy
        ↓
Driver is matched
        ↓
Price is calculated
        ↓
Trip is created
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ This step is crucialβ€”it directly drives your class design.

Step 4: Identify Classes & Responsibilities

Core Entities

Trip β†’ represents a ride
Rider / Driver β†’ system users
TripMetaData β†’ context (ratings, locations)

Manager Classes (to organize logic)

TripMgr β†’ manages trip lifecycle
RiderMgr / DriverMgr β†’ manage users
StrategyMgr β†’ selects strategies

πŸ‘‰ These act as centralized handlers for data and operations.

Step 5: Define Relationships

Understanding relationships is key to a good UML.

Aggregation (loosely coupled)
RiderMgr β†’ Rider
DriverMgr β†’ Driver

πŸ‘‰ These objects can exist independently.

Composition (tightly coupled)
TripMgr β†’ Trip

πŸ‘‰ Trip lifecycle is controlled by TripMgr.

Step 6: Apply Design Patterns

To make the system extensible:

πŸ”Ή Singleton Pattern

Used for:

  • TripMgr
  • RiderMgr
  • DriverMgr

πŸ‘‰ Ensures a single source of truth as these classes will be interacting with database.

πŸ”Ή Strategy Pattern

Used for:

  • Pricing Strategy
  • Driver Matching Strategy
PricingStrategy β†’ Default / RatingBased
DriverMatchingStrategy β†’ LeastTimeBased
Enter fullscreen mode Exit fullscreen mode

πŸ‘‰ This avoids hardcoding logic and allows easy extension.

πŸ”Ή Factory Pattern (Ride Selection)
To support multiple ride types:

RideFactory β†’ BikeRide / AutoRide / CabRide
Enter fullscreen mode Exit fullscreen mode

Flow:

  • User selects ride type
  • RideService delegates creation to RideFactory
  • Factory returns appropriate ride type object


πŸ‘‰ This centralizes ride creation and avoids scattered conditional logic.

Have attached a rough UML diagram for reference

This exercise helped me:

Think in terms of flow before code
Understand where Factory vs Strategy fits
Appreciate the importance of clear system boundaries

Still learningβ€”would love to hear how others approach this problem πŸ™Œ

Top comments (0)