Composite-Korridore und Primärquellen in Kap. 2 ehrlich kalibriert; DoD/Verify, Surfaces und Anhänge in 04–16 geschärft; eBook 119 S. neu gebaut.
9.4 KiB
8. Vertikale Slices über den Stack
Kern: Ein Slice ist eine nutzbare Scheibe UI ↔ API ↔ Daten — nicht „erst alle DTOs, dann alle Services, dann irgendwann UI“.
Die Slice-Idee kommt aus dem Theorie-Schwesterbuch (Coding Agents in der Praxis, Kap. 8): Komplexität begrenzen, reviewbar bleiben, DoD am echten Outcome messen. Hier die Enterprise-Übersetzung für Angular + Spring Boot (oder Quarkus) mit Agents — wo Multi-Repo, Contracts und getrennte Sessions die Regel sind, nicht die Ausnahme.
Kapitel 5–7 haben die Idiome pro Schicht. Dieses Kapitel verbindet sie: ein Use-Case, dünn, end-to-end, mit messbarer Fertigstellung. Ohne diesen Schnitt multiplizieren Agents Fehler über den Stack — und Review wird zur Archäologie.
8.1 Warum horizontal teuer wird
Typischer Auftrag im Backlog: „Customer-Domain vorbereiten.“ Der Agent modelliert Entities, DTOs, Mapper, leere Services, Angular-Modelle — Wochen später fehlt die eine Liste, die der Nutzer braucht. Jede Schicht ist „fast fertig“, nichts ist nutzbar, und der Context jeder Session war voller spekulativer Typen.
Du merkst den horizontalen Big-Bang daran, dass:
- der Diff viele Dateien hat, aber kein einzelnes grünes Outcome,
- Frontend und Backend parallel raten, was der Contract werden könnte,
- Review den Auftrag nicht in einem Satz wiedergeben kann.
Vertikal heißt: eine nutzbare Scheibe zuerst. Komplexitätsbudget ist Review-Budget (Kap. 2.2.4): was du im Diff nicht in endlicher Zeit verstehst, war zu groß — auch wenn CI irgendwann grün war.
8.2 Schnitt: von Outcome zu Schritten
Formuliere den Slice vom Nutzer her, nicht vom Layer her.
Beispiel-Outcome: „Benutzer kann X anlegen und in der Liste sehen.“
Sinnvolle Reihenfolge (anpassen, nicht dogmatisieren):
- Contract — OpenAPI (oder bestehendes Endpoint-Pattern) erweitern bzw. festnageln
- Backend — Handler/Resource + scoped Test (+ Persistenz nur soweit nötig)
- Angular — Feature (Liste/Form) + Unit-Test gegen euer HTTP-Muster
- Tight-Loop pro Schicht nach sinnvollen Patches; Slice-DoD wenn Outcome baubar und zum Auftrag passt
- Heavy — optional e2e / Integration nach Policy (Kap. 9)
In Multi-Repo sind 2 und 3 oft getrennte Sessions mit Handoff (Kap. 2.5): Backend grün und Contract gemerged, dann Frontend-Session mit Contract-Pfad in den Dateien mit Vorrang. Eine Session über drei Repos ist Context-Selbstmord.
Task-Formel (Kap. 2.4) bleibt der Kleber:
Outcome: …
Nebenbedingungen: bestehende Patterns, Security, OpenAPI
Ausschlüsse: kein Payment-Refactor, keine neuen NgModules, kein Native
DoD: Backend-Command && Frontend-Command (+ Contract aktualisiert)
Vorlage: templates/task-prompt-fullstack-slice.md. Skill: templates/skill-fullstack-slice/.
| Do this | Avoid that |
|---|---|
| Ein Outcome, ein Slice, eine DoD | „Domain fertig machen“ ohne UI-Nutzen |
| Contract vor oder mit dem ersten schreibenden Patch | FE und BE raten parallel ohne Repo-Wahrheit |
| Handoff an Slice-Grenze FE/BE | Eine Session über Monorepo und drei Services |
8.3 Contracts als Kleber
In Multi-Repos (und oft im Monorepo) ist OpenAPI oder ein äquivalenter Contract die gemeinsame Wahrheit. Agents bekommen den Contract im Repo, nicht nur als Chat-Paste, der nach Compact verschwindet.
Mini-Artefakt (imitierbar): Enum und Endpoint im Contract, nicht nur in der Tabelle:
# packages/contracts/openapi/orders.yaml (Auszug)
components:
schemas:
OrderStatus:
type: string
enum: [NEW, CONFIRMED, SHIPPED]
Order:
type: object
required: [id, status]
properties:
id: { type: integer, format: int64 }
status: { $ref: '#/components/schemas/OrderStatus' }
paths:
/api/orders/{id}:
get:
operationId: getOrder
# …
Handoff an der FE/BE-Grenze (Vorlage: templates/handoff-stack.md):
Contract: packages/contracts/openapi/orders.yaml (Order.status enum)
Endpoint: GET /api/orders/{id} — BE-Verify: ./mvnw -q -Dtest=OrderControllerTest test
Nicht gebaut: Checkout, Mail, Payment-Refactor
FE-nächste Session: List-Component + Typ/Client aus Contract; kein parallel erfundenes Interface
FE-Konsum — eine erlaubte Wahrheit (Policy im Repo, nicht im Chat):
| Erlaubt (eine wählen und pinnen) | Avoid |
|---|---|
| OpenAPI-Source → generierter Client/Types | parallel erfundene FE-Interfaces „nur fürs UI“ |
| bewusst gepflegte FE-Types mit DoD „bei API-Change mitziehen“ | Mock-Welt über Wochen ohne Contract-Update |
| Rolle | Contract im Repo | Nur Chat / Wiki |
|---|---|---|
| Backend-Session | spezifiziert Request/Response, generiert Client optional | Agent erfindet Felder |
| Frontend-Session | liest Operation + Schema | mockt eine Parallelwelt |
| Review | Diff gegen spezifizierte API | „fühlt sich an wie REST“ |
| Teach-back | Generator/Pipeline als eine Wahrheit | drei Versionen der Wahrheit |
Contract-Drift ist die stille Variante des horizontalen Big-Bangs: Backend ändert ein Feld, Frontend-Session von gestern kennt es nicht, Integration scheitert im Heavy. Gegenmittel: Contract-Pfad in beiden AGENTS.md; DoD-Zeile „Contract aktualisiert bei API-Change“; nach API-Merge kurze Frontend-Session statt „machen wir später“.
| Do this | Avoid that |
|---|---|
| OpenAPI (o. Ä.) versioniert im Repo | „Schau in Confluence / frag Team X“ |
| Contract in Dateien mit Vorrang | Nur generiertes Artefakt ohne Source |
| Breaking Changes bewusst + Handoff | Stille Feld-Umbenennungen im Agent-Flow |
8.4 Anti-Patterns
| Anti-Pattern | Was passiert | Besser |
|---|---|---|
| Horizontaler Layer-Big-Bang | viele Dateien, kein nutzbares Outcome | ein Use-Case end-to-end dünn |
| Frontend-Mock-Welt über Wochen | UI-Polish auf erfundener API | Contract + echter Endpoint früh |
| „Erst die ganze Domain modellieren“ | spekulative Typen, Context-Müll | Persistenz nur für diesen Slice |
| Ein Agent, alle Repos, ein Thread | Rot, falsche Module, Ownership-Wirrwarr | Session pro Seite + Handoff |
| DoD nur „compiles“ | falsches Grün | scoped Tests FE und BE |
| Slice ohne Ausschlüsse | Scope-Creep über Nachbar-Domains | Task-Template mit Ausschlüssen |
Diese Liste ist die Checkliste vor dem Prompt — nicht die Moral danach.
8.5 Mini-Walkthrough (Angular + Spring)
Outcome: Bestellstatus in der Liste anzeigen (Anschluss an Kap. 2 und 5–6).
- Plan: nur Anzeige + Mapping; kein Checkout, kein Payment, keine neuen Module.
- Contract:
Order-Schema umstatus(enum) erweitern, falls noch nicht spezifiziert. - Backend-Session (Tight-Loop): Controller/DTO +
OrderControllerTest— Commands aus Package-AGENTS.md(Maven-Muster:./mvnw -Dtest=OrderControllerTest test; Gradle:./gradlew test --tests …OrderControllerTest); Security-Pattern beibehalten. - Handoff: Contract-Pfad, Endpoint, was nicht gebaut wurde.
- Frontend-Session (Tight-Loop): List-Component + ggf. Typ aus Contract/Client;
npm test -- --include=order-list+ Lint. - Slice-DoD: Diff matcht Auftrag; Tight grün + baubar (Maven
package/ Gradlebuild -x testnach Repo-Wahrheit); Contract konsistent; kein Drive-by. - Heavy (optional): e2e oder manuelle Checkliste nur wenn Policy es verlangt.
Dasselbe Muster mit Quarkus: Resource + @QuarkusTest statt Spring-Slice; Idiom aus Kap. 7, Schnitt aus diesem Kapitel.
8.6 Feature-Flags und Strangler (kurz)
Manchmal ist der Slice hinter einem Flag oder nur auf einer Legacy-Route live. Das ändert nicht den vertikalen Schnitt — es ändert nur Deploy- und Review-Ampel (oft gelb/rot, Kap. 12). Strangler-Migration mit engen Slices: Kap. 11. Hier zählt: auch Migrationsarbeit in nutzbare Scheiben schneiden, nicht „erst das neue Domänenmodell fertig“.
Key Takeaways
- End-to-end dünn schneiden; DoD pro Slice — nicht pro Layer.
- Contract im Repo hält Front- und Backend-Sessions zusammen.
- Horizontale Monster-Tasks multiplizieren Agent-Fehler und Review-Kosten.
- Multi-Repo: Session-Grenzen + Handoff sind Teil des Slices, nicht Overhead.
- Task-Formel (Outcome, Nebenbedingungen, Ausschlüsse, DoD) ist der operative Kleber.
Praktische nächste Schritte
- Nächstes Feature als vertikalen Slice formulieren — Vorlage
templates/task-prompt-fullstack-slice.md. - Contract-Datei im Repo verlinken (beide Seiten: FE- und BE-
AGENTS.md). - Backend- und Frontend-Verify als Tight-Loop getrennt in die DoD; Integration/e2e als Heavy (Kap. 9).
- Einmal bewusst Handoff an der FE/BE-Grenze fahren (
templates/handoff-stack.md). - Danach Kap. 9 — Kanon Tight-Loop · Slice-DoD · Heavy so schärfen, dass der Slice prüfbar bleibt.
Ein guter Slice fühlt sich klein an und ist trotzdem fertig im Sinne des Nutzers. Das nächste Kapitel macht aus „fertig“ Exit-Codes — sonst bleibt der vertikale Schnitt eine schöne Zeichnung.

