Loading content...
We've covered requirements, entities, matching algorithms, pricing, state management, and design patterns. Now we consolidate everything into a complete, presentable design—the kind you'd present in an interview or use as the blueprint for implementation.
This page covers:
By the end of this page, you will have a complete mental model of the ride-sharing system that you can confidently present in interviews. You'll know how to structure your explanation, what to emphasize, and how to handle follow-up questions about extensions and trade-offs.
The class diagram shows all entities, their attributes, and relationships. This is typically what you'd draw on a whiteboard during an interview.
┌───────────────────────────────────────────────────────────────────────────────┐│ RIDE-SHARING SYSTEM CLASS DIAGRAM │└───────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────┐ ┌─────────────────────┐│ Location │ │ Vehicle │├─────────────────────┤ ├─────────────────────┤│ -latitude: number │ │ -id: string ││ -longitude: number │ │ -make: string ││ -address?: string │ │ -model: string │├─────────────────────┤ │ -licensePlate: str ││ +distanceTo(): km │ │ -type: VehicleType ││ +equals(): boolean │ │ -capacity: number │└─────────────────────┘ └──────────┬──────────┘ △ │ 1 │ │ │ uses │ has │ │┌────────┴────────┐ ┌──────────┴──────────┐│ │ │ Driver ││ Rider │ ├─────────────────────┤├─────────────────┤ │ -id: string ││ -id: string │ │ -name: string ││ -name: string │ │ -status: DriverStat ││ -email: string │ │ -location: Location ││ -status: RiderSt│ │ -rating: number ││ -rating: number │ │ -acceptanceRate: num││ -paymentMethods │ ├─────────────────────┤├─────────────────┤ │ +goOnline() ││ +requestRide() │ │ +goOffline() ││ +cancelRide() │ │ +updateLocation() ││ +rateDriver() │ │ +isAvailable(): bool│└────────┬────────┘ └──────────┬──────────┘ │ 1 │ 0..1 │ requests │ executes │ │ ▼ * ▼ *┌─────────────────────────────────────────────────────┐│ Trip │├─────────────────────────────────────────────────────┤│ -id: string ││ -rider: Rider ││ -driver?: Driver ││ -pickupLocation: Location ││ -destination: Location ││ -state: TripState ││ -estimatedFare: Fare ││ -actualFare?: Fare ││ -requestedAt: Date ││ -matchedAt?: Date ││ -completedAt?: Date │├─────────────────────────────────────────────────────┤│ +assignDriver(driver): void ││ +driverArrived(): void ││ +startTrip(): void ││ +completeTrip(fare): void ││ +cancel(reason): void ││ +getState(): TripState │└─────────────────────────────────────────────────────┘ │ │ uses ▼┌─────────────────────┐ ┌─────────────────────┐│ Fare │ │ <<interface>> │├─────────────────────┤ │ PricingStrategy ││ -baseFare: number │ ├─────────────────────┤│ -distanceFare: num │◄────────│ +calculateFare(): ││ -timeFare: number │ creates │ Fare ││ -surgeMultiplier │ └─────────┬───────────┘│ -totalFare: number │ △└─────────────────────┘ ┌─────────┴───────────┐ │ │ ┌───────────┴───────┐ ┌────────┴────────┐ │ StandardPricing │ │ PremiumPricing │ └───────────────────┘ └─────────────────┘ ┌─────────────────────┐ ┌─────────────────────┐│ <<interface>> │ │ MatchingEngine ││ MatchingStrategy │◄────────├─────────────────────┤├─────────────────────┤ uses │ -strategy ││ +rankDrivers(): │ │ -locationService ││ Driver[] │ ├─────────────────────┤└─────────┬───────────┘ │ +findMatch(request) │ △ │ : MatchResult │ ┌──────┴──────┬───────┐ └─────────────────────┘ │ │ │┌──┴───┐ ┌────┴───┐ ┌─┴────────────┐│Nearest│ │Weighted│ │FairDistribut.││Driver │ │Score │ │Strategy │└───────┘ └────────┘ └──────────────┘Don't draw everything at once. Start with core entities (Rider, Driver, Trip, Location). Add relationships. Then layer in services (MatchingEngine, PricingStrategy). Finally, show patterns (Strategy interfaces). This progressive disclosure helps interviewers follow your thinking.
Sequence diagrams show the dynamic behavior—how objects interact over time. Here are the critical flows:
Rider RideService TripFactory MatchingEngine Driver │ │ │ │ │ │──request(pickup,dest)────►│ │ │ │ │ │ │ │ │ │──createTrip()─►│ │ │ │ │ │──estimate────►│ │ │ │ │◄─fare────────│ │ │ │◄─trip────────│ │ │ │ │ │ │ │ │◄──estimated fare, confirm?│ │ │ │ │ │ │ │ │──confirm()─►│ │ │ │ │ │──trip.startMatching() │ │ │ │ │ │ │ │ │──────────findMatch(trip)────►│ │ │ │ │ │──getNearby()─►│ │ │ │ │◄─drivers─────│ │ │ │ │ │ │ │ │ │──rank()──────►│ │ │ │ │◄─ordered─────│ │ │ │ │ │ │ │ │ │──offer()─────►│ │ │ │ │ ◄──────│accept │ │◄─────────────match result───│ │ │ │ │ │ │ │ │──trip.assignDriver(driver) │ │ │ │──notify───────────────────────────────────►│ │◄──driver assigned, ETA────│ │ │Beyond entities, several services orchestrate the ride-sharing system:
| Service | Responsibility | Key Dependencies |
|---|---|---|
| RideService | Orchestrates ride request through completion | TripFactory, MatchingEngine, TripRepository |
| MatchingEngine | Finds and ranks drivers for requests | DriverLocationService, MatchingStrategy |
| DriverLocationService | Tracks real-time driver positions | Spatial index (Redis/GeoHash) |
| FareCalculator | Calculates estimated and actual fares | PricingStrategy, SurgePricingService |
| SurgePricingService | Manages dynamic pricing zones | Zone definitions, demand/supply metrics |
| PaymentService | Processes payments and payouts | Payment gateway (abstracted) |
| NotificationService | Sends push notifications to apps | FCM/APNS adapters (abstracted) |
| RatingService | Manages bidirectional ratings | User repositories |
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
class RideService { constructor( private tripFactory: TripFactory, private tripRepository: TripRepository, private matchingEngine: MatchingEngine, private fareCalculator: FareCalculator, private paymentService: PaymentService, private notificationService: NotificationService, private eventPublisher: TripEventPublisher ) {} async requestRide( rider: Rider, pickupLocation: Location, destination: Location, vehicleType: VehicleType ): Promise<Trip> { // Validate rider can request if (!rider.isAvailableForTrip()) { throw new Error('Rider already has an active trip'); } if (!rider.hasValidPayment()) { throw new Error('Rider has no valid payment method'); } // Create trip with estimated fare const trip = this.tripFactory.createTrip( rider, pickupLocation, destination, vehicleType ); // Persist trip await this.tripRepository.save(trip); // Update rider status rider.setStatus(RiderStatus.REQUESTING); return trip; } async confirmRide(tripId: string): Promise<MatchResult> { const trip = await this.tripRepository.findById(tripId); // Start matching trip.startMatching(); await this.tripRepository.save(trip); // Find driver const matchResult = await this.matchingEngine.findMatch(trip); if (matchResult.success && matchResult.driver) { // Assign driver trip.assignDriver(matchResult.driver); matchResult.driver.setStatus(DriverStatus.ASSIGNED); await this.tripRepository.save(trip); // Publish event for notifications this.eventPublisher.publish({ tripId: trip.getId(), eventType: TripEventType.DRIVER_ASSIGNED, timestamp: new Date(), data: { riderId: trip.getRider().getId(), driverId: matchResult.driver.getId(), eta: matchResult.estimatedPickupSeconds, } }); } else { trip.failMatching(); await this.tripRepository.save(trip); } return matchResult; } async completeTrip(tripId: string): Promise<Fare> { const trip = await this.tripRepository.findById(tripId); const driver = trip.getDriver()!; // Calculate actual fare const actualFare = this.fareCalculator.calculateActualFare(trip); // Complete trip trip.completeTrip(actualFare); // Process payment await this.paymentService.charge( trip.getRider(), actualFare.totalFare, tripId ); // Credit driver const driverEarning = actualFare.totalFare * 0.75; await this.paymentService.credit(driver, driverEarning, tripId); // Update statuses driver.setStatus(DriverStatus.AVAILABLE); trip.getRider().setStatus(RiderStatus.IDLE); // Persist await this.tripRepository.save(trip); // Publish completion event this.eventPublisher.publish({ tripId, eventType: TripEventType.TRIP_COMPLETED, timestamp: new Date(), data: { fare: actualFare } }); return actualFare; }}Presenting this design in a 45-minute interview requires structure. Here's a recommended approach:
Be prepared for: 'How would you handle driver cancellation affecting rider?' (State machine + rematch). 'What if two requests target the same driver?' (Optimistic locking, OFFERED status). 'How does surge get calculated?' (Zone-based demand/supply ratio). 'How would you add tipping?' (Post-completion tip amount on Trip, PaymentService handles).
A good design anticipates future evolution. Here's how our design accommodates common extensions:
| Feature | How to Extend | Affected Components |
|---|---|---|
| Ride Pooling | Trip holds List<Rider>; PoolMatchingStrategy; shared fare calculation | Trip, MatchingStrategy, PricingStrategy |
| Scheduled Rides | Trip.scheduledTime field; ScheduledRideService; delayed matching | Trip, new ScheduledRideService |
| Multiple Vehicle Types | New VehicleType enum values; new PricingStrategy implementations | VehicleType enum, PricingStrategyFactory |
| International Support | Location includes country/region; region-based pricing; currency handling | Location, Fare, PricingStrategy |
| Promotions/Discounts | DiscountStrategy applied to Fare; PromoCode entity | Fare, new DiscountStrategy |
| Driver Earnings Dashboard | New DriverEarningsService querying trip history | New service, Trip repository queries |
| Real-time Map Tracking | More frequent location observer; WebSocket push to rider app | Observer pattern, new tracking observer |
This design demonstrates:
Congratulations! You've completed the Ride-Sharing Service case study. You now have a comprehensive, interview-ready design covering requirements analysis, entity modeling, matching algorithms, pricing strategies, state management, and design patterns. This knowledge applies to any real-time, multi-party coordination system you'll encounter.