<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Facade Pattern | Alan P. Barber</title><link>https://alanbarber.com/tags/facade-pattern/</link><atom:link href="https://alanbarber.com/tags/facade-pattern/index.xml" rel="self" type="application/rss+xml"/><description>Facade Pattern</description><generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>en-us</language><copyright>© 2026 Alan P. Barber &amp;middot; Hosting by [CldSvr.com](http://cldsvr.com)</copyright><lastBuildDate>Mon, 27 Apr 2026 00:00:00 -0400</lastBuildDate><image><url>https://alanbarber.com/img/portrait.jpg</url><title>Facade Pattern</title><link>https://alanbarber.com/tags/facade-pattern/</link></image><item><title>The Facade Pattern for C# Developers</title><link>https://alanbarber.com/post/the-facade-pattern-for-csharp-developers/</link><pubDate>Mon, 27 Apr 2026 00:00:00 -0400</pubDate><guid>https://alanbarber.com/post/the-facade-pattern-for-csharp-developers/</guid><description>&lt;p>The Facade pattern is one of the simpler patterns to understand, but it&amp;rsquo;s also one of the most useful. It gives you a clean, simple interface to a messy or complex subsystem. If you&amp;rsquo;ve ever wrapped a bunch of related calls behind a single method to make life easier for the caller, you&amp;rsquo;ve already used a facade.&lt;/p>
&lt;h2 id="lets-define-the-pattern">Let&amp;rsquo;s Define the Pattern&lt;/h2>
&lt;p>A facade is a class that provides a simplified interface to a larger body of code. It hides the complexity of the subsystem and exposes only what the caller needs.&lt;/p>
&lt;p>The key idea is that the facade knows how to coordinate the subsystem, but the caller doesn&amp;rsquo;t have to. The caller gets a simple API. The messy details stay behind the curtain.&lt;/p>
&lt;p>What a facade is &lt;em>not&lt;/em>: it&amp;rsquo;s not about adding new functionality. It&amp;rsquo;s about making existing functionality easier to use. The subsystem still exists and still works the same way. The facade just provides a friendlier front door.&lt;/p>
&lt;h2 id="the-problem-it-solves">The Problem It Solves&lt;/h2>
&lt;p>Imagine you&amp;rsquo;re building an e-commerce system. Placing an order involves multiple steps:&lt;/p>
&lt;pre>&lt;code class="language-csharp">public class OrderController
{
public async Task&amp;lt;IActionResult&amp;gt; PlaceOrder(OrderRequest request)
{
// Validate inventory
var inventory = await _inventoryService.CheckAvailability(request.Items);
if (!inventory.AllAvailable)
return BadRequest(&amp;quot;Some items are out of stock&amp;quot;);
// Calculate pricing
var pricing = await _pricingService.Calculate(request.Items, request.CustomerId);
// Apply discounts
var discounts = await _discountService.GetApplicableDiscounts(request.CustomerId);
var finalPrice = _discountService.Apply(pricing, discounts);
// Process payment
var payment = await _paymentService.Charge(request.PaymentMethod, finalPrice);
if (!payment.Success)
return BadRequest(&amp;quot;Payment failed&amp;quot;);
// Create order
var order = await _orderService.Create(request, finalPrice, payment.TransactionId);
// Send confirmation
await _emailService.SendOrderConfirmation(order);
// Update inventory
await _inventoryService.Reserve(request.Items);
return Ok(order);
}
}
&lt;/code>&lt;/pre>
&lt;p>This controller knows way too much. It&amp;rsquo;s coordinating six different services, handling their interactions, and managing the workflow. Every controller that needs to place an order has to repeat this dance.&lt;/p>
&lt;p>The problems:&lt;/p>
&lt;ul>
&lt;li>The controller is doing orchestration work that doesn&amp;rsquo;t belong there&lt;/li>
&lt;li>Changes to the order process require editing every place that places orders&lt;/li>
&lt;li>Testing requires mocking six services&lt;/li>
&lt;li>New developers have to understand the entire flow to make changes&lt;/li>
&lt;/ul>
&lt;h2 id="core-structure-and-roles">Core Structure and Roles&lt;/h2>
&lt;p>The Facade pattern has two main parts:&lt;/p>
&lt;p>&lt;strong>Facade&lt;/strong>: The simplified interface that clients use. It knows how to coordinate the subsystem.&lt;/p>
&lt;p>&lt;strong>Subsystem classes&lt;/strong>: The existing classes that do the actual work. They don&amp;rsquo;t know about the facade and don&amp;rsquo;t change.&lt;/p>
&lt;pre>&lt;code class="language-csharp">public class OrderFacade
{
private readonly IInventoryService _inventoryService;
private readonly IPricingService _pricingService;
private readonly IDiscountService _discountService;
private readonly IPaymentService _paymentService;
private readonly IOrderService _orderService;
private readonly IEmailService _emailService;
public OrderFacade(
IInventoryService inventoryService,
IPricingService pricingService,
IDiscountService discountService,
IPaymentService paymentService,
IOrderService orderService,
IEmailService emailService)
{
_inventoryService = inventoryService;
_pricingService = pricingService;
_discountService = discountService;
_paymentService = paymentService;
_orderService = orderService;
_emailService = emailService;
}
public async Task&amp;lt;OrderResult&amp;gt; PlaceOrder(OrderRequest request)
{
var inventory = await _inventoryService.CheckAvailability(request.Items);
if (!inventory.AllAvailable)
return OrderResult.Failed(&amp;quot;Some items are out of stock&amp;quot;);
var pricing = await _pricingService.Calculate(request.Items, request.CustomerId);
var discounts = await _discountService.GetApplicableDiscounts(request.CustomerId);
var finalPrice = _discountService.Apply(pricing, discounts);
var payment = await _paymentService.Charge(request.PaymentMethod, finalPrice);
if (!payment.Success)
return OrderResult.Failed(&amp;quot;Payment failed&amp;quot;);
var order = await _orderService.Create(request, finalPrice, payment.TransactionId);
await _emailService.SendOrderConfirmation(order);
await _inventoryService.Reserve(request.Items);
return OrderResult.Success(order);
}
}
&lt;/code>&lt;/pre>
&lt;p>Now the controller becomes simple:&lt;/p>
&lt;pre>&lt;code class="language-csharp">public class OrderController
{
private readonly OrderFacade _orderFacade;
public OrderController(OrderFacade orderFacade)
{
_orderFacade = orderFacade;
}
public async Task&amp;lt;IActionResult&amp;gt; PlaceOrder(OrderRequest request)
{
var result = await _orderFacade.PlaceOrder(request);
return result.IsSuccess
? Ok(result.Order)
: BadRequest(result.Error);
}
}
&lt;/code>&lt;/pre>
&lt;p>The controller no longer knows or cares about inventory, pricing, discounts, payments, or emails. It just asks the facade to place an order.&lt;/p>
&lt;h2 id="when-to-reach-for-a-facade">When to Reach for a Facade&lt;/h2>
&lt;p>Facades are useful in several situations:&lt;/p>
&lt;p>&lt;strong>Simplifying complex subsystems&lt;/strong>: When you have multiple services that need to work together in a specific sequence, a facade can hide that coordination.&lt;/p>
&lt;p>&lt;strong>Reducing coupling&lt;/strong>: Instead of a class depending on five services, it depends on one facade. Changes to the subsystem don&amp;rsquo;t ripple out to every consumer.&lt;/p>
&lt;p>&lt;strong>Providing a clean API for external consumers&lt;/strong>: If you&amp;rsquo;re building a library or SDK, a facade can give users a simple entry point without exposing internal complexity.&lt;/p>
&lt;p>&lt;strong>Legacy system integration&lt;/strong>: When wrapping old code that has a messy API, a facade can present a cleaner interface to the rest of your application.&lt;/p>
&lt;h2 id="facade-vs-similar-concepts">Facade vs Similar Concepts&lt;/h2>
&lt;p>&lt;strong>Facade vs Adapter&lt;/strong>: An adapter converts one interface to another. A facade simplifies a complex interface. An adapter is about compatibility; a facade is about convenience.&lt;/p>
&lt;p>&lt;strong>Facade vs Service Layer&lt;/strong>: These overlap quite a bit. A service layer often acts as a facade over domain logic and infrastructure. The difference is mostly intent: &amp;ldquo;service layer&amp;rdquo; implies a specific architectural role, while &amp;ldquo;facade&amp;rdquo; is a general pattern.&lt;/p>
&lt;p>&lt;strong>Facade vs Mediator&lt;/strong>: A mediator coordinates communication between objects that know about each other. A facade provides a simple interface to objects that don&amp;rsquo;t know about the facade. The subsystem classes in a facade don&amp;rsquo;t change; in a mediator pattern, the colleagues typically reference the mediator.&lt;/p>
&lt;p>&lt;strong>Facade vs Aggregate Root (DDD)&lt;/strong>: In Domain-Driven Design, an aggregate root controls access to a cluster of domain objects. It&amp;rsquo;s similar in spirit to a facade but focused on domain invariants rather than simplifying an API.&lt;/p>
&lt;h2 id="facade-with-dependency-injection">Facade with Dependency Injection&lt;/h2>
&lt;p>Facades work naturally with DI. You inject the subsystem dependencies into the facade, then inject the facade where it&amp;rsquo;s needed.&lt;/p>
&lt;pre>&lt;code class="language-csharp">services.AddScoped&amp;lt;IInventoryService, InventoryService&amp;gt;();
services.AddScoped&amp;lt;IPricingService, PricingService&amp;gt;();
services.AddScoped&amp;lt;IDiscountService, DiscountService&amp;gt;();
services.AddScoped&amp;lt;IPaymentService, PaymentService&amp;gt;();
services.AddScoped&amp;lt;IOrderService, OrderService&amp;gt;();
services.AddScoped&amp;lt;IEmailService, EmailService&amp;gt;();
services.AddScoped&amp;lt;OrderFacade&amp;gt;();
&lt;/code>&lt;/pre>
&lt;p>If you want to abstract the facade behind an interface (useful for testing or if you might have multiple implementations):&lt;/p>
&lt;pre>&lt;code class="language-csharp">services.AddScoped&amp;lt;IOrderFacade, OrderFacade&amp;gt;();
&lt;/code>&lt;/pre>
&lt;p>The facade itself can have dependencies injected, and it can be injected into controllers, other services, or anywhere else that needs it.&lt;/p>
&lt;h2 id="testing-with-facades">Testing with Facades&lt;/h2>
&lt;p>Facades can make testing easier or harder depending on how you use them.&lt;/p>
&lt;p>&lt;strong>Testing the facade itself&lt;/strong>: You mock the subsystem services and verify the facade coordinates them correctly.&lt;/p>
&lt;pre>&lt;code class="language-csharp">[Fact]
public async Task PlaceOrder_WhenInventoryUnavailable_ReturnsFailure()
{
var inventoryService = new Mock&amp;lt;IInventoryService&amp;gt;();
inventoryService
.Setup(x =&amp;gt; x.CheckAvailability(It.IsAny&amp;lt;List&amp;lt;Item&amp;gt;&amp;gt;()))
.ReturnsAsync(new InventoryResult { AllAvailable = false });
var facade = new OrderFacade(
inventoryService.Object,
Mock.Of&amp;lt;IPricingService&amp;gt;(),
Mock.Of&amp;lt;IDiscountService&amp;gt;(),
Mock.Of&amp;lt;IPaymentService&amp;gt;(),
Mock.Of&amp;lt;IOrderService&amp;gt;(),
Mock.Of&amp;lt;IEmailService&amp;gt;());
var result = await facade.PlaceOrder(new OrderRequest());
Assert.False(result.IsSuccess);
Assert.Equal(&amp;quot;Some items are out of stock&amp;quot;, result.Error);
}
&lt;/code>&lt;/pre>
&lt;p>&lt;strong>Testing consumers of the facade&lt;/strong>: You mock just the facade, not all the subsystem services. This is much simpler.&lt;/p>
&lt;pre>&lt;code class="language-csharp">[Fact]
public async Task PlaceOrder_WhenSuccessful_ReturnsOk()
{
var facade = new Mock&amp;lt;IOrderFacade&amp;gt;();
facade
.Setup(x =&amp;gt; x.PlaceOrder(It.IsAny&amp;lt;OrderRequest&amp;gt;()))
.ReturnsAsync(OrderResult.Success(new Order()));
var controller = new OrderController(facade.Object);
var result = await controller.PlaceOrder(new OrderRequest());
Assert.IsType&amp;lt;OkObjectResult&amp;gt;(result);
}
&lt;/code>&lt;/pre>
&lt;p>This is one of the main benefits. Without the facade, testing the controller would require mocking six services.&lt;/p>
&lt;h2 id="common-pitfalls-and-code-smells">Common Pitfalls and Code Smells&lt;/h2>
&lt;p>&lt;strong>Facades that do too much&lt;/strong>: A facade should simplify, not become a dumping ground. If your facade has 50 methods, it&amp;rsquo;s probably doing too much. Consider splitting it into multiple focused facades.&lt;/p>
&lt;p>&lt;strong>Facades that add business logic&lt;/strong>: A facade should coordinate, not make decisions. If you&amp;rsquo;re adding validation rules or business logic to the facade, that logic probably belongs in a domain service or the subsystem itself.&lt;/p>
&lt;p>&lt;strong>Facades that expose subsystem details&lt;/strong>: If the facade&amp;rsquo;s return types or parameters leak internal types from the subsystem, you haven&amp;rsquo;t really hidden the complexity. Define clean DTOs or result types for the facade&amp;rsquo;s API.&lt;/p>
&lt;p>&lt;strong>Too many layers of facades&lt;/strong>: If you have a facade that calls a facade that calls a facade, you&amp;rsquo;ve created indirection without value. Keep it simple.&lt;/p>
&lt;p>&lt;strong>Skipping the facade for &amp;ldquo;just this one call&amp;rdquo;&lt;/strong>: If some code bypasses the facade and calls the subsystem directly, you lose the benefits of centralization. Be consistent.&lt;/p>
&lt;h2 id="when-not-to-use-a-facade">When Not to Use a Facade&lt;/h2>
&lt;p>&lt;strong>Simple subsystems&lt;/strong>: If the subsystem is already easy to use, a facade adds indirection without benefit.&lt;/p>
&lt;p>&lt;strong>When callers need fine-grained control&lt;/strong>: If different callers need to use the subsystem in different ways, a facade that forces one workflow might be too restrictive.&lt;/p>
&lt;p>&lt;strong>Performance-critical paths&lt;/strong>: Each layer adds a small overhead. In most cases this doesn&amp;rsquo;t matter, but if you&amp;rsquo;re in a tight loop, measure before adding abstractions.&lt;/p>
&lt;p>&lt;strong>When it&amp;rsquo;s really just one service&lt;/strong>: If your &amp;ldquo;facade&amp;rdquo; wraps a single service and just forwards calls, it&amp;rsquo;s not adding value. A facade makes sense when coordinating multiple things.&lt;/p>
&lt;h2 id="practical-guidelines">Practical Guidelines&lt;/h2>
&lt;p>A few things to keep in mind:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Name facades after what they do, not what they wrap.&lt;/strong> &lt;code>OrderFacade&lt;/code> or &lt;code>OrderingService&lt;/code> is better than &lt;code>OrderSubsystemWrapper&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Keep the facade&amp;rsquo;s API focused.&lt;/strong> It should expose the operations callers actually need, not every possible combination of subsystem calls.&lt;/li>
&lt;li>&lt;strong>Don&amp;rsquo;t let the facade become a god class.&lt;/strong> If it&amp;rsquo;s growing too large, split it by use case or domain area.&lt;/li>
&lt;li>&lt;strong>The subsystem should still work without the facade.&lt;/strong> The facade is a convenience, not a requirement. Other parts of the system might still use the subsystem directly if they need to.&lt;/li>
&lt;li>&lt;strong>Consider using an interface for the facade.&lt;/strong> This makes testing easier and allows for alternative implementations if needed.&lt;/li>
&lt;/ul>
&lt;p>The Facade pattern is a straightforward way to tame complexity. It gives callers a simple interface while keeping the messy coordination logic in one place. Use it when you have a complex subsystem that multiple parts of your application need to use, and you want to make their lives easier.&lt;/p></description></item></channel></rss>