Wie detailliert sollte ein Befehl in einem CQ [R] S-Modell sein?

17

Ich überlege mir ein Projekt, um einen Teil unserer WCF-basierten SOA auf ein Service-Bus-Modell (wahrscheinlich nServiceBus) zu migrieren und ein einfaches Pub-Sub zu verwenden, um eine Trennung von Befehlen und Abfragen zu erreichen .

Ich bin nicht neu in SOA oder sogar in der Wartung von Busmodellen, aber ich gebe zu, dass sich mein Konzept der "Trennung" bis vor kurzem auf das alltägliche Spiegeln und Replizieren von Datenbanken beschränkt hat. Ich bin dennoch von der Idee angetan, weil sie alle Vorteile eines schlussendlich konsistenten Systems zu bieten scheint und gleichzeitig viele der offensichtlichen Nachteile umgeht (insbesondere den Mangel an angemessener Transaktionsunterstützung).

Ich habe viel zu diesem Thema von Udi Dahan gelesen, der im Grunde genommen der Guru für ESB-Architekturen ist (zumindest in der Microsoft-Welt), aber eine Sache, die er sagt, verwirrt mich wirklich:

Je größer Entitäten mit mehr Feldern sind, desto mehr Akteure arbeiten mit denselben Entitäten. Je höher die Wahrscheinlichkeit ist, dass ein bestimmtes Attribut von ihnen berührt wird, desto höher ist die Anzahl der Nebenläufigkeitskonflikte.

[...]

Ein zentrales Element von CQRS ist das Überdenken des Designs der Benutzeroberfläche, damit wir die Absichten unserer Benutzer erfassen können, sodass die Bevorzugung eines Kunden eine andere Arbeitseinheit für den Benutzer darstellt als die Angabe, dass der Kunde umgezogen ist oder sie erhalten hat verheiratet. Wie wir oben gesehen haben, erfasst die Verwendung einer Excel-ähnlichen Benutzeroberfläche für Datenänderungen nicht die Absicht.

- Udi Dahan, geklärter CQRS

Aus der im Zitat beschriebenen Perspektive ist es schwierig, mit dieser Logik zu argumentieren. In Bezug auf SOAs scheint dies jedoch gegen den Strich zu gehen. Eine SOA (und wirklich die Dienste im Allgemeinen) sollen grobkörnige Nachrichten verarbeiten , um das Chatter im Netzwerk zu minimieren - neben vielen anderen Vorteilen.

Mir ist klar, dass Netzwerk-Chatter ein geringeres Problem darstellt, wenn Sie über stark verteilte Systeme mit guter Nachrichtenwarteschlange verfügen und kein RPC-Gepäck haben. Es ist jedoch nicht ratsam, das Problem vollständig zu verwerfen. Udi scheint fast zu sagen, dass jede Attributänderung (dh Feldaktualisierung) ein eigener Befehl sein sollte, der im Kontext eines Benutzers schwer vorstellbar ist, der möglicherweise Hunderte oder Tausende von kombinierten Entitäten und Attributen aktualisiert, wie es häufig bei einem herkömmlichen Befehl der Fall ist Internetservice.

Eine Stapelaktualisierung in SQL Server kann einen Bruchteil einer Sekunde in Anspruch nehmen, wenn eine gute hochparametrisierte Abfrage, ein tabellenwertiger Parameter oder eine Masseneinfügung in eine Staging-Tabelle vorliegt. Die Verarbeitung all dieser Aktualisierungen nacheinander ist langsam, langsam, langsam und die OLTP-Datenbankhardware ist die teuerste von allen, um sie zu vergrößern / zu verkleinern.

Gibt es eine Möglichkeit, diese konkurrierenden Bedenken in Einklang zu bringen? Denke ich falsch darüber nach? Hat dieses Problem eine bekannte Lösung in der CQS / ESB-Welt?

Wenn nicht, wie entscheidet man dann, wie die "richtige" Granularität in einem Befehl sein soll? Gibt es einen "Standard", den man als Ausgangspunkt verwenden kann - etwa 3NF in Datenbanken - und der nur dann abweichen kann, wenn eine sorgfältige Profilerstellung einen potenziell signifikanten Leistungsvorteil nahelegt?

Oder ist dies möglicherweise eines der Dinge, die, obwohl mehrere starke Meinungen von verschiedenen Experten geäußert wurden, wirklich nur eine Ansichtssache sind?

Aaronaught
quelle

Antworten:

7

Zum Thema "Jede Attributänderung"

Ich denke, Sie haben den Punkt verpasst. Herr Udi Dahan sagt, Sie sollten die Absicht des Benutzers als Befehl erfassen. Ein Endbenutzer muss angeben können, dass ein Kunde umgezogen ist. Abhängig vom Kontext, in dem dieser Befehl eine Kundenidentifikation enthalten könnte, die neue Adresse (aufgeteilt in Straße, Straßennummer, Postleitzahl, ...), optional eine neue Telefonnummer (nicht ungewöhnlich, wenn Sie umziehen - bei all diesen Mobiltelefonen möglicherweise weniger). . Das ist kaum eine Eigenschaft. Eine bessere Frage ist "Wie entwerfe ich Befehle?". Sie entwerfen sie aus einer Verhaltensperspektive. Jeder Anwendungsfall, jeder Ablauf und jede Aufgabe, die ein Endbenutzer ausführen möchte, wird in einem oder mehreren Befehlen erfasst. Welche Daten mit diesen Befehlen verbunden sind, ist eine Selbstverständlichkeit, wenn Sie sie näher betrachten. Achten Sie auf Daten, die wie folgt interpretiert werden:Dies könnte ein Hinweis darauf sein, dass Sie den Befehl aufteilen müssen. Ich hoffe, Sie werden diesen Standard in Bezug auf die Befehlsgranularität nie finden . Gute Frage!

