Wie kann festgestellt werden, ob eine Nachricht eine Befehlsnachricht oder eine Ereignismeldung sein soll?


11

Zwei Unternehmensintegrationsmuster sind die Befehlsnachricht und die Ereignismeldung . Ich arbeite an einem System, in dem wir Messaging nicht nur zur Integration in andere Systeme, sondern auch zur internen Kommunikation zwischen Diensten verwenden. Es soll ein letztendlich konsistentes System sein, und die Dienste sollen einander nicht kennen (mit Ausnahme einiger spezieller Dienste). Aus diesem Grund versuchen wir, Dinge zu vermeiden, die sich wie Remoteprozeduraufrufe (RPC oder RPI) anfühlen . Wir haben ein bus- und nachrichtenorientiertes Middleware-System, und alle Nachrichten werden gesendet.

Wir neigen dazu, unsere Botschaften als Ereignisse zu bezeichnen, dh als eine Phrase in der Vergangenheit, die perfekt ist, z PurchaseOrderShipped. Die Ereignisse werden jedoch häufig nur hinzugefügt, wenn einige andere Dienste über sie Bescheid wissen müssen, und am Anfang kümmert sich häufig nur ein Dienst darum. Darüber hinaus gibt dieser Dienst manchmal ein Ereignis aus, das vom ersten Dienst abgehört wird. Wenn ich also die Interaktion grafisch darstellen würde, würde sie dem Diagramm für die Befehlsnachricht im obigen Link (oder sogar dem RPC-Diagramm) viel ähnlicher sein als dem für die Ereignismeldung, obwohl dies wiederum nicht tatsächlich implementiert ist Direktnachrichten, aber auf einem Bus gesendet. Fügen Sie dazu die Tatsache hinzu, dass ich kürzlich einige Nachrichten gesehen habe, die als Befehle benannt wurden, dh eine Phrase im Imperativ, z BillShippedPurchaseOrder.

Das Seltsame ist, dass sich die Namen der Nachrichten und die Art und Weise, wie sie fließen, nicht dadurch ändern, ob sie als Ereignis oder als Befehl benannt werden. Wie kann man also bestimmen, ob etwas eine Befehlsnachricht oder ein Ereignis sein soll? Ist dies nur ein Unterschied zwischen Semantik und Benennung oder gibt es einen tatsächlichen Implementierungsunterschied zwischen Befehls- und Ereignismeldungen? Bedeutet das, dass alle unsere Nachrichten gesendet werden, dass keine von ihnen wirklich Befehlsnachrichten sind?

Antworten:


11

Es gibt einen subtilen, aber wichtigen Unterschied zwischen Befehlen und Ereignissen. Ein Befehl setzt eine Antwort voraus, während ein Ereignis keine Antwort voraussetzt, sondern lediglich eine Anweisung.

Um weniger abstrakt zu sein:

ShipOrderist ein Befehl und der Absender von ShipOrderwird wahrscheinlich eine Antwort erwarten.
OrderShippedist eine Erklärung, und es ist unwahrscheinlich, dass der Absender eine Antwort erwartet, ebenso GoodJob!wie eine nutzlose Antwort in diesem Beispiel.

Wenn Sie Ihre Systeme so gestalten, dass nur Ereignismeldungen erwartet werden, spielt es für das Systemdesign nicht unbedingt eine Rolle, wie Sie die Nachrichten nennen. Entwickler werden möglicherweise durch den Namen einer Nachricht verwirrt, aber die Systeme reagieren einwandfrei, unabhängig davon, mit welcher Konvention Sie die Dinge benennen.

Es hört sich jedoch nicht so an, als würden Ihre Entwicklerkollegen dem Nur-Ereignis-Nachrichtenmodell folgen. Wenn Dienste Antworten auf die von ihnen gesendeten "Ereignismeldungen" erwarten, senden sie tatsächlich Befehlsnachrichten aus. Es ist keine große Sache, und ich kann mir viele Fälle vorstellen, in denen Befehle wie Informationsanfragen erforderlich wären. Sie haben jedoch semantische Kopfschmerzen, wenn Sie nur Ereignismeldungen sehen möchten.

