Was ist der Unterschied zwischen Befehlen und Ereignissen in Architekturen, die Ereignisse hervorheben? Der einzige Unterschied, den ich sehen kann, ist, dass Befehle normalerweise von Akteuren außerhalb des Systems bezogen / aufgerufen werden, während Ereignisse von Handlern und anderem Code in einem System bezogen zu werden scheinen. In vielen Beispielanwendungen, die ich gesehen habe, haben sie jedoch unterschiedliche (aber funktional ähnliche) Schnittstellen.
events
command
cqrs
event-driven-design
alphadogg
quelle
quelle
Antworten:
Befehle können abgelehnt werden.
Ereignisse sind passiert.
Dies ist wahrscheinlich der wichtigste Grund. In einer ereignisgesteuerten Architektur kann es keine Frage geben, dass ein ausgelöstes Ereignis etwas darstellt, das passiert ist .
Nun, da Befehle sind etwas , was wir wollen passieren, und Ereignisse sind etwas , das ist passiert, sollten wir verschiedene Verben verwenden , wenn wir diese Dinge nennen. Dies führt zu separaten Darstellungen.
Dies ist ein weiterer Grund, warum sie separat dargestellt werden. Konzeptionelle Klarheit.
Befehle und Ereignisse sind beide Nachrichten. Tatsächlich handelt es sich jedoch um separate Konzepte, und Konzepte sollten explizit modelliert werden.
quelle
Zusätzlich zu allen hier offengelegten Antworten kann ein Ereignishandler möglicherweise auch einen Befehl auslösen, nachdem er eine Benachrichtigung über das Auftreten eines Ereignisses erhalten hat.
Angenommen, Sie möchten nach dem Erstellen eines Kunden auch einige Kontenwerte usw. initialisieren. Nachdem Ihr Kunden-AR das Ereignis zum EventDispatcher hinzugefügt hat und dieses von einem CustomerCreatedEventHandler-Objekt empfangen wird, kann dieser Handler einen Versand eines Befehls auslösen, der führt alles aus, was Sie brauchen, etc.
Es gibt auch DomainEvents und ApplicationEvents. Der Unterschied ist einfach konzeptionell. Sie möchten zuerst alle Ihre Domänenereignisse auslösen (einige von ihnen können Anwendungsereignisse erzeugen). Was meine ich damit?
Das Initialisieren eines Kontos nach dem Auftreten eines CustomerCreatedEvent ist ein DOMAIN-Ereignis. Das Senden einer E-Mail-Benachrichtigung an den Kunden ist ein Anwendungsereignis.
Der Grund, warum Sie sie nicht mischen sollten, ist klar. Wenn Ihr SMTP-Server vorübergehend außer Betrieb ist, bedeutet dies nicht, dass Ihr DOMAIN-BETRIEB davon betroffen sein sollte. Sie möchten weiterhin einen nicht beschädigten Status Ihrer Aggregate beibehalten.
Normalerweise füge ich meinem Dispatcher Ereignisse auf der Ebene des aggregierten Stamms hinzu. Diese Ereignisse sind entweder DomainEvents oder ApplicationEvents. Kann beides sein und kann viele von ihnen sein. Sobald mein Befehlshandler fertig ist und ich wieder im Stapel zu dem Code bin, der den Befehlshandler ausführt, überprüfe ich meinen Dispatcher und versende jedes andere DomainEvent. Wenn all dies erfolgreich ist, schließe ich die Transaktion ab.
Wenn ich Anwendungsereignisse habe, ist dies die Zeit, diese zu versenden. Das Senden einer E-Mail erfordert nicht unbedingt eine offene Verbindung zu einer Datenbank oder einen offenen Transaktionsbereich.
Ich bin ein wenig von der ursprünglichen Frage abgewichen, aber es ist auch wichtig, dass Sie verstehen, wie Ereignisse auch konzeptionell anders behandelt werden können.
Dann haben Sie Sagas ... aber das ist WAYYYY OFF vom Umfang dieser Frage :)
Macht das Sinn?
quelle
Die Veranstaltung ist eine Tatsache aus der Vergangenheit.
Der Befehl ist nur eine Anfrage und kann daher abgelehnt werden.
quelle
Nachdem ich einige Beispiele und insbesondere die Präsentation von Greg Young ( http://www.youtube.com/watch?v=JHGkaShoyNs ) durchgearbeitet habe, bin ich zu dem Schluss gekommen, dass Befehle redundant sind. Es sind einfach Ereignisse von Ihrem Benutzer, sie haben diese Taste gedrückt. Sie sollten diese genauso speichern wie andere Ereignisse, da es sich um Daten handelt und Sie nicht wissen, ob Sie sie in einer zukünftigen Ansicht verwenden möchten. Ihr Benutzer hat diesen Artikel hinzugefügt und später aus dem Warenkorb entfernt oder zumindest versucht. Möglicherweise möchten Sie diese Informationen später verwenden, um den Benutzer zu einem späteren Zeitpunkt daran zu erinnern.
quelle
Sie werden getrennt dargestellt, weil sie sehr unterschiedliche Dinge darstellen. Wie @qstarin sagte, sind Befehle Nachrichten, die abgelehnt werden können und die bei Erfolg ein Ereignis erzeugen. Befehle und Ereignisse sind Dtos, sie sind Nachrichten und sie sehen beim Erstellen und Entifizieren sehr ähnlich aus, jedoch von da an nicht unbedingt.
Wenn Sie sich Sorgen über die Wiederverwendung machen, können Sie Befehle und Ereignisse als Umschläge für Ihre (Messge-) Nutzdaten verwenden
Ich würde jedoch gerne wissen, warum Sie fragen: Haben Sie zu viele Befehle / Ereignisse?
quelle
Zusätzlich zu den oben erwähnten konzeptionellen Unterschieden gibt es meines Erachtens noch einen weiteren Unterschied in Bezug auf gemeinsame Implementierungen:
Ereignisse werden normalerweise in einer Hintergrundschleife verarbeitet, die die Ereigniswarteschlangen abfragen muss . Jede Partei, die daran interessiert ist, auf das Ereignis zu reagieren, kann normalerweise einen Rückruf registrieren, der als Ergebnis der Verarbeitung der Ereigniswarteschlange aufgerufen wird. Ein Ereignis kann also eins zu viele sein .
Befehle müssen möglicherweise nicht auf diese Weise verarbeitet werden. Der Urheber des Befehls hat normalerweise Zugriff auf den beabsichtigten Ausführenden des Befehls. Dies kann beispielsweise in Form einer Nachrichtenwarteschlange an den Executor erfolgen. Somit ist ein Befehl für eine einzelne Entität vorgesehen .
quelle
Ich denke, etwas, das Quentin-Santins Antwort hinzufügen kann, ist, dass sie:
Quelle .
quelle
Sie können einen Status nicht basierend auf Befehlen neu berechnen, da diese im Allgemeinen bei jeder Verarbeitung unterschiedliche Ergebnisse liefern können.
Stellen Sie sich zum Beispiel einen
GenerateRandomNumber
Befehl vor. Jedes Mal, wenn es aufgerufen wird, wird eine andere Zufallszahl X erzeugt. Wenn Ihr Status von dieser Zahl abhängt, erhalten Sie jedes Mal, wenn Sie Ihren Status aus dem Befehlsverlauf neu berechnen, einen anderen Status.Ereignisse lösen dieses Problem. Wenn Sie einen Befehl ausführen, wird eine Folge von Ereignissen erzeugt, die das Ergebnis der Befehlsausführung darstellen. Beispielsweise
GenerateRandomNumber
könnte der Befehl einGeneratedNumber(X)
Ereignis erzeugen , das die generierte Zufallszahl protokolliert. Wenn Sie jetzt Ihren Status aus dem Ereignisprotokoll neu berechnen, erhalten Sie immer denselben Status, da Sie immer dieselbe Nummer verwenden, die durch eine bestimmte Ausführung des Befehls generiert wurde.Mit anderen Worten, Befehle sind Funktionen mit Nebenwirkungen. Ereignisse zeichnen das Ergebnis einer bestimmten Ausführung eines Befehls auf.
Hinweis: Sie können weiterhin einen Verlauf von Befehlen für Prüf- oder Debugging-Zwecke aufzeichnen. Der Punkt ist, dass Sie zur Neuberechnung des Status den Verlauf von Ereignissen verwenden, nicht den Verlauf von Befehlen.
quelle
Nur um diese großartigen Antworten zu ergänzen. Ich möchte auf Unterschiede in Bezug auf die Kopplung hinweisen.
Befehle sind an einen bestimmten Prozessor gerichtet. Somit besteht ein gewisses Maß an Abhängigkeit / Kopplung mit dem Befehlsinitiator und dem Prozessor.
Beispielsweise
UserService
sendet a beim Erstellen eines neuen Benutzers einen Befehl "E-Mail senden" anEmailService
.Die Tatsache, dass das
UserService
weiß, dass es das brauchtEmailService
, das koppelt schon. WennEmailService
das API-Schema geändert wird oder ausfällt, wirkt sich dies direkt auf dieUserService
Funktion aus.Ereignisse richten sich nicht an einen bestimmten Ereignishandler. Dadurch wird der Event-Publisher lose gekoppelt. Es ist egal, welcher Dienst seine Veranstaltung verbraucht. Es ist sogar gültig, 0 Verbraucher eines Ereignisses zu haben.
Beispielsweise veröffentlicht a
UserService
beim Erstellen eines neuen Benutzers ein "Benutzer erstelltes Ereignis". MöglicherweiseEmailService
kann ein Benutzer dieses Ereignis nutzen und eine E-Mail an den Benutzer senden.Hier
UserService
ist sich das nicht bewusstEmailService
. Sie sind völlig entkoppelt. Wenn dasEmailService
ausfällt oder Geschäftsregeln geändert werden, müssen wir nur das bearbeitenEmailService
Beide Ansätze haben Vorzüge. Ein rein ereignisgesteuertes Architekturdesign ist schwieriger zu verfolgen, da es insbesondere bei großen Systemen zu locker gekoppelt ist. Und eine befehlslastige Architektur weist ein hohes Maß an Kopplung auf. Eine gute Balance ist also ideal.
Hoffe das macht Sinn.
quelle