2015-12-15 9 views
6

In einem CQRS Domain Driven Design-System besagt die FAQ, dass eine Saga die Leseseite nicht abfragen sollte (http://cqrs.nu). Eine Saga hört jedoch Ereignisse ab, um Befehle auszuführen, und weil sie Befehle ausführt, ist sie im Wesentlichen ein "Client". Warum kann also eine Saga die gelesenen Modelle nicht abfragen?Warum kann Sagas die Leseseite nicht abfragen?

Antwort

0

Sagas verwenden das Befehlsmodell, um den Status des Systems zu aktualisieren. Das Befehlsmodell enthält Geschäftsregeln und kann sicherstellen, dass Änderungen innerhalb einer bestimmten Domäne gültig sind. Dazu verfügt das Befehlsmodell über alle Informationen, die es benötigt.

Das Lesemodell hat andererseits einen ganz anderen Zweck: Es strukturiert Daten, so dass es geeignet ist, Informationen zu liefern, z. auf einer Webseite anzuzeigen.

Da die Saga über das Befehlsmodell alle benötigten Informationen enthält, benötigt sie das Lesemodell nicht. Schlechter würde das Verwenden des gelesenen Modells von einer Saga zusätzliche Kopplung einführen und die Gesamtkomplexität des Systems beträchtlich erhöhen.

Dies bedeutet nicht, dass Sie das Lesemodell absolut nicht verwenden können. Aber wenn Sie das tun, vergewissern Sie sich, dass Sie die Konsequenzen verstehen. Für mich ist diese Bar ziemlich hoch und ich habe immer eine andere Lösung gefunden.

+0

OK, aber was ist mit diesem Szenario (http://stackoverflow.com/questions/34257897/how-are-consistency-viiolations-handled-in-event-sourcing)? Würden Sie empfehlen, den Ereignisspeicher intelligent zu machen (kompliziert), indem Sie zulassen, dass er von beliebigen Aggregatschlüssel/Wert-Paaren abgefragt wird? – magnus

+0

Sie müssen sicherlich in der Lage sein, ein Aggregat aus dem Ereignisspeicher zu rekonstruieren, um Geschäftsregeln überprüfen zu können - darum geht es beim Befehlsmodell. Natürlich ist das ein bisschen komplizierter als bei der Verwendung eines ORM - das ist der Kompromiss, den Sie bei der Auswahl von ES gemacht haben. – theDmi

+0

Sie haben die Frage in meinem Kommentar nicht beantwortet. Bei der referenzierten SO-Frage gibt es eine AR 'Bestellung' und eine 'Kunde' AR. Wenn die "postalAddress" des "Kunden" aktualisiert wird, muss die Saga alle nicht versandten 'Bestellungen' des Kunden abrufen, um die' deliveryAddress' der Bestellung zu aktualisieren (dies ist eine 1: n-Beziehung in SQL-Begriffen, obwohl sie beide ARs in DDD-Bedingungen sind). Wie würdest du die Sage machen, ohne auf das Lesemodell zuzugreifen? – magnus

2

Sagas sollten die gelesene Seite (Projektionen) nicht nach Informationen abfragen, die sie benötigt, um ihre Aufgabe zu erfüllen. Der Grund ist, dass Sie nicht sicher sein können, dass die Leseseite aktuell ist. In einem eventuellen konsistenten System wissen Sie nicht, wann die Projektion aktualisiert wird, so dass Sie sich nicht auf ihren Zustand verlassen können.

Das bedeutet nicht, dass sagas keinen Zustand halten sollte. Sagas müssen in vielen Fällen den Staat im Auge behalten, aber dann sollte die Saga dafür verantwortlich sein, diesen Staat zu schaffen. Wie ich es sehe, kann dies auf zwei Arten geschehen.

Er kann seinen Status durch Lesen der Ereignisse aus dem Ereignisspeicher aufbauen. Wenn es ein Ereignis empfängt, auf das es ausgelöst werden soll, liest es alle Ereignisse, die es benötigt, aus dem Speicher und baut seinen Zustand auf ähnliche Weise wie ein Aggregat auf. Dies kann in Event Store durch Erstellen neuer Streams performant gemacht werden.

Die andere Möglichkeit besteht darin, dass es ständig Ereignisse aus dem Ereignisspeicher überwacht und Zustände aufbaut und diese wie bei Projektionen auf einem Datenspeicher speichert. Seien Sie vorsichtig mit diesem Ansatz. Sie können Sagas nicht genauso beantworten wie mit Projektionen. Wenn Sie die Art ändern müssen, in der Sie den Status speichern und neu erstellen möchten, stellen Sie sicher, dass Sie die Befehle, die Sie bereits ausgeführt haben, nicht ausführen.

+0

Aber was ist, wenn es uns egal ist, dass die Daten nur schließlich konsistent sind, d.h. wenn der Wert ein bisschen alt ist? Alle über die Benutzeroberfläche eingehenden Befehle basieren auf alten Daten (projizierte Daten, die seit der Abfrage nicht aktualisiert wurden). Wir haben damit kein Problem. Persönlich denke ich, dass Sagas vielleicht etwas wie ein Kunde betrachtet werden könnte. PS: Ich kann verstehen, dass es Situationen geben kann, in denen transaktionskonsistente Daten benötigt werden, und ich unterstütze die Verwendung des Ereignisses mehr, um diese Daten in Saga aktuell zu halten. –

0

Es geht in erster Linie um die Trennung von Anliegen. Prozessmanager (sagas) sind staatliche Maschinen, die für die Koordination von Aktivitäten verantwortlich sind. Wenn der Prozessmanager die Änderung beeinflussen möchte, sendet er Befehle (asynchron).

Auch: Was ist das Lesemodell? Es ist eine Projektion einer Reihe von Ereignissen, die bereits passiert sind. Also, wenn der Prozessor sich um diese Ereignisse gekümmert hat ... hätte er sie nicht die ganze Zeit abonniert haben sollen? Es riecht hier also nach Geruch.

Mögliche Probleme:

Die Prozess-Manager auf frühere Nachrichten abhören im Strom haben sollten, so dass sie im richtigen Zustand sein würden, wenn diese Meldung kommt.

Das aktuelle Ereignis sollte reicher sein (damit die Daten, die der Prozessmanager benötigt, bereits vorhanden sind).

... Variation - der Befehlshandler sollte stattdessen auf ein anderes Ereignis warten, und das sollte reich sein.

Die Abfrage, die Sie wirklich wollen, ein Befehl an ein Aggregat sein sollte, dass die Antwort bereits

und es nicht alle anderen

senden einen Befehl an einen Dienst kennt, der die Abfrage ausgeführt und löst Ereignisse in Reaktion . Das hört sich merkwürdig an, aber es ist bereits üblich, dass ein Prozessmanager eine Nachricht an einen Terminplanungsdienst sendet, um "aufgewacht" zu werden, wenn eine bestimmte Zeit verstrichen ist.

Verwandte Themen