Taktisches Frontend-Design
Frontend-Architektur scheitert selten daran, dass niemand die richtigen Begriffe kennt.
ViewModel. Store. Mapper. Command. Query. Anti-Corruption Layer. Feature Boundary. Event.
Die Begriffe sind schnell erklärt.
Schwieriger ist die nächste Frage:
Wo liegt der Code?
Nicht im Architekturdiagramm. Nicht im Konferenzraum. Nicht im Blogpost.
Sondern konkret im Projekt:
- Welche Datei lädt Daten?
- Welche Datei mappt DTOs?
- Welche Datei kennt das ViewModel?
- Welche Datei startet einen Command?
- Welche Datei zeigt einen Toast?
- Welche Datei entscheidet über Navigation?
- Welche Datei darf einen Store neu laden?
- Und was davon gehört auf keinen Fall in die Komponente?
Diese Rubrik heißt Taktisches Frontend-Design, weil sie genau dort ansetzt.
Nicht bei der großen Architekturvision.
Sondern beim Schnitt im Code.
Nicht noch ein Pattern-Katalog
Abschnitt betitelt „Nicht noch ein Pattern-Katalog“Diese Rubrik erklärt nicht noch einmal, warum ViewModels, Stores, Anti-Corruption Layer oder Events sinnvoll sein können.
Dafür gibt es bereits Grundlagenartikel:
- ViewModel Aggregation beschreibt, warum ein ViewModel eine bewusste UI-Entscheidung ist und kein umbenanntes Backend-DTO.
- Event-driven Projection beschreibt, warum UI-Zustand als Projektion aus Ereignissen verstanden werden kann und nicht als beliebig mutierbare Datenkiste.
- Anti-Corruption Layer beschreibt, warum fremde Modelle nicht ungefiltert durch das Frontend wandern sollten.
Diese Rubrik macht etwas anderes.
Sie nimmt diese Gedanken und fragt:
Wie sieht das als lauffähiger Code-Slice aus?
Patterns beschreiben den Gedanken.
Taktisches Frontend-Design zeigt den Schnitt.
Der eigentliche Schmerz
Abschnitt betitelt „Der eigentliche Schmerz“In vielen Frontends beginnt alles harmlos.
Eine Page-Komponente lädt Daten.
Dann kommt Loading dazu.
Dann Error Handling.
Dann ein Mapper.
Dann ein Toast.
Dann Navigation nach dem Speichern.
Dann ein Reload der Liste.
Dann ein Sonderfall.
Dann noch ein zweiter Sonderfall.
Irgendwann ist die Komponente kein UI-Baustein mehr, sondern ein kleiner Use-Case-Orchestrator mit Template.
Oder der Store wird zum Sammelbecken für alles:
- HTTP-Aufrufe
- Mapping
- Commands
- Query State
- Formularzustand
- Notifications
- Routing
- Reload-Logik
- fachliche Entscheidungen
- technische Seiteneffekte
Das funktioniert.
Bis es nicht mehr funktioniert.
Taktisches Frontend-Design versucht, diese Verantwortung wieder sichtbar zu machen.
Nicht durch mehr Abstraktion.
Sondern durch bewusstere Schnitte.
Was hier mit „taktisch“ gemeint ist
Abschnitt betitelt „Was hier mit „taktisch“ gemeint ist“Der Begriff ist bewusst von Domain-Driven Design inspiriert.
Im klassischen DDD geht es beim taktischen Design um konkrete Bausteine wie Entities, Value Objects, Aggregates, Repositories oder Domain Services.
Im Frontend ist die Lage anders.
Ein Angular-Frontend ist keine kleine Kopie des Backends. Es ist auch kein Ort, an dem man DDD-Begriffe mechanisch nachbaut, nur damit der Ordnerbaum fachlicher aussieht.
Trotzdem ist der Gedanke wertvoll:
Fachlichkeit braucht Formen im Code.
Für diese Rubrik heißt das:
- Ein Read Flow ist nicht einfach ein
GET. - Ein Create Flow ist nicht einfach ein
POST. - Ein ViewModel ist nicht einfach das DTO mit anderem Namen.
- Ein Command ist nicht einfach eine Store-Methode mit HTTP-Aufruf.
- Ein Toast ist kein Detail, das zufällig irgendwo nach dem Speichern erscheint.
- Routing ist kein Nebeneffekt, der im Button-Click-Handler versteckt werden muss.
Die Beispiele orientieren sich gedanklich an DDD im Frontend, unter anderem an Ansätzen, die Manfred Steyer im Angular-Umfeld geprägt hat.
Aber sie übernehmen diese Ansätze nicht als Dogma.
Sie nutzen sie als Werkzeugkasten.
Der technische Rahmen
Abschnitt betitelt „Der technische Rahmen“Die Code-Slices in dieser Rubrik orientieren sich an einem modernen Angular-Stack mit Angular 21 und NgRx 21.
Das ist keine zufällige Versionsnummer.
Die Rubrik soll nicht zeigen, wie man historische Angular-Anwendungen irgendwie weiter betreibt. Sie soll zeigen, wie man fachliche Frontend-Flows mit heutigen Mitteln organisieren kann:
- Standalone APIs
- Signals
- NgRx Signal Store
- moderne NgRx-Patterns
- funktionale Provider, Guards und Resolver, wo passend
- moderne Control-Flow-Syntax
- klare Feature-Grenzen
- explizite ViewModels
- getrennte Read- und Command-Flows
Trotzdem geht es hier nicht um Versionsmarketing.
Angular 21 und NgRx 21 setzen den Werkzeugkasten.
Die eigentliche Frage bleibt architektonisch:
Wo liegt Verantwortung?
Kontext entscheidet
Abschnitt betitelt „Kontext entscheidet“Kein Schnitt passt überall.
Ein dedizierter Read Store mit eigenem Mapper, ViewModel und Tests kann sehr sinnvoll sein, wenn fachliche Leseprojektionen komplex sind, mehrere Komponenten denselben Zustand konsumieren oder der Slice langfristig wachsen wird.
In einem kleinen, stabilen Backoffice-Dialog kann derselbe Schnitt Overengineering sein.
Diese Rubrik behauptet deshalb nicht:
„So macht man es richtig.“
Sondern:
„So kann man es schneiden — und jetzt können wir konkret darüber reden.“
Relevant sind immer:
- Teamgröße und Erfahrung
- fachliche Komplexität
- erwartete Lebensdauer
- Änderungsdruck
- Teststrategie
- vorhandene Architektur
- Kosten der zusätzlichen Struktur
Architektur ist kein Selbstzweck.
Aber fehlende Struktur ist auch keine Einfachheit.
Geplante Code-Slices
Abschnitt betitelt „Geplante Code-Slices“CRUD-Slices
Abschnitt betitelt „CRUD-Slices“CRUD klingt technisch.
Im Frontend sind es aber meistens fachliche Flows mit Zustand, Entscheidungen und Seiteneffekten.
- Retrieve Slice: Daten laden ohne Komponentenlogik
- Create Slice: Schreiben als Command Flow
- Update Slice: Formularzustand ist kein DTO
- Delete Slice: Löschen ist eine fachliche Entscheidung
Global Events
Abschnitt betitelt „Global Events“Manche Reaktionen gehören nicht in die Komponente, die den Button enthält.
Ein erfolgreicher Command kann Notifications auslösen, Navigation starten oder Read Stores invalidieren. Die Frage ist nicht nur, dass das passiert, sondern wo diese Reaktion modelliert wird.
Reference Implementation
Abschnitt betitelt „Reference Implementation“Damit ein Schnitt im Team funktioniert, braucht er Wiedererkennbarkeit.
Deshalb geht es auch um Struktur, Namen und Tests.
Ein Gedanke zum Einstieg
Abschnitt betitelt „Ein Gedanke zum Einstieg“Frontend-Architektur wird oft an zwei Stellen unbrauchbar.
Zu abstrakt:
„Wir brauchen klare Grenzen.“
Stimmt.
Aber welche Datei ziehe ich wohin?
Zu technisch:
„Wir nutzen NgRx Signal Store mit withMethods und withHooks.“
Gut.
Aber welche Verantwortung bekommt dieser Store?
Diese Rubrik sucht die Mitte.
Konkret genug, um Dateien anzulegen.
Abstrakt genug, um den Schnitt zu verstehen.
Kritisierbar genug, um im echten Projekt angepasst zu werden.