Yves Reynhout
quelle
Diese Definition fühlt sich für mich immer noch sehr willkürlich an; Das konzeptionelle Modell eines CSR kann den bevorzugten Status und den Kriegsstatus auf dieselbe Weise zusammenfassen, wie Sie die Adresse und die Postleitzahl zusammenfassen. Ich möchte keine Haare spalten, es scheint mir nur, dass man in der Lage sein muss, die Downstream-Effekte und OTOH die gesamte Idee von ESB und CQS und pub / vorherzusagen, um wirklich zu verstehen, ob es sich um unterschiedliche Verhaltensweisen handelt. Sub ist, dass Sie nicht wissen oder sich darum kümmern sollen, was stromabwärts passiert. Vielen Dank für Ihre Antwort, ich weiß es zu schätzen, obwohl ich nicht sagen kann, dass ich mich bisher aufgeklärter fühle ...
Aaronaught
@Aaronaught: Die Definition ist beliebig. Die Granularität eines Befehls sollte für jedes Szenario sinnvoll sein . Es gibt keine Einheitsgröße. Es gibt verschiedene Richtlinien, z. B. die Zuordnung von Befehlen zu Anwendungsfällen, Aufgaben oder Aktionen, die in der Benutzeroberfläche verfügbar sind. Eine andere besteht darin, granularere Befehle gegenüber weniger granularen Befehlen zu bevorzugen (insbesondere, wenn Yves der Ansicht ist, dass Daten, die als logischer Steuerungsfluss interpretiert werden, vorsichtig sind). aber keine feste Regel. Gibt es ein tatsächliches Szenario, in dem "ein Benutzer möglicherweise Hunderte oder Tausende kombinierter Entitäten und Attribute aktualisiert"?
Quentin-Starin
Das ist der springende Punkt! Nicht zusammen werfen. Teilen Sie nach Verhalten! Fügen Sie keine Daten in den Befehl ein, die nicht mit der Absicht des Befehls / Endbenutzers übereinstimmen. Dabei geht es nicht um nachgelagerte Systeme.
Yves Reynhout
@qes: In unseren Systemen gibt es mehrere solche Szenarien, sehr real und sehr notwendig. Um es so einfach wie möglich auszudrücken, müssen sie ganze Sequenzen von Daten modifizieren und diese Sequenzen sind nur als Sequenzen sinnvoll. Natürlich nehmen sie diese Änderungen normalerweise nicht einzeln vor, sondern wenden einen Algorithmus auf den Großteil der Änderungen an und korrigieren dann einige Ausnahmen. Vielleicht ist dies für CQS zunächst einfach kein geeignetes Szenario, aber diese Entscheidung ist nur eine Teilmenge meiner weiter gefassten Frage.
Aaronaught
1
@qes: Fair genug, und das ist eine Antwort für sich. Ich verstehe sicherlich das Konzept einer logischen Operation (das ist , wie die bestehenden Dienste modelliert), ich glaube , ich habe gerade besorgt, dass CQS einige der Regeln zu ändern scheint , um , wie Sie sollte eine Operation definieren. "Traditionelle" SOA scheint von einer möglichst groben Definition auszugehen und bei Bedarf die Abstraktionsleiter hinunterzugehen. Mein bisheriges Verständnis von CQS scheint das Gegenteil anzudeuten. Ich gehe von einer möglichst granularen und abstrakten Definition aus, wenn es zu sehr nach RPC oder Kontrollfluss aussieht.
Aaronaught
2

Die Botschaft, die Udi zu vermitteln versucht, ist, dass CQRS mehr als nur CRUD ist. Warum habe ich diesen Datensatz erstellt? Warum ändere ich diesen Datensatz? Warum wird es gelöscht / als gelöscht markiert?

Befehle sollten Aktionen / Anwendungsfällen entsprechen, die der Benutzer mit dem System durchführt, und die Absicht der Aktion zum Ausdruck bringen, anstatt nur zu sagen, dass dies geändert werden soll. Es mag auch so aussehen, als wäre es feinkörniger, aber es könnte viel gröber sein, als es zuerst erscheint. Zum Beispiel kann das Upgrade auf den Goldstatus eine Änderung mehrerer Attribute beinhalten, und eine Reihe anderer Aggregate kann sogar auf das entsprechende Ereignis reagieren und sich ändern.

Bei CQRS geht es darum, die Geschäftssprache in der Service-Ebene zu erfassen, damit sich die Benutzeroberfläche keine Gedanken darüber machen muss, was passiert, wenn ich das Goldstatus-Upgrade vornehme oder wenn die Sendung vom Spediteur als nicht zustellbar markiert oder der Mitarbeiter befördert wurde zum Manager des Technologiekonzerns. Nun, technisch gesehen spreche ich jetzt über Event Sourcing, aber Sie bekommen meinen Drift. Es gibt deutlichere Botschaften, aber diese sind nicht unbedingt feinkörniger als die Standard-CUD.

Michael Brown
quelle