Eine Fassade bietet Aufrufern eine kleine, zweckorientierte Schnittstelle zu einem komplexeren Subsystem. Sie verbirgt die Orchestrierung, lässt jedoch die zugrunde liegende Arbeit weiterhin wirksam im Hintergrund ablaufen.
Ohne eine Fassade muss jeder Client möglicherweise wissen, in welcher Reihenfolge Codecs, Puffer, Reader und Writer aufgerufen werden:
const video = new VideoFile('movie.ogg');
const codec = new OggCodec();
const buffer = new Buffer();
buffer.extract(video, codec);
buffer.convert(new MPEG4AudioCodec());
Ändert sich die Reihenfolge, müssen viele Clients angepasst werden, was zu einem aufwändigen und fehleranfälligen Prozess werden kann. Jeder einzelne Aufruf muss dann an den neuen Ablauf angepasst werden, sonst bricht die gesamte Verarbeitungskette zusammen.
Die Fassade stellt den Anwendungsfall bereit, während sich das Subsystem intern weiterentwickeln kann. Dies bedeutet, dass Änderungen innerhalb des Subsystems keine Auswirkungen auf Clients haben, die die Fassade nutzen, was den Systemeigenen Widerstand gegen Veränderungen erhöht.
Eine Fassade bietet meist eine schmalere Schnittstelle; sie ist nicht einfach ein umbenannter Proxy oder Adapter. Stattdessen bietet sie eine vereinfachte Schnittstelle, die die Komplexität des Subsystems abstrahiert.
Fassade und verwandte Muster
| Muster | Hauptzweck |
|---|---|
| Fassade | Zugriff auf ein Subsystem vereinfachen |
| Adapter | Eine inkompatible Schnittstelle nutzbar machen |
| Mediator | Kommunikation zwischen Partnerobjekten koordinieren |
| Proxy | Zugriff kontrollieren und eine zielähnliche Schnittstelle bewahren |
Sie ist also mehr als ein bloßer Proxy oder Adapter; sie fasst die Komplexität des Subsystems in einer klaren, reduzierten API zusammen.
Wo Fassaden helfen
Eine Fassade kann eine Bibliothek, ein Legacy‑Subsystem oder einen Anwendungsfall wie den Checkout kapseln:
class OrderFacade {
constructor(
private inventory: InventoryService,
private payments: PaymentService,
private orders: OrderRepository,
) {}
async createOrder(customerId: string, items: OrderItem[]) {
await this.inventory.reserve(items);
const payment = await this payments.charge(customerId, items);
const order = new Order(customerId, items, payment.id);
await this.orders.save(order);
return order;
}
}
Controllers rufen die Fassade des Anwendungsfalls auf, statt alle Abhängigkeiten selbst zu koordinieren. Dies reduziert die Komplexität und macht den Code leichter zu verwalten; ein Controller muss nun nur noch den Eingang verarbeiten und das Ergebnis zurückliefern, während die gesamte Geschäftslogik in der Fassade gekapselt ist. Dadurch lässt sich jeder Controller leichter testen, weil man die Fassade mocken kann.
Gestaltungsregeln
- Ein zu breites Spektrum führt schnell zu unübersichtlichen Abhängigkeiten.
- Orchestrierung über Domänendienste. Die eigentlichen Geschäftsregeln bleiben in dedizierten Services; die Fassade koordiniert lediglich deren Aufruf. So bleibt die fachliche Logik dort, wo sie hingehört, und die Fassade bleibt schlank.
- Abstraktionen verwenden und Kollaboratoren injizieren. Durch Interfaces bleibt die Fassade testbar und lässt sich leicht austauschen. Im Test kann ein Mock‑Interface eingespeist werden, ohne das reale Service‑Gerüst zu starten.
- Eine gut gestaltete Fassade liefert ein Ergebnis, das sofort weiterverwendet werden kann, ohne dass der Client weitere Details kennen muss.
Eine Fassade bringt wenig, wenn das Subsystem bereits klein ist, Aufrufer fast alle Low‑Level‑Operationen benötigen oder die Fassade nur Methoden einzeln weiterreicht. In solchen Fällen fügt die zusätzliche Schicht lediglich Overhead hinzu, weil jeder Aufruf lediglich an das zugrundeliegende Objekt delegiert wird, ohne Mehrwert zu schaffen. Dann entsteht eher ein Wartungsburden als ein Schutzmechanismus.
Fazit
Fassaden kapseln Komplexität, beseitigen sie aber nicht. Sie verlagern die Komplexität in einen klar definierten Ort, sodass andere Teile des Systems sie nicht mehr direkt tragen müssen. Eine Fassade einsetzen, sobald ein stabiler Anwendungsfall Aufrufer vor Subsystemdetails und internen Änderungen schützen kann. Dieser Ansatz vereinfacht nicht nur den Client‑Code, sondern stärkt auch die Wartbarkeit und Anpassbarkeit des Gesamtsystems.

Comments (0)
Please sign in to leave a comment