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
Tripentity, 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())));
}
}
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
AtomicReferenceorReentrantLockon theTripobject 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)