Behandlung von Fehlern nach der Validierung im Befehl (DDD + CQRS)

17

Zum Beispiel, wenn Sie ein Register Formular abgesendet hat , müssen Sie in der überprüfen Domain Model( WriteModelin CQRS) , dass es in einem gültigen Zustand (zB E - Mail - Adresse Syntax, Alter, etc.) ist.

Dann erstellen Sie eine Commandund senden sie an eine Command Bus.

Ich verstehe, dass Befehle nichts zurückgeben sollten.

Wie gehen Sie mit einem Fehler darüber hinaus um Command Bus? (Beispiel: Ein Benutzer hat sich 1 Sekunde zuvor bei demselben registriert username/email.)

Woher wissen Sie, dass dieser Befehl fehlgeschlagen ist, und woher wissen Sie, dass der Fehler aufgetreten ist?

JorgeeFG
quelle
2
Sie benötigen keinen Eventbus. Warum jeder denkt, dass Sie bei der Implementierung von CQRS einen Ereignisbus benötigen, weiß ich einfach nicht. CQRS bedeutet einfach, dass Sie Schreib- und Lesevorgänge vollständig voneinander trennen und die einzelnen Probleme lösen. Sie haben CQRS, solange Sie das tun. Ihre Befehle müssen nicht einmal asynchron sein. Wenn für Sie synchrone Befehle mit Fehlerberichten funktionieren, tun Sie dies.
Andy
1
Befehle sollten bei Erfolg nichts zurückgeben . Die Idee ging von CQS aus , was implizierte, dass der Befehl bei einem Fehler immer noch eine Ausnahme auslösen konnte. Was Sie beschreiben, ist ein Einwegbefehl. Siehe diese Antwort im Zusammenhang damit.
Kasey Speakman

Antworten:

3

Ich verstehe, dass Befehle nichts zurückgeben sollten.

Das ist eine Ansicht, aber nicht ganz in Stein gemeißelt. Erwägen Sie Schreibvorgänge (PUT, POST, DELETE) in HTTP. Alle diese Nachrichten sind Befehle in dem Sinne, dass es sich um Nachrichten handelt, die den Status der Ressourcenänderung anfordern, und dennoch alle Antworten zurückgeben.

Wie gehen Sie mit Fehlern jenseits des Command Bus um? (Beispiel: Ein Benutzer hat sich 1 Sekunde zuvor mit demselben Benutzernamen / derselben E-Mail-Adresse registriert.)

Woher wissen Sie, dass dieser Befehl fehlgeschlagen ist, und woher wissen Sie, dass der Fehler aufgetreten ist?

In einem Fall, in dem Sie direkt mit dem Befehlshandler kommunizieren, ist eine zurückgegebene Nachricht eine sehr vernünftige Methode, um zu bestätigen, dass der Befehl empfangen und verarbeitet wurde.

Wenn Sie eine Middleware wie einen Bus verwenden, die Sie daran hindert, direkt mit dem Ziel zu kommunizieren, sollten Sie asynchrone Messaging-Muster verwenden Anrufer?

Eine Idee ist, das Ergebnis des Befehls zu abonnieren. Dies basiert auf einigen Ideen in Hohpes Enterprise Integration Patterns. Die Grundidee ist, dass der Client, da er mit der gesendeten Befehlsnachricht vertraut ist, gut positioniert ist, um alle neuen Nachrichten zu abonnieren, die als Folge der Befehlsnachricht veröffentlicht wurden. Nachdem die Daten im Protokoll gespeichert wurden, veröffentlicht der Befehlshandler Ereignisse, die den Erfolg der Änderung anzeigen, und der Client abonniert diese Ereignisse. Er erkennt die richtigen Ereignisse, indem er die Übereinstimmung verschiedener Kennungen in der Nachricht berücksichtigt (Ursachen-ID, Korrelations-ID usw.).

Alternative Ansätze sind etwas direkter. Eine Möglichkeit wäre, einen Rückruf in die Nachricht aufzunehmen, der vom Befehlshandler aufgerufen werden kann, nachdem die Nachricht erfolgreich verarbeitet wurde.

Eine sehr ähnliche Alternative besteht darin, Platz in der Befehlsnachricht für den Befehlshandler zu reservieren, um die Bestätigung zu schreiben - da der Client die fragliche Befehlsnachricht bereits hat, ist die Schaltung bereits abgeschlossen. Denken Sie an " Versprechen " oder " abschließbare Zukunft". Die Nachricht teilt dem Befehlshandler mit, wo die Bestätigung geschrieben werden soll. dies signalisiert dem Client (Countdown-Latch), dass die Bestätigung verfügbar ist.

Und natürlich haben Sie die zusätzliche Möglichkeit, die Middleware zu entfernen, die Sie scheinbar daran hindert, einfach das Richtige zu tun.

Beispielsweise hat sich ein Benutzer 1 Sekunde zuvor mit demselben Benutzernamen / derselben E-Mail-Adresse registriert

Wenn Sie die Benutzerregistrierung idempotent handhaben, ist dies nicht unbedingt ein Fehler. Das Wiederholen von Nachrichten, bis eine Antwort beobachtet wird, ist eine übliche Methode, um mindestens eine Zustellung sicherzustellen.

