Vertical Slice Architecture - Eine Einführung

Von: Thomas Bayer
Datum: 15. Juli 2024

Die Vertical Slice Architecture ermöglicht es, Use Case gesteuert vorzugehen und fachliche Anforderungen effizient umzusetzen. Die Architektur erfreut sich zunehmender Beliebtheit und stellt eine einfachere Alternative zur Hexagonal-, Onion und Clean Architecture dar.

Im Artikel wird die Architektur vorgestellt und mit der Schichtenarchitektur und den Microservices verglichen.


Abbildung : Vertical Slice Architecture

Vertical Slice Architecture - Eine Einführung

Entworfen wurde die Softwarearchitektur von Jimmy Bogard, dem Entwickler des MediatoR-Frameworks. Bogard stieß bei der der Onion-Architektur auf diverse Schwierigkeiten und begann daraufhin, seinen Code anders zu organisieren.


Abbildung : Jimmy Bogard, Erfinder der Vertical Slice Architecture

Im Folgenden werfen wir einen genaueren Blick auf die Probleme, die zur Entwicklung der Vertical Slice Architecture führten.

1. Herausforderungen der traditionellen Architekturen

Die Hexagonale-, die Onion- und die Clean-Architecture stellen Weiterentwicklungen der klassischen Schichtenarchitektur dar. Allerdings sind alle drei Architekturen von ähnlichen Problemen betroffen.


Abbildung : Varianten der Schichtenarchitektur: Hexagonal-, Onion- und Clean-Architecture

Angenommen, es soll eine Änderung an einer Anwendung vorgenommen werden. Die Anpassung der Benutzeroberfläche allein genügt in der Regel nicht, die Geschäftslogik und die Datenbank müssen ebenfalls entsprechend modifiziert werden.


Abbildung : Anpassung der einzelnen Schichten bei Änderungen

In großen Anwendungen werden die verschiedenen Schichten häufig von getrennten Teams entwickelt, die eine enge Abstimmung erfordern. Oftmals sind die Schichten in eigenen Code-Repositories organisiert, die bei jeder Änderung aktualisiert werden müssen.

Die Struktur der Abhängigkeiten ist meist komplexer als im Beispiel oben. Die Servicebeziehungen verlaufen oft unübersichtlich quer durch die Anwendung, was Veränderungen und Refactoring erheblich erschwert.


Abbildung : Komplexe Service Abhängigkeiten

Sowohl die Hexagonale- als auch die Clean-Architecture basieren auf Abstraktionen in Form von Schnittstellen, die bei Änderungen häufig angepasst werden müssen. Der betroffene Code verteilt sich dabei über mehrere Verzeichnisse und Projekte.


Abbildung : Verteilung der Dateien auf Ports und Adapter bei der hexagonalen Architektur

2. Die Vertical Slice Architecture

Bei der Vertical Slice Architecture wird der Code nicht in horizontalen Schichten organisiert, sondern in vertikalen Scheiben, den sogenannten Slices. Ein Slice durchläuft den gesamten Stack und bildet eine vollständige fachliche Funktion ab. Jedes Slice ist in sich geschlossen (self-contained), was bedeutet, dass es alle Komponenten enthält, die für die Umsetzung eines bestimmten Use Cases erforderlich sind. Änderungen können somit an nur einer Stelle vorgenommen werden.

Neue Funktionalitäten werden in zusätzlichen Slices implementiert, wodurch bestehender Code nicht geändert werden muss.


Abbildung : Organisation der Fachlichkeit in vertikalen Slices oder Features

Ein Slice kann von einem einzelnen Entwickler bearbeitet werden, ohne dass Absprachen mit anderen Teams erforderlich sind. Dies minimiert das Risiko, dass andere Funktionen beeinträchtigt werden.

Die Vertical Slice Architecture minimiert oder vermeidet die Kopplung zwischen den Slices und maximiert die Kohäsion, also den Zusammenhalt innerhalb eines Slices.

3. Aufbau eines Slices

Ein Feature in der Vertical Slice Architecture implementiert einen Use Case, der durch ein externes Ereignis ausgelöst wird. Ein Beispiel hierfür ist das Drücken eines Knopfes durch den Anwender, was eine POST-Anfrage an eine API sendet.


Abbildung : Aufbau eines Slices

Ein Controller nimmt diese Anfrage entgegen und erzeugt eine Nachricht, die dann an einen Mediator weitergeleitet wird. Der Mediator ist nicht zwingend erforderlich, wird jedoch häufig verwendet, um die Entkopplung zu unterstützen.

Der Mediator ermittelt einen passenden Handler, der die Anfrage verarbeiten kann. Dieser Handler führt die Geschäftslogik aus und greift auf ein Repository zu, um Änderungen in der Datenbank vorzunehmen.

Falls eine Antwort erforderlich ist, wird diese auf demselben Weg zurückgesendet.

Der Code für die vollständige Verarbeitung einer Anfrage wird in einer einzigen Datei abgelegt. Jede Anfrage stellt ein eigenes Slice dar und erhält eine separate Datei.

Verarbeitung von Anfragen

Die Verarbeitung von Anfragen findet in einem Handler statt. Der Controller erzeugt eine Nachricht, die entweder einen Befehl oder eine Abfrage darstellt. HTTP-POST- oder PUT-Methoden führen in der Regel zu Befehlen, während ein GET zu einer Abfrage wird. Der Mediator ermittelt den passenden Handler und übergibt diesem die Nachricht zur Verarbeitung. Der Handler führt daraufhin die Verarbeitung durch und erzeugt die entsprechende Ausgabe.


Abbildung : Verarbeitung einer Anfrage

