Real World Softwaredesign, Teil 3: Command Query Responsibility Segregation Pattern

In diesem Artikel möchte ich Ihnen ein weiteres Software-Designkonzept anhand eines Beispiels aus der realen Welt vorstellen.

Lassen Sie uns dazu einen Teil der Logistikkette einer Produktionsfirma für Kaffeemaschinen betrachten. Es handelt sich dabei um qualitativ hochwertige Maschinen die in kleineren Stückzahlen produziert werden. Wir betrachten den Bereich der Materialbeschaffung in Form des Wareneingangs und den Vertrieb in Form des Warenausgangs.

Die Produktionsfirma arbeitet mit einem Logistikpartner zusammen. Dieser ist für die Anlieferung der benötigten Materialien und für den Auslieferung der hergestellten Waren verantwortlich. Im Moment liefert der Logistikpartner jeden Montag, Mittwoch und Freitag die entsprechenden Materiealien. Jeden Dienstag und Donnerstag erfolgt die Abholung der fertigen Kaffeemaschinen.

 

Vorteile

Dieses Warenumschlagsintervall ist für die Produktionsfirma vorteilhaft. Diese kann dadurch den Warenumschlagsbereich klein halten. Es wird beispielweise nur eine Laderampe benötigt da niemals Anlieferung und Abholung zugleich erfolgen.

Auch der Logistikpartner profitiert von diesem Vorgehen. Er kann den kompletten Warenumschlag der Produktionsfirma über einen Angestellten abwickeln.

Das Warenumschlagsintervall kann dabei ausserdem recht einfach geändert werden. Ist an einem Montag zum Beispiel ein Feiertag so kann der Lieferungs- und Abholrhythmus einfach um einen Tag verschoben werden. Dazu reicht die Absprache mit dem Logistikpartner. Hätte die Produktionsfirma mehrere Logistikpartner so müsste sie diese mühsam synchronisieren. Bei einem Logistikpartner kann sich dieser selbst um die Synchronisation der Liefer- und Abholtermine kümmern.

Nun möchte ich dieses Beispiel auf die Softwareentwicklung anwenden. In einer Softwareanwendung werden typischerweise keine Warenströme realisiert, sondern Datenströme. Beispielsweise könnte die Produktionsfirma eine Software einsetzen welche den Warenumschlag verwaltet. Dabei müssen Lieferdaten zu den Waren erfasst, verwaltet und abgefragt werden.

In einer typischen Softwareanwendung gibt es meist eine Geschäftslogikschicht welche die Daten verwaltet. Diese nutzt wiederum eine Datenschicht welche die Daten beispielsweise in einer Datenbank speichert. Genau wie die Produktionsfirma die Materialien vom Logistikpartner entgegennimmt, so nimmt die Geschäftslogikschicht die abgefragten Daten von der Datenschicht entgegen. Die Warenübergabe von Produzenten an den Logistikpartner entspricht einer Datenübergabe aus der Geschäftslogikschicht in die Datenschicht.

Die Produktionsfirma nutzt in unserem Beispiel einen Logistikpartner für Lieferung und Abholung von Waren. Die Datenschicht der Anwendung soll gleichermassen aufgebaut werden. Es wird eine Komponente implementiert welche sowohl Datenabfragen, als auch Datenlieferungen also Datenaktualisierungen zulässt.

Genau wie bei der Produktionsfirma entstehen dadurch einige Vorteile. Die Geschäftslogikschicht muss sich beispielsweise nicht um die Synchronisation von Abfragen und Aktualisierungen kümmern. Dies erledigt die Datenschicht, die genau wie die Logistikfirma einen oder bei Bedarf mehrere Angestellte in Form von mehreren Threads einsetzt und diese intern synchronisiert.

 

Nachteile

