Playbook

Von Schichten zu Features: Warum entstand Vertical Slice? (Von Schichten Zu Features Warum Vertical Slice Entstand)

Warum verlangsamt eine Schichtenarchitektur Veränderung, wenn ein System wächst? Ein Architekturleitfaden zu Vertical Slice als Entscheidung über Feature…

Vertical Slice — Feature-orientiertes Engineering

Teil 1 von 4

A software feature flowing from request to behaviour, data, and tests in one vertical slice

Geben wir CRUD und Schichten nicht zuerst die Schuld

Eine Schichtenarchitektur ist für viele kleine und mittlere Systeme ein guter Start. Die Trennung von Controller, Application Service, Repository und Datenzugriff gibt dem Team eine gemeinsame technische Sprache. Das Problem ist nicht die Existenz von Schichten. Es beginnt, wenn eine Nutzeranforderung über alle Schichten verteilt wird und jede Änderung zu Koordinationsarbeit wird.

Eine kleine Anforderung kommt hinzu: einer Bestellung eine Liefernotiz geben.

Controller
  → Request / DTO
  → Service
  → Validator
  → Repository
  → Mapping
  → Test Doubles
  → Tests

Acht Dateien zu ändern ist nicht automatisch falsch. Wenn sie aber für dasselbe Verhalten, gleichzeitig und vom selben Team geändert werden, beschreibt das Dateisystem technische Rollen statt Business Value. Vertical Slice ist eine pragmatische Antwort auf diese Reibung.

Begriffe bei der ersten Verwendung

📦 Vertical Slice
Eine End-to-End-Feature-Einheit, die eine Nutzerintention vom Request über Persistenz bis zu Tests in einer Grenze hält.

📦 Locality of Behaviour
Code, der zum Verstehen oder Ändern eines Verhaltens nötig ist, bleibt physisch nah beieinander.

📦 Temporal DRY
Eine DRY-Perspektive, die fragt, ob ähnlicher Code über die Zeit aus demselben Grund verändert wird.

📦 Wrong Abstraction
Eine Abstraktion, die nur wegen Wiederholung geteilt wird und später unterschiedliche Bedürfnisse koppelt.

Vertical Slice verbietet keine Schichten. Die technische Trennung bleibt innerhalb des Features; Nutzerintention, Business Rules und Ownership bestimmen seine äußere Grenze.

Die Geschichte: Wann Schichten Delivery verlangsamen

Am ersten Tag ist CreateOrder klein. Ein Controller, ein Service und ein Repository wirken ausreichend. Dann kommen Bestandsprüfung, Kampagnenregeln, Lieferpräferenzen und Audit Records hinzu. Wenn jedes Feature in denselben OrderService gelangt, wird die riskanteste Datei zur am stärksten geteilten Datei.

Neues Feature
  → berührt Shared Service
  → beeinflusst unabhängige Tests
  → wartet auf ein fremdes Release

CRUD ist nicht kaputt. Die Verantwortung des Modells und der Application Layer hat sich verändert. Vertical Slice fragt: Welche Business-Intention lässt dieses Verhalten ändern?

Horizontale und vertikale Organisation

Kriterium Schichtenorientiert Feature-orientiert
Organisationsachse Technische Rolle Nutzerintention / Feature
Veränderungseinheit Dateien in mehreren Schichten Eine Feature-Grenze
Code Sharing Frühe Shared-Service-Tendenz Bewiesene Gemeinsamkeit
Navigation Controller → Service → Repository Feature → Request → Handler → Test
Fehlerwirkung Kann sich über Shared Layers ausbreiten Bleibt an der Feature-Grenze sichtbarer
❌ Controllers / Services / Repositories
    → OrdersController
    → OrderService
    → OrderRepository

✓ Features / Orders / CreateOrder
    → Request
    → Validator
    → Handler
    → Response
    → Tests

Das ist nicht nur eine Namenswahl. Es verändert die Kosten, eine Änderung zu finden, zu verstehen, zu testen und zurückzunehmen. Selbst wenn die Suche über n Dateien im Worst Case O(n) bleibt, verringert Colocation irrelevante Navigation und mentale Kontextwechsel.

Screaming Architecture: Was soll ein Verzeichnis sagen?

Wenn ein Projekt mit Controllers, Services und Infrastructure beginnt, erzählt es von Werkzeugen. Beginnt es mit Orders, Catalog, Billing und Returns, erzählt es vom Geschäft. Architektur sollte Produktintention lauter zeigen als das Framework.

Wer CancelOrder ändert, sollte Handler, Validation, Response und Tests zusammen finden. Ein Feature-Ordner ist aber kein kleiner Monolith mit allem als public. Sein Einstiegspunkt bleibt explizit; die Implementierungsdetails bleiben verborgen.

Kohäsion, Encapsulation und strategische Duplikation

Ein Slice sollte die interne Implementierung eines anderen Slice nicht kennen. Verhalten wird nur geteilt, wenn es stabil ist und sich in mehreren unabhängigen Fällen aus demselben Grund ändert. Sonst wird ein Shared-Ordner zu einer neuen Schicht mit unsichtbaren Grenzen.

CreateOrder
  → fordert das Order Aggregate zu einer Aktion auf
  → schließt eine lokale Transaction ab
  → erzeugt eine Response

CancelOrder
  → wendet eigene Regeln an
  → ruft nicht den CreateOrder-Handler auf

Duplikation kann der richtige Preis sein. Wenn zwei ähnliche Codestellen wegen verschiedener Business-Entscheidungen verändert werden, kann eine frühe Zusammenführung jede spätere Änderung auf O(k) abhängige Features ausweiten.

Migrationssignale

