// Design Patterns · 10
Facade
One simple front door to a complicated subsystem.
How it fits together
- CheckoutEndpoint uses / calls CheckoutFacade (one call)
- CheckoutFacade uses / calls InventoryService (1 reserve)
- CheckoutFacade uses / calls PricingService (2 price)
- CheckoutFacade uses / calls TaxService (3 tax)
- CheckoutFacade uses / calls PaymentService (4 charge)
Spot it
- Callers orchestrate five services for one task
- The same call sequence copied across features
- You must learn a subsystem just to use it
It costs
It can grow into a god class, and it hides options some callers still need.
In code
public sealed class CheckoutFacade( IInventoryService inventory, IPricingService pricing, ITaxService tax, IPaymentService payment){ public async Task<Receipt> PlaceOrderAsync(CheckoutRequest request, CancellationToken ct) { await inventory.ReserveAsync(request.Lines, ct); var subtotal = await pricing.PriceAsync(request.Lines, ct); var total = subtotal + await tax.CalculateAsync(subtotal, request.Address, ct); var charge = await payment.ChargeAsync(request.PaymentToken, total, ct); return new Receipt(charge.Id, total); }}Go deeperThe full explanation and what to ask for · 1 min readExpandCollapse
A facade gives a simple interface to a set of classes that are complicated to use together. It does not forbid direct access; it just makes the common path easy.
A facade that keeps absorbing business rules turns into a god object. One that maps one-to-one onto a single service adds a layer without simplifying anything.
A module's public API in a modular monolith is a facade over its internals. Adapter converts one interface to another; facade simplifies many behind one.
Ask for it
- facade
- subsystem
- simplified interface
- orchestration
- module public API
Checkout code calls inventory, pricing, tax and payment services in sequence from three places. Create a CheckoutFacade with one PlaceOrderAsync(request) method that orchestrates them, and make all callers use only that.