CQRS – neues Architekturprinzip zur Trennung von Befehlen und Abfragen

Architektur/Methoden  –  10 Kommentare

CQRS ist ein erfolgreicher Gegenentwurf zum klassischen Schichtenmodell für Systeme mit parallelem Nutzerzugriff. Das Prinzip fordert eine Aufteilung in Verhaltens- und Abfragemodelle, mit der man die Geschäftslogik als wertvollsten Bestandteil einer Anwendung von der Datenbereitstellung für Benutzerschnittstellen und Reporting entkoppelt entwickeln kann.

Das Architekturprinzip CQRS (Command Query Responsibility Segregation) fordert im Kern die Aufteilung der Softwarearchitektur in zwei Teile [1, 2, 3, 4]. Diese haben klar getrennte Verantwortlichkeiten: einerseits für das Ausführen von Befehlen (Commands), die eine Zustandsänderung des Softwaresystems nach sich ziehen, andererseits für das seiteneffektfreie Bedienen von Abfragen (Queries). Diese Trennung ist eine Weiterführung von Bertrand Meyers CQS-Prinzip (Command Query Separation) [5, 6], das eine analoge Trennung für einzelne Methoden eines Interfaces verlangt.

CQRS ist durchaus keine neue Idee. Es ist vielmehr als zeitgemäßer Gegenentwurf zum allgegenwärtigen vertikalen Schichtenmodell typischer n-tier Anwendungen zu sehen. Die hierbei übliche Anordnung von Datenbank (relational), Datenzugriffsschicht (O/R Mapper), Geschäftslogik, Applikationsschicht und Präsentationsschicht bedingt in der Regel eine Verletzung des Single-Responsibility-Prinzips (SRP) [7] auf Ebene der Softwarearchitektur. Datenzugriffsschicht und Geschäftslogik werden sowohl zur Validierung und Ausführung von Benutzeraktionen herangezogen als auch für das Bereitstellen von Daten zur Anzeige in Präsentationsschicht und Reporting. Diese Verflechtung zweier unterschiedlicher Verantwortlichkeiten gehen Entwickler und Architekten oft unreflektiert und mit fatalen Folgen ein. Sie führt dazu, dass die Umsetzung der Anforderungen an die Prozesslogik durch Notwendigkeiten der einigermaßen performanten Abfragebearbeitung kompromittiert wird. Im Gegenzug stört implementiertes Verhalten dabei, größere Datenmengen an Abfragen performant zurückzuliefern.

CRUD

CRUD steht für Create, Read, Update und Delete, also ausschließlich grundlegende Datenbankoperationen ohne jegliche Funktion aus der eigentlichen Anwendungsdomäne.

Sollten so konstruierte Systeme parallel von vielen Nutzern verwendet werden, stoßen sie schnell an Grenzen und sind aufwendig zu verbessern. Die Komplexität steigt, und die Wartbarkeit nimmt ab. Der Versuch gegenzusteuern resultiert dann nicht selten in der Vernachlässigung eigentlich gewünschten Verhaltens in der Geschäftslogik und einer Überbetonung von Daten und Strukturen. Im Extremfall erhält man sogenannte Spreadsheet- oder CRUD-Anwendungen (siehe Kasten), bei denen die abzubildenden Prozesse und Geschäftsregeln in Betriebshandbücher und damit aus der Software verdrängt werden. In engem Zusammenhang damit steht das "anämische Domänenmodell", ein Anti-Pattern, das die objektorientierte Modellimplementierung des eigentlichen Verhaltens beraubt und auf Felder und Validierung reduziert ist.

CQRS löst diesen Konflikt durch die Einführung von zwei Modellen, eines für die Abbildung der Geschäftslogik (oft in Form eines objektorientierten Domänenmodells) und eines für die Bereitstellung von Daten (Abfragemodell). Die Aufteilung erlaubt nicht nur, beide Modelle auf ihre jeweilige Verantwortlichkeit hin zu optimieren. Sie ermöglicht wesentlich einfachere Tests der Geschäftslogik und öffnet darüber hinaus den Weg für eine ganze Reihe von Vereinfachungen, die im Wegfall einiger "großer" Techniken gipfeln: O/R Mapper werden ebenso überflüssig wie Datenbankcluster oder Caches, und sogar auf relationale Datenbanken lässt sich verzichten.

Kontroll- und Datenfluss in einer CQRS-Architektur. Die Anwendung sendet Befehle an das Modell der Geschäftslogik. Dieses veröffentlicht Ereignisse als Ergebnis. Das Abfragemodell wertet die Ereignisse aus und erstellt daraus Daten für den Abruf durch die Anwendung (Abb. 1).

CQRS beschreibt eine Architektur mit getrennten Pfaden und Verantwortlichkeiten, mit denen sich einerseits Verhalten zur Änderung des Systemzustands ausführen und andererseits Daten abfragen lassen (Abb. 1). Bei der Auswahl der konkreten Implementierung des Prinzips gibt es viel Gestaltungsspielraum durch unterschiedliche Entwurfsmuster. Auch wenn dieser Spielraum anfangs verwirren mag, ist er hilfreich und wichtig, um die Systemarchitektur optimal an den nichtfunktionalen Anforderungen auszurichten. Der Artikel beschränkt sich auf die Darstellung einer gebräuchlichen Variante. Die Autoren kombinieren CQRS mit dem Persistenzmechanismus Event Sourcing [8] und einem objektorientierten Domänenmodell zum Beispiel nach Domain-Driven Design (DDD) [9, 10, 11] für die Geschäftslogik. Einen Überblick über den Informationsfluss in der Architektur gibt Abbildung 2.

Eine konkrete CQRS-Architektur. Die primäre Datenhaltung geschieht hierbei im "Event store". Die Abfragemodelle lassen sich je nach Anforderungen in unterschiedlicher Form vorhalten (Abb. 2).

Die einzelnen Komponenten seien im Folgenden vorgestellt.