Das Senden von Nachrichten hat keinen wirklichen Einfluss darauf, ob eine Nachricht ein Befehl oder ein Ereignis ist. Im Allgemeinen senden Sie keine Befehle, da dies den Aufwand verdoppelt. Aber es gibt nichts zu sagen, was Sie nicht könnten. Frühe Netzwerkprotokolle sendeten jedes Paket und die Empfänger mussten intelligent genug sein, um zu wissen, wann sie es ignorieren solltenMitteilungen Pakete, die ihnen nicht gehörten.


Wie implementieren Sie request for informationFunktionen? Es scheint natürlich, so etwas wie getUserInfo(uid)eine Befehlsnachricht zu verwenden, die eine Antwort erwartet. Ich weiß, dass Befehlsnachrichten die Kopplung einführen, aber leider sehe ich in diesem Fall nicht, wie sie mit Ereignismeldungen implementiert werden sollen. Oder ist es in Ordnung, sich bei solchen Gelegenheiten an Befehlsnachrichten zu halten?
du369

@ du369 Sorry, aber ich folge deiner Frage nicht ganz. Es hört sich so an, als würden Sie versuchen, einen Befehl zu erstellen, aber Ereignisse verwenden?

Ja, so ziemlich das. In dem Link in Lees Antwort wird dieselbe Funktionalität auf zwei verschiedene Arten implementiert. Einer verwendet eine CancelPolicyRequestNachricht, die ein Befehl ist. Der andere Ansatz verwendet zwei Ereignismeldungen, nämlich InvoicePastDueNotificationund PolicyCancelledNotification. Ich frage mich also, ob es möglich ist, Befehle wie getUserInfo(uid)den Stil von Ereignismeldungen zu ändern und wie ich das tun soll.
du369

1
@ du369 Irgendwas muss irgendwo den Actionmit dem Befehl verbundenen ausführen . Einem Befehl sind zwei Schritte zugeordnet. 1) Wird der Befehl benötigt (z. B. Richtlinie abgelaufen) und 2) Führen Sie den Befehl aus (z. B. Abbrechen der Richtlinie). Wenn das Actorbestimmt, ob der Befehl benötigt wird UND ausgeführt werden kann, kann es ActorEreignismeldungen senden. Andernfalls ist zum Senden eines Befehlsereignisses alles erforderlich, was bestimmt, dass der Befehl benötigt wird.

5

Eine Ereignismeldung ist gerade passiert. Sie benachrichtigen über das gerade eingetretene Ereignis.

Eine Befehlsnachricht ist eine Nachricht, die erwartet, dass etwas getan wird. Es kann eine Antwort erwarten oder nicht.

Wann zu verwenden ist, worauf es bei der Kopplung ankommt, und der Unterschied wird sich erst im Laufe der Zeit ergeben, wenn sich die Systeme weiterentwickeln. Das Bevorzugen von Ereignissen gegenüber Befehlen führt zu einer geringeren Kopplung. Der Veranstalter kümmert sich nicht um den Verbraucher. In einem Befehlsmuster kennt der Anrufer die Existenz des Anbieters und ist daher von dieser abhängig.

Bill Poole schlägt vor, Befehlsnachrichten insgesamt zu vermeiden: http://bill-poole.blogspot.com.au/2008/04/avoid-command-messages.html

http://bill-poole.blogspot.com.au/


Lee, danke für deine Antwort, aber ich verstehe die Theorie hinter der Definition von jedem. Meine Frage ist, wie man dies im wirklichen Leben anwendet - wann man benachrichtigt, dass etwas passiert ist, was oft dazu führt, dass etwas getan wird, und wann man verlangt, dass etwas getan wird.
Kazark

Ich denke, es kommt auf die Kopplung an und der Unterschied wird sich erst im Laufe der Zeit ergeben, wenn sich die Systeme weiterentwickeln. Das Bevorzugen von Ereignissen gegenüber Befehlen führt zu einer geringeren Kopplung. Der Veranstalter kümmert sich nicht um den Verbraucher. In einem Befehlsmuster kennt der Anrufer die Existenz des Anbieters und ist daher von dieser abhängig. Haben Sie die Artikel von Bill Poole gelesen?
Lee Simpson

Lee, danke, das ist hilfreich. Tatsächlich schlage ich vor, dass Sie den Inhalt Ihres Kommentars in Ihrer Antwort bearbeiten, einschließlich eines Links zu den Poole-Artikeln (von denen ich nicht sicher bin, ob ich sie gelesen habe).
Kazark
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.