VoiceOfUnreason
quelle
1

Wenn Sie beispielsweise ein Registrierungsformular senden, müssen Sie im Domänenmodell (WriteModel in CQRS) überprüfen, ob es einen gültigen Status aufweist (Beispiel: E-Mail-Adressensyntax, Alter usw.).

Es gibt viele Arten der Validierung. Die Überprüfung bei der Überprüfung der E-Mail-Adressensyntax und des Altersformats ist eine Art der Überprüfung, die ein Befehl durchführen kann. Dies ist kein wirkliches Domain-Problem. Es mag so aussehen, weil einige Domain-Experten Ihnen diese Spezifikationen mitteilen würden, aber Sie sollten diese Art der Validierung bei der Befehlserstellung durchführen. Tatsächlich besteht die allgemeine Idee darin, die Validierung so bald wie möglich durchzuführen, da es nach dem Erstellen eines Befehls und dem Senden an einen BUS komplizierter ist, Maßnahmen zu ergreifen.

Wie gehen Sie mit Fehlern jenseits des Command Bus um? (Beispiel: Ein Benutzer hat sich 1 Sekunde zuvor mit demselben Benutzernamen / derselben E-Mail-Adresse registriert.)

Diese Art der Validierung wird in der CQRS-Community seit Beginn von CQRS viel diskutiert. Wo kann man es machen? Es ist sehr umstritten. Ich persönlich gehe folgendermaßen vor: Bevor der Befehl an den BUS gesendet wird, markiere ich den Benutzernamen / die E-Mail als zentralisiert (dh eine eindeutige Indexbeschränkung für den Benutzernamen / die E-Mail). Danach sende ich den Befehl. Der Nachteil ist, dass, wenn der Befehl fehlschlägt, der Benutzername für einen kurzen Zeitraum vergeben und nicht verwendet wird. Dies ist akzeptabel für mein Geschäft, wahrscheinlich für Ihr Geschäft.

Woher wissen Sie, dass dieser Befehl fehlgeschlagen ist, und woher wissen Sie, dass der Fehler aufgetreten ist?

Wenn ein asynchroner Befehl vom Aggregat aufgrund einer Domäneninvariante zurückgewiesen wird, müssen einige Maßnahmen ergriffen werden, indem ein Ausgleichsbefehl ausgegeben wird, der den Herausgeber des Befehls auf irgendeine Weise benachrichtigt (dh eine Erklärungs-E-Mail sendet, dass der Befehl fehlgeschlagen ist).

Das Problem bei doppelten E-Mails ist, dass Sie keine E-Mails senden können, da diese E-Mail-Adresse einer anderen Person gehört. Deshalb überprüfe ich sie, bevor ich den Befehl an den Bus sende.

Constantin Galbenu
quelle
1

Die Validierung sollte in einem Dekorateur durchgeführt werden. Dann könnte jeder Befehl, der eine Validierung benötigt, als solcher dekoriert werden.

Validierungen können mit Ausnahmen behandelt werden, wenn Ihre Rückgabe mit Ihrem Befehl ungültig wird, sodass sie entweder mit Synchronisierungs- oder Asynchronisierungsaufrufen mit dem zurückgegebenen Aufgabenergebnis abgerufen werden können.

Eine andere Möglichkeit besteht darin, sich die Validierung als eine Art "Abfrage" vorzustellen, die ein Validierungsergebnis zurückgibt. Führen Sie die Überprüfungsabfrage aus, und führen Sie dann den Befehl aus, wenn Sie übergeben werden. Dies wäre eine Alternative zum Dekorateuransatz.

Jon Raynor
quelle
Ich mag den Ausnahmeansatz, weil er am saubersten ist. Aber sind Ausnahmen dafür nicht zu schwer?
EresDev
1
HI @EresDev - Ja, sie sind schwer. Aber ich weiß nicht, wie "gültig" Ihre Daten sind. Nehmen wir an, von 1000 Datensätzen sind 2 ungültig. Ausnahmen könnten durchaus machbar sein, da es sich um wirklich außergewöhnliche Bedingungen handelt. Betrachten Sie jetzt 1000 Datensätze mit 200 ungültigen Datensätzen. In diesem Fall sollten Ausnahmen vermieden werden, da 20% Ihrer Daten ungültig sind. Daher überlasse ich es Ihnen, zu entscheiden, ob Sie diesen Ansatz basierend auf Ihrer aktuellen Datengültigkeit wählen oder nicht. :)
Jon Raynor
Ich werde dem hinzufügen, indem ich sage, dass, wenn wir das Beispiel des Registrierungsformulars beibehalten, bei dem ich denke, dass 50% oder noch mehr Benutzer zuerst ungültige Daten einfügen, Ausnahmen immer noch in Ordnung sind. Im Webanwendungs-Backend erhalten Sie meist gültige Daten, da die Frontends auch eine Validierung durchführen. Sie erhalten nur, wenn etwas die Frontend-Validierung durch einen seltenen Zufall verpasst hat oder wenn jemand herumalbert. Ausnahmen sind in diesem Fall also in Ordnung.
EresDev