DEV Community

Machine coding Master
Machine coding Master

Posted on • Originally published at javalld.com

Java Machine Coding: How to Design a Scalable Cab Booking System (Uber/Ola)

Java Machine Coding: How to Design a Scalable Cab Booking System (Uber/Ola)

Designing a cab-booking system like Uber is a staple in senior machine coding rounds because it tests your ability to handle real-time state changes and extensible business logic. It’s not just about CRUD operations; it’s about how you decouple driver matching from pricing algorithms under high concurrency.

Want to go deeper? javalld.com — machine coding interview problems with working Java code and full execution traces.

The Mistake Most Candidates Make

  • Hardcoding Logic: Embedding "Nearest Driver" logic directly inside a RideService, making it impossible to swap for "Highest Rated Driver" or "Batch Matching" later.
  • Race Conditions: Neglecting thread safety in the ride lifecycle, allowing two drivers to accept the same ride or a rider to cancel while a driver is being assigned.
  • Fat Entities: Mixing pricing logic (Surge, Discounts) with the Trip entity, violating the Single Responsibility Principle.

The Right Approach

  • Core mental model: Treat ride allocation and pricing as pluggable strategies decoupled from the core ride state machine.
  • Key entities: Rider, Driver, Trip, Location, MatchingStrategy, PricingStrategy.
  • Why it beats the naive approach: It allows the system to evolve (e.g., adding "Surge Pricing" or "Carpooling") without modifying the existing booking orchestration code.

The Key Insight (Code)

The secret to a senior-level solution is using the Strategy Pattern for driver matching. This keeps your TripManager clean and extensible.

public interface MatchingStrategy {
    Optional<Driver> findDriver(TripRequest request, List<Driver> availableDrivers);
}

public class NearestDriverStrategy implements MatchingStrategy {
    @Override
    public Optional<Driver> findDriver(TripRequest request, List<Driver> drivers) {
        return drivers.stream()
            .filter(Driver::isAvailable)
            .min(Comparator.comparingDouble(d -> 
                d.getLocation().distanceTo(request.getPickup())));
    }
}
Enter fullscreen mode Exit fullscreen mode

Key Takeaways

  • Strategy Pattern is King: Encapsulate volatile business rules like surge pricing and driver selection into separate strategy classes.
  • Thread-Safe State Machine: Use AtomicReference or ReentrantLock on the Trip object to handle state transitions (Requested -> Accepted -> Completed) safely.
  • Spatial Indexing: In a real-world scenario, don't iterate over all drivers; use Geohashing or a Quadtree to query only drivers within a specific radius.

Full working implementation with execution trace available at https://javalld.com/problems/cab-booking

Top comments (0)