Neben den genannten Vorteilen entstehen natürlich auch Nachteile. Ein grosser Nachteil ist die direkte Abhängigkeit von dem einen monopolistischen Dienstanbieter. In Bezug auf die Produktionsfirma entsteht eine starke Abhängigkeit vom Logistikpartner. Wenn dieser Konkurs geht oder wenn dieser sein Preismodell ändert, dann hat die Produktionsfirma ein Problem das nicht schnell gelöst werden kann. Ein Wechsel zu einem anderen Logistikpartner ist mit hohem zeitlichem und finanziellem Aufwand verbunden.

Ähnlich sieht die Situation in Softwareprojekten aus. Hier sind Sie gleichermassen von der einen Datenkomponente abhängig. Sicher haben Sie auch schon in Ihren Projekten erlebt wie schwierig es wird wenn z.B. der Entwickler dieser Komponente die Firma verlässt oder wegen Krankheit eine längere Zeit ausfällt. Auch in dieser Situation kommt ein hoher Zeit-und Kostenfaktor auf Sie zu der mit der Einarbeitung eines neuen Entwicklers und meist auch mit einer Refaktorisierung einzelner Komponenten verbunden ist.

Neben der Abhängigkeit ist ein weiterer Nachteil in der eingeschränkten Flexibilität zu sehen. Die Produktionsfirma möchte beispielsweise ihren Warenumsatz erhöhen. Dazu bietet sie zusätzlich einen Werksverkauf an. Um mehr produzieren zu können benötigt die Firma nun mehr Materialien. Die drei Liefertermine pro Woche reichen daher nicht mehr aus. Eine Erhöhung auf vier Liefertermine ist aber mit vielen Hindernissen verbunden. Diese kommen in Konflikt mit den zwei Abtransporten der fertigen Waren. Hier gibt es nun Terminüberscheidungen. Daher muss die Produktionsfirma ihr Lager erweitern und eine zweite Laderampe bauen. Der Logistikpartner wiederrum muss einen weiteren Mitarbeiter einstellen um ein paralleles Liefern und Abholen zu ermöglichen. Diese parallelen Dienste müssen darüber hinaus synchronisiert werden.

Auf die Softwareanwendung angewendet stehen die gleichen Probleme im Raum. Die Datenkomponente die ursprünglich für einen single-thread Fall implementiert wurde muss nun multi-thread fähig gemacht werden um die parallelen Prozesse zu unterstützen. Dies kann unter Umständen dazu führen das ein Grossteil der Komponente neu programmiert werden muss.

Auch die Geschäftslogikschicht der Applikation muss angepasst werden. Genau wie eine zweite Laderampe im Warenlager der Produktionsfirma nötig ist, muss die Geschäftslogikschicht nun ebenfalls mehrere gleichzeitige Abläufe zulassen. Damit ist auch in diesem Bereich eine Erweiterung des Quellcodes um multi-threading Features nötig.

 

Alternative

Nach Betrachtung der Nachteile sollte nun geprüft werden welche Alternative zu dem oben
aufgezeigtem Modell möglich ist um die Nachteile auszuräumen. Eine einfache und in der Praxis oft gesehene Alternative besteht darin, dass mit mehreren Logistikpartnern zusammen gearbeitet wird. So könnte die Produktionsfirma zum Beispiel mehrere Lieferanten für die Materialien einsetzen und auch mehrere Auslieferer für die fertigen Waren beauftragen.

Dies erhöht die Flexibilität der Produktionsfirma ungemein und senkt zusätzlich das Risiko bei Ausfall einer Partnerfirma. Wenn ein Logistikpartner zum Beispiel Konkurs geht kann er einfacher durch einen anderen Logistikpartner ersetzt werden.

Für die Produktionsfirma entsteht im Gegenzug aber ein erhöhter Aufwand im Bereich der logistischen Planung. Die Produktionsfirma muss sich nun selbst darum kümmern die Warenströme der verschiedenen Logistikpartner zu synchronisieren.