Nur modern aussehen zu wollen genügt nicht. Die Investition lohnt sich, wenn mehrere Signale gemeinsam auftreten:

  1. Eine einfache Anforderung verlangt wiederholt Änderungen in vielen Schichten.
  2. Kleine Änderungen in Shared Services brechen unabhängige Feature-Tests.
  3. Mock-lastige Tests schützen Aufrufreihenfolgen statt Verhalten.
  4. Das Team findet nur schwer, wo eine Business Rule lebt.
  5. Feature Owner und Delivery-Rhythmen haben sich auseinanderentwickelt.

Diese Grenzen sollten nicht nur in Dokumentation stehen. Architekturtests können in .NET verhindern, dass ein Feature von den internen Details eines anderen abhängt. Die Regel kostet O(dependency)-Scanning beim Build oder Test; ihr Nutzen ist eine sichtbare Verletzung vor Production.

Beziehung zu DDD und CQRS

Vertical Slice organisiert die Anwendung. DDD erklärt, wo Business Language und Rules leben. CQRS kann den Command- und Query-Flow eines Use Case trennen. Sie sind keine Konkurrenten, sondern unterschiedliche Ebenen architektonischer Entscheidungen.

Feature Boundary    → Vertical Slice
Consistency Rule    → DDD Aggregate
Read / Write Flow   → CQRS
Deployment Unit     → Modular Monolith oder Microservice

Eine Feature-Grenze zuerst im Modular Monolith zu beweisen, testet die Unabhängigkeitsannahme, ohne Microservice-Kosten zu früh zu zahlen.

Assoziationen, die falsche Sicherheit erzeugen

❌ Vertical Slice = umbenannte Ordner
✓ Es hält Nutzerintention, Verhalten und Ownership in einer Grenze.

❌ DRY = jede ähnliche Zeile teilen
✓ Code teilen, der sich aus demselben Grund ändert.

❌ Handler = jede Business Rule
✓ Der Handler orchestriert; Domain Rules leben im passenden Modell.

❌ Vertical Slice = Microservice
✓ Zuerst eine Application Boundary, die im Modular Monolith bewiesen werden kann.

❌ Shared = kostenlose Wiederverwendung
✓ Shared Code bringt auch Versionierungs- und Koordinationskosten.

Entscheidungs-Checkliste

  1. Ändert sich dieser Code wegen derselben Nutzerintention?
  2. Sind Request, Validation, Handler, Response und Tests eines Features zusammen auffindbar?
  3. Kann ich die Anforderung erfüllen, ohne auf eine interne Klasse eines anderen Features zuzugreifen?
  4. Ändert sich diese Shared Abstraction in mindestens drei unabhängigen Fällen aus demselben Grund?
  5. Sind Aggregate Rules von Application Orchestration getrennt?
  6. Wird die Feature-Grenze im Modular Monolith durch Architekturtests geschützt?
  7. Sind Fehlerwirkung, Testabdeckung und Rollback nach einer Änderung sichtbar?

Das Ziel sind nicht mehr Ordner. Es ist eine kleinere Code- und Entscheidungsfläche für die Änderung eines Verhaltens.

Was bleiben sollte

  1. Eine Schichtenarchitektur ist nicht schlecht; Koordinationskosten wachsen, wenn eine Änderung über Schichten verteilt wird.
  2. Vertical Slice gruppiert Code um Nutzerintention und Verhalten statt um technische Rollen.
  3. Strategische Duplikation kann weniger kosten als eine falsche Abstraktion.
  4. Vertical Slice ist eine Entscheidung zur Anwendungsorganisation, die mit DDD, CQRS und einem Modular Monolith zusammenarbeitet.

Vertical Slice bedeutet nicht, Dateien vertikal zu stapeln. Es bedeutet, die Wirkung einer Veränderung in der richtigen Feature-Grenze zu halten.

Im nächsten Kapitel sehen wir, wie ein Slice von innen funktioniert: Request, Validation, Handler, Mapping und Tests.

FAQ

Häufige Fragen

Was ist Vertical Slice?

Eine End-to-End-Feature-Einheit, die eine Nutzerintention vom Request über Persistenz bis zu Tests in einer Grenze hält.

Was ist Locality of Behaviour?

Code, der zum Verstehen oder Ändern eines Verhaltens nötig ist, bleibt physisch nah beieinander.

Stimmt es, dass „Vertical Slice = umbenannte Ordner“?

Es hält Nutzerintention, Verhalten und Ownership in einer Grenze.

Was legt dieser Teil fest?

Acht Dateien zu ändern ist nicht automatisch falsch. Wenn sie aber für dasselbe Verhalten, gleichzeitig und vom selben Team geändert werden, beschreibt das Dateisystem technische Rollen statt Business Value. Vertical Slice ist eine pragmatische Antwort auf diese Reibung. Eine Schichtenarchitektur ist nicht schlecht; Koordinationskosten wachsen, wenn eine Änderung über Schichten verteilt wird. Eine Schichtenarchitektur ist für viele kleine und mittlere Systeme ein guter Start. Die Trennung von Controller, Application Service, Repository und Datenzugriff gibt dem Team eine gemeinsame technische Sprache. Das Problem ist nicht die Existenz von Schichten. Es beginnt, wenn eine Nutzeranforderung über alle Schichten verteilt wird und jede Änderung zu Koordinationsarbeit wird.

Gelernte Engineering-Prinzipien

  • Code-Organisation soll den Grund für Veränderung vor technischen Schichten sichtbar machen.
  • Locality of Behaviour ist eine Architekturentscheidung, die Navigations- und Testkosten senkt.
  • Sharing ist nur wertvoll, wenn der Grund für Veränderung geteilt wird; sonst kann Duplikation sicherer sein.

Weiterlesen

Weiterlesen

Nachster Teil der Serie

Verwandte Beitrage

Verwandte Beitrage

Paylaş