Lesson 12 / 25
Facade
One simple front door to a complex subsystem.
Hide the moving parts
Intent: provide a simple, higher-level interface to a set of interfaces in a subsystem. Placing an order might involve inventory, pricing, payments, shipping and email; an OrderFacade.placeOrder() hides that orchestration so controllers stay thin. Facades reduce coupling: callers depend on one object, not five. Unlike an Adapter, a Facade does not aim to match an existing interface; it defines a new, simpler one. Use it when many callers repeat the same multi-step sequence or when you want a clear boundary around a module. Avoid letting the facade grow into a god object that accumulates every operation in the system; split facades by use case.
An order placement facade
Callers make one call; the facade coordinates subsystems.
class OrderFacade {
constructor(
private inventory: InventoryService,
private pricing: PricingService,
private payments: PaymentGateway,
private shipping: ShippingService,
private mailer: Mailer,
) {}
async placeOrder(cart: Cart, customer: Customer) {
await this.inventory.reserve(cart.items);
try {
const quote = await this.pricing.quote(cart, customer);
const payment = await this.payments.charge(customer.id, quote.totalCents);
if (!payment.ok) throw new Error('Payment declined');
const shipment = await this.shipping.schedule(cart.items, customer.address);
await this.mailer.sendOrderConfirmation(customer.email, quote, shipment);
return { orderTotal: quote.totalCents, trackingId: shipment.trackingId };
} catch (err) {
await this.inventory.release(cart.items);
throw err;
}
}
}
// Controller stays thin
app.post('/orders', async (req, res) => {
res.json(await orderFacade.placeOrder(req.body.cart, req.user));
});A hotel concierge
You ask the concierge for dinner and theatre tickets; they deal with the restaurant, the box office and the taxi. You see one simple interface.
Quick check: What is a risk of a Facade that keeps growing?
- It stops compiling
- It turns into a god object that knows about everything
- It forces every caller to use inheritance
- It makes the subsystem faster
Answer
It turns into a god object that knows about everything — Keep facades focused on a use case.