Ich möchte meine erste Anwendung mithilfe des CQRS-Musters zusammen mit Event Sourcing implementieren. Ich frage mich, wie die Erstellung aggregierter Wurzeln richtig gehandhabt werden sollte. Angenommen, jemand sendet den Befehl CreateItem. Wie soll damit umgegangen werden? Wo soll das Ereignis ItemCreated gespeichert werden? Als erstes Ereignis eines neuen Artikels? Oder sollte ich eine Art ItemList-Entität haben, die alle Elemente aggregiert und deren Ereignisliste nur aus ItemCreated-Ereignissen besteht?
Udi Dahan schlägt vor, keine aggregierten Wurzeln zu erstellen und stattdessen immer eine Art Abrufmethode zu verwenden. Aber wie kann ich etwas abrufen, das neu ist und dem sicherlich keine ID zugewiesen wurde? Ich verstehe die Idee dahinter und es ist ziemlich vernünftig zu glauben, dass ein neues Objekt ein Objekt ist, dessen Status aus null Ereignissen besteht, auf die geantwortet wurde. Aber wie soll ich es benutzen? Sollte ich eine bestimmte Methode in meinem Repository haben getNewItem()
oder meine get(id)
Methode Optional<ItemId>
stattdessen akzeptieren lassen ?
Bearbeiten: Nach einiger Zeit des Grabens fand ich eine wirklich interessante Implementierung der oben genannten Muster unter Verwendung von Schauspielern. Anstatt das Aggregat zu erstellen, ruft der Autor es aus einem Repository mit neu erstellter UUID ab. Der Nachteil dieses Ansatzes besteht darin, dass er einen vorübergehenden Inkonsistenzzustand zulässt. Ich frage mich auch, wie ich delete
mit einem solchen Ansatz eine Methode implementieren kann . Einfach Gelöschtes Ereignis zur Ereignisliste des Aggregats hinzufügen?
Antworten:
Die Idee in Udis Post ist, wie ich erfahre, dass keine Art von Gegenstand aus dem Nichts erscheint. Es gibt (fast) immer etwas oder genauer gesagt eine Domänenoperation, die dazu geführt hat, dass das Element erstellt wurde. Genau wie Udis Beispiel eines Benutzers, der tatsächlich aus einem Besucher geboren wurde, der sich auf der Website registriert. An diesem Punkt und in diesem begrenzten Kontext ist Besucher der aggregierte Stamm, der von seiner IP-Adresse abgerufen wird. Dieser Besucher erstellt dann das neue "Element", einen Benutzer zu diesem Zeitpunkt, über eine Domänenoperation namens Registrieren . Gleiches gilt für den vorherigen Schritt, bei dem es sich um einen weiteren begrenzten Kontext handelt: Referrer ist der AR, der von der URL abgerufen wird und über eine Domänenoperation namens BroughtVisitorWithIp verfügt , in der der Besucher geboren wird.
Udi schreibt auch sehr gut über das Löschen: http://www.udidahan.com/2009/09/01/dont-delete-just-dont/ . Die Hauptidee ist, dass Sie niemals etwas löschen. Dahinter steckt immer eine Domain-Operation, die wir erfassen möchten. Wie eine Bestellung, die storniert und nicht gelöscht wird. Lies es, es ist ein sehr guter Beitrag.
Der Hauptpunkt hier auf beiden Konten, DDD und insbesondere Event Sourcing, ist, dass Sie niemals reine CRUD-Operationen durchführen sollten. Wenn Sie sich in einer Situation befinden, in der Sie wirklich nur einige Daten einfügen, aktualisieren oder löschen müssen und wirklich keine Domänenoperation dahinter steckt, ist DDD und Event Sourcing möglicherweise nicht für diesen begrenzten Kontext geeignet . Sie können diese beiden nach Belieben kombinieren, solange ein einziger begrenzter Kontext einem Prinzip entspricht. Auf diese Weise kann der begrenzte Kontext im CRUD-Stil eine Zeile in der Datenbank erstellen, die zu einer Entität und einem Aggregatstamm in einem anderen begrenzten Kontext wird, in dem Sie jetzt den AR abrufen können und ihn nicht erstellen müssen.
quelle