2Brute2Best
πŸ”₯0
A9

One-Call Checkout Across Five Subsystems

Pro OnlyFacade
⚑ 60-Second Architecture SummaryA9 · Facade
Naive Bottleneck→Facade Cure
The Naive Bottleneck: Inventory locks leaked indefinitely during payment failures

Every client controller independently instantiates and choreographs five separate subsystems (`CartValidator`, `InventoryLock`, `PaymentGateway`, `RiderDispatcher`, `NotificationBus`). When the mobile team forgot to release inventory locks upon payment failure, restaurant stock leaked for hours. Duplicating 30+ lines of fragile orchestration and rollback glue across callers creates catastrophic reliability bugs.

The mobile controller developer handled payment failure but omitted inventory.releaseLock(lockId). Because orchestration is duplicated, human errors cause critical resource leaks.

The Pattern Cure: Facade

Provide a unified, simplified interface to a complex set of interfaces in a subsystem, making the subsystem easier to use without hiding its underlying classes.

We introduce CheckoutFacade which aggregates CartValidator, InventoryLock, PaymentGateway, RiderDispatcher, and NotificationBus. It exposes a single method: CheckoutResult placeOrder(const OrderRequest&). The facade enforces the exact sequence (validate β†’ lock β†’ charge β†’ dispatch β†’ notify) and guarantees automatic compensation rollback if any intermediate step fails.

Sprint 9 of 9 Β· The Unified PlaceOrderFacade Entry Point
Story A β€” Food Delivery System β€” Progressive System Build
1. Where our codebase left off
← A8

Across Sprints 1 through 8 (A1–A8), we built modular, robust domain subsystems: interchangeable payment strategies, SRP-compliant pricing and repositories, observer event buses, lifecycle state machines, factory fulfillment dispatchers, DIP test doubles, ISP role interfaces, and 3rd-party vendor adapters.

2. What we are building now

We need to expose a simple, unified order placement entry point (CheckoutFacade / PlaceOrderFacade) for our Mobile App, Web App, and Voice Assistant controllers, coordinating all checkout subsystems in exact sequence.

3. The pain point we hit

Every client controller independently instantiates and choreographs five separate subsystems (CartValidator, InventoryLock, PaymentGateway, RiderDispatcher, NotificationBus). When the mobile team forgot to release inventory locks upon payment failure, restaurant stock leaked for hours. Duplicating 30+ lines of fragile orchestration and rollback glue across callers creates catastrophic reliability bugs.

4. What this unlocks next

The Facade pattern (CheckoutFacade / PlaceOrderFacade) bundles all subsystems behind a single clean placeOrder(request) method with guaranteed automated rollback on failure, completing our end-to-end Food Delivery architecture. With SOLID principles and core GoF patterns mastered on a consumer platform, you are now ready for Story B (Low-Latency Trading Engine)!

01

The product ticket

Ticket Β· A9FOOD-109 Β· Coordinate Five Checkout Subsystems with Rollback Behind a Unified Facade

Placing an order requires orchestrating 5 separate subsystems in exact sequential order: CartValidator, InventoryLock, PaymentGateway, RiderDispatcher, and NotificationBus. Currently, our Mobile API, Web API, and Alexa Voice Assistant controllers each call all 5 subsystems directly. Yesterday, the Mobile controller suffered a major incident: when payment failed, it forgot to call InventoryLock::releaseLock(), leaving restaurant inventory locked for hours and preventing customers from ordering.

Requirements
  • β€’

    Provide a unified CheckoutFacade with a simple placeOrder(OrderRequest) entry point.

  • β€’

    Encapsulate the exact execution pipeline and compensation rollback: if payment fails, unlock reserved inventory; if rider dispatch fails, refund payment and unlock inventory.

  • β€’

    Eliminate duplicated subsystem wiring and fragile error handling across mobile, web, and voice controllers.

The next requirement that breaks naive code

Subsystems must remain independently accessible for specialised non-checkout operations (such as warehouse stock audits or standalone customer notifications) without being hidden inside private monolithic classes.

02

Step 1 β€” The naive code & why it breaks

Every client controller independently instantiates and orchestrates all 5 subsystems, duplicating glue code and frequently forgetting rollback steps on failure.

Naive design (what not to ship) Β· naive.cpp
#include <format>
#include <print>
#include <string>
#include <unordered_set>

struct OrderRequest {
    std::string orderId;
    std::string customerId;
    std::string restaurantId;
    std::string itemName;
    int amountRupees;
};

// 1. Cart Validator Subsystem
class CartValidator {
public:
    bool validate(const OrderRequest& req) {
        if (req.amountRupees <= 0 || req.itemName.empty()) {
            std::println("[CartValidator] Invalid order request: {}", req.orderId);
            return false;
        }
        std::println("[CartValidator] Cart valid for order {}", req.orderId);
        return true;
    }
};

// 2. Inventory Lock Subsystem
class InventoryLock {
    std::unordered_set<std::string> activeLocks_;
    int lockCounter_{100};
public:
    std::string acquireLock(const std::string& restaurantId, const std::string& item) {
        std::string lockId = std::format("LOCK_{}_{}", restaurantId, ++lockCounter_);
        activeLocks_.insert(lockId);
        std::println("[InventoryLock] Acquired {} for item '{}' (Active locks: {})",
                     lockId, item, activeLocks_.size());
        return lockId;
    }

    void releaseLock(const std::string& lockId) {
        activeLocks_.erase(lockId);
        std::println("[InventoryLock] Released {} (Active locks: {})", lockId, activeLocks_.size());
    }