Für die Softwareapplikation entsteht eine ähnliche Konstellation. Die Datenkomponente kann durch mehrere spezialisierte Komponenten ersetzt werden, welche die unterschiedlichen Datenströme steuern. Dies erhöht die Skalierbarkeit, Erweiterbarkeit und Flexibilität der Anwendung. Wenn diese Komponenten von unterschiedlichen Entwicklern erstellt wurden wird gleichzeitig das Risiko bei Ausfall eines Entwicklers gemindert.

Aber auch im Fall der Softwareapplikation muss nun die Geschäftslogikschicht erweitert werden. Diese muss sich um die Synchronisation der Datenkomponenten kümmern und die Aufgaben auf diese Komponenten verteilen.

 

Softwaredesignkonzept

Im Bereich der Softwareentwicklung gibt es für diesen Anwendungsfall ein entsprechendes Designkonzept, das Command Query Responsibility Segregation Pattern (CQRS).

Dieses besagt, dass Datenströme nach Datenabfragen und Datenmanipulationen getrennt werden sollten. Das Konzept wird meist in Verbindung mit Datenbanken genannt. Das Designkonzept ist aber nicht auf eine bestimmte Form der Datenspeicherung beschränkt. Es lässt sich allgemein bei jeder Form der Datenverwaltung anwenden.

Allgemein sagt das Konzept aus, dass bei Abfragen (Queries) die Daten nur zurückgegeben werden und es keinerlei Änderungen an den Daten geben darf. Datenaktualisierung (Commands) hingegen ändern die Daten, geben dafür aber keine Daten zurück.

Die Trennung nach Datenabfragen und Datenmanipulationen kann je nach Anwendungsfall unterschiedlich ausfallen. Im einfachsten Fall handelt es sich um zwei unterschiedliche Objekte die von der Geschäftslogikschicht genutzt werden. Aber auch eine getrennte Ausführung von mehreren Services auf unterschiedlicher Hardware ist denkbar.

Diese strikte Trennung nach Belangen hat die dementsprechenden Vorteile bei der Implementierung, Verwendung und Erweiterung der Softwarekomponenten.

Diesen Vorteil erkauft man sich, wie bereits beschrieben, mit einem höheren Synchronisationsaufwand. Stellen Sie sich beispielsweise vor Sie wollen Daten ausgehend von deren aktuellem Status aktualisieren. Das heisst das Datenabfragen und Datenaktualisierungen in einen direkten logischen Zusammenhang gebracht werden müssen. Hierbei entsteht in der Geschäftslogikschicht ein erhöhter Implementierungsaufwand da diese Funktionalitäten unter Umständen mit aufwändigen Multithreading- und Transaktionskonzepten gelöst werden müssen.

Die aufgezeigten Vorteile und Nachteile des Designkonzept implizieren dass dieses Konzept nicht in jeder Situation sinnvoll einsetzbar ist. Je nach Anwendungsfall kann das Designkonzept besser oder schlechter verwendet werden.

In hochperformanten Anwendungen kann die Trennung der Abfragen und Aktualisierungen viel Gewinn bringen und eine besserer Skalierung zulassen.  Ist die Datenanbindung hingegen relativ unkritisch (zeitlich und funktional) dann kann ein klassisches CRUD Model, also eine Datenverwaltung mit Create, Read, Update und Delete Funktionen durchaus die besser Wahl sein. Es gilt also wie immer einen Kosten- und Nutzenvergleich aufzustellen.

 

Fazit

Als Softwareentwickler sollten Sie das Command Query Responsibility Segregation Pattern immer in der Hinterhand haben. Sie sollten dieses aber nicht zwangsweise in jedem Projekt einsetzen. Anhand der projektspezifischen Anforderungen sollte entschieden werden ob dieses Design Pattern für die Umsetzung der Anforderungen geeignet ist oder ob es bessere Alternativen gibt.

Advertisements
Dieser Beitrag wurde unter Softwaredesign abgelegt und mit verschlagwortet. Setze ein Lesezeichen auf den Permalink.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s