Dieser Prozess folgt dem grundlegenden EVA-Prinzip (Eingabe, Verarbeitung, Ausgabe).

Der Controller ruft den Handler nicht direkt auf, sondern übergibt die Nachricht an den Mediator. Der Mediator stellt sicher, dass vor der Ausführung des Handlers Cross-Cutting Concerns, also übergreifende Aspekte, die nicht einem einzelnen Feature zugeordnet sind, berücksichtigt werden. Dazu gehören beispielsweise die Validierung oder Sicherheitsprüfungen.

4. Vergleich mit Microservices

Die Vertical Slice Architecture weist auf den ersten Blick Ähnlichkeiten mit der Microservices-Architektur auf, unterscheidet sich jedoch grundlegend in einigen Aspekten. Ein Microservice besitzt eine eigene Codebasis und kann unabhängig von anderen Services entwickelt, installiert, bereitgestellt und betrieben werden. Im Gegensatz dazu ist der Code eines Slices in der Vertical Slice Architecture zwar von dem anderer Slices getrennt, jedoch sind die einzelnen Features alle Teil eines einzigen Projekts und werden gemeinsam bereitgestellt und betrieben.


Abbildung : Vergleich der Deployment-Einheiten mit den Mircoservices

5. Code Sharing

Bei Microservices wird kein Code geteilt, und auf den ersten Blick könnte man annehmen, dass auch bei der Vertical Slice Architecture keine Codewiederverwendung stattfindet. Ein Slice bildet eine Funktion ab und sollte unabhängig von anderen Features sein. Jeder Use Case wird in einem separaten Feature implementiert.


Abbildung : Isolation der Features

Dennoch ist es möglich und üblich, Code zu teilen. Fachklassen können in einem Model gekapselt werden, das von mehreren Slices verwendet wird. Funktionalitäten, die keinem einzelnen Use Case zugeordnet werden können, lassen sich in einen Service auslagern. Beispiele hierfür sind Datumsberechnungen oder Utility-Funktionen.


Abbildung : Shared Services

Wenn jedoch immer mehr Code von Features in Services ausgelagert wird, nähert sich die Architektur im Extremfall wieder der Schichtenarchitektur an. Daher sollte sorgfältig abgewogen werden, welche Teile ausgelagert werden und in manchen Fällen doppelte Codefragmente akzeptiert werden.


Abbildung : Übergang von der Virtual Slice Architecture in eine Mehrschichtenarchitektur

6. Vergleich mit den Schichtenarchitekturen

Bei der Vertical Slice Architecture existieren keine Schichten, die in der gesamten Anwendung sichtbar sind. Die einzelnen Features werden jedoch häufig in Schichten gegliedert. Anzahl und Aufbau der Schichten können sich dabei von Slice zu Slice unterscheiden.


Abbildung : Schichten innerhalb der Slices

In der Schichtenarchitektur können UI- oder Datenbankkomponenten relativ einfach ausgetauscht werden. Allerdings stellt sich die Frage, was häufiger Änderungen unterliegt: die Datenbanktechnologie oder die fachlichen Anforderungen? Die Vertical Slice Architecture ist darauf ausgelegt, Änderungen und Erweiterungen der Fachlichkeit optimal zu unterstützen.

7. Vor- und Nachteile

Die Vertical Slice Architecture bietet eine Reihe von Vorzügen:

  • Konzentration auf die Fachlichkeit: Durch die Organisation nach fachlichen Slices wird die Entwicklung und Wartung erleichtert. Änderungen oder Erweiterungen betreffen in der Regel nur eine begrenzte Anzahl von Dateien oder Verzeichnissen, wodurch Seiteneffekte minimiert werden.
  • Bessere Testbarkeit: Die Isolation der Slices ermöglicht auch das getrennte Testen einzelner Funktionen und Use Cases
  • Kürzere Einarbeitungszeit: Im Vergleich zu komplexeren Architekturen wie der hexagonalen oder Clean Architecture ist die Vertical Slice Architecture einfacher zu verstehen und erfordert weniger Zeit für die Einarbeitung. Entwickler können schneller produktiv werden, da sie sich auf die spezifischen Anforderungen und Implementierungsdetails innerhalb eines Slices konzentrieren können.
  • Unabhängige Teams: Jedes Slice kann von einem dedizierten Team bearbeitet werden, ohne dass Abstimmungen mit anderen Teams erforderlich sind. Dies fördert die Autonomie und Flexibilität der Entwicklungsteams.
  • Lose Kopplung: Die Vertical Slice Architecture minimiert die Abhängigkeiten zwischen verschiedenen Slices. Jedes Slice ist weitgehend unabhängig von anderen, was die Skalierbarkeit und Wartbarkeit der Anwendung verbessert.

Die Vertical Slice Architecture hat aber auch Nachteile:

  • Gefahr der geringen Abstraktion: Es besteht das Risiko, dass zu wenig abstrahiert wird. Dies kann dazu führen, dass ähnliche Funktionalitäten in verschiedenen Slices dupliziert werden, was die Wartbarkeit und die Wiederverwendbarkeit des Codes beeinträchtigen kann.
  • Komplexität der Gesamtarchitektur: Wenn die Anwendung wächst und viele Slices hinzugefügt werden, kann die Gesamtarchitektur komplexer werden.
Training

Vertiefe deine Skills in der Softwarearchitektur Schulung.

Online Training
7. - 8. 11.2024
27. - 28. 3.2025
Jetzt anmelden
für 1.370,- €*

Schulungen in Bonn
19. - 20. 5.2025
Jetzt anmelden
für 1.480,- €*