    void commitLock(const std::string& lockId) {
        activeLocks_.erase(lockId);
        std::println("[InventoryLock] Committed {} permanently (Active locks: {})", lockId, activeLocks_.size());
    }

    [[nodiscard]] size_t activeLockCount() const { return activeLocks_.size(); }
};

// 3. Payment Gateway Subsystem
struct PaymentResult {
    bool success;
    std::string txId;
};

class PaymentGateway {
public:
    PaymentResult charge(const std::string& customerId, int amountRupees, bool shouldFail = false) {
        if (shouldFail) {
            std::println("[PaymentGateway] Declined payment of Rs.{} for {}", amountRupees, customerId);
            return {false, ""};
        }
        std::string txId = std::format("TXN_{}", amountRupees * 7);
        std::println("[PaymentGateway] Charged Rs.{} to {} (Tx: {})", amountRupees, customerId, txId);
        return {true, txId};
    }
};

// 4. Rider Dispatcher Subsystem
class RiderDispatcher {
public:
    std::string dispatchRider(const std::string& restaurantId) {
        std::string riderId = "RIDER_42";
        std::println("[RiderDispatcher] Assigned {} for pickup at {}", riderId, restaurantId);
        return riderId;
    }
};

// 5. Notification Bus Subsystem
class NotificationBus {
public:
    void notify(const std::string& channel, const std::string& message) {
        std::println("[NotificationBus:{}] {}", channel, message);
    }
};

// Naive: MobileController juggles all 5 subsystems by hand and forgets rollback!
class NaiveMobileOrderController {
    CartValidator validator_;
    InventoryLock inventory_;
    PaymentGateway payment_;
    RiderDispatcher dispatcher_;
    NotificationBus notifications_;
public:
    void handleMobileCheckout(const OrderRequest& req, bool forcePaymentFailure) {
        std::println("--- Naive Mobile Checkout Initiated ---");
        if (!validator_.validate(req)) return;

        std::string lockId = inventory_.acquireLock(req.restaurantId, req.itemName);

        auto pay = payment_.charge(req.customerId, req.amountRupees, forcePaymentFailure);
        if (!pay.success) {
            std::println("[NaiveMobileController] Payment failed! Returning error to user.");
            // BUG: Developer forgot inventory_.releaseLock(lockId)!
            // The item remains locked indefinitely, blocking other customers!
            return;
        }

        std::string riderId = dispatcher_.dispatchRider(req.restaurantId);
        inventory_.commitLock(lockId);
        notifications_.notify("Customer", "Order placed successfully!");
    }

    [[nodiscard]] size_t leakedLocks() const { return inventory_.activeLockCount(); }
};

int main() {
    NaiveMobileOrderController mobileController;
    OrderRequest req{"ORD-801", "cust_99", "REST_MUM_01", "Tandoori Chicken", 480};

    // Simulate payment failure where naive controller forgets rollback
    mobileController.handleMobileCheckout(req, true);

    std::println("\n[ALERT] Leaked active locks in inventory subsystem: {}",
                 mobileController.leakedLocks());
    return 0;
}
Inventory locks leaked indefinitely during payment failures

The mobile controller developer handled payment failure but omitted inventory.releaseLock(lockId). Because orchestration is duplicated, human errors cause critical resource leaks.

30+ lines of identical glue code duplicated across clients

Mobile, web, and voice controllers all implement the exact same 5-step choreography. Any change to subsystem signatures requires updating every caller.

Subsystem coupling prevents independent evolution

Every client controller directly depends on 5 separate classes. Upgrading payment or inventory APIs forces widespread regressions across client adapters.

03

Step 2 β€” The fix: Facade

Core idea in one sentence

Provide a unified, simplified interface to a complex set of interfaces in a subsystem, making the subsystem easier to use without hiding its underlying classes.

We introduce CheckoutFacade which aggregates CartValidator, InventoryLock, PaymentGateway, RiderDispatcher, and NotificationBus. It exposes a single method: CheckoutResult placeOrder(const OrderRequest&). The facade enforces the exact sequence (validate β†’ lock β†’ charge β†’ dispatch β†’ notify) and guarantees automatic compensation rollback if any intermediate step fails.

Pattern roles in our story
Facade

CheckoutFacade β€” coordinates the 5 checkout subsystems, implements rollback logic on failures, and provides a clean placeOrder() entry point.

Subsystem Classes

CartValidator, InventoryLock, PaymentGateway, RiderDispatcher, NotificationBus β€” handle focused domain tasks and remain directly usable.

Client

MobileController, WebController, VoiceAssistant β€” invoke only CheckoutFacade::placeOrder() without knowing subsystem details.

Brute2Best Pro Content

Unlock Full UML Diagram & C++23 Solution

The interactive UML architecture diagrams, refactored C++23 code, real-world extensions, and interview Q&A are part of Brute2Best Pro. All 7 foundation chapters are 100% free.

All 440 visual dry runs & algorithms
Interactive step-by-step playback with pointer & array state transitions
52 comprehensive LLD chapters
Interactive UML diagrams, real-world stories (Food Delivery, Trading, RPG), and practice solutions
40 C++ basics labs & hardware memory models
Vtables, byte layouts, assembly insights, and multi-threading race conditions
Production-ready C++23 source code
Modern idioms, clean contracts, time/space complexity derivations, and interview takeaways

First anchor question per pattern, Part 1 LLD & Module 1 C++ basics are 100% Free forever.

Systems Integration

Related C++ Systems & Algorithmic Foundations

Deep dive into underlying layers