Szenario:
Ein Kunde gibt eine Bestellung auf und gibt nach Erhalt des Produkts eine Rückmeldung zum Bestellvorgang.
Nehmen Sie die folgenden aggregierten Wurzeln an:
- Kunde
- Auftrag
- Feedback
Hier sind die Geschäftsregeln:
- Ein Kunde kann nur Feedback zu seiner eigenen Bestellung geben, nicht zu der eines anderen.
Ein Kunde kann nur dann eine Rückmeldung geben, wenn die Bestellung bezahlt wurde.
class Feedback { public function __construct($feedbackId, Customer $customer, Order $order, $content) { if ($customer->customerId() != $order->customerId()) { // Error } if (!$order->isPaid()) { // Error } $this->feedbackId = $feedbackId; $this->customerId = $customerId; $this->orderId = $orderId; $this->content = $content; } }
Nehmen wir nun an, das Unternehmen möchte eine neue Regel:
Ein Kunde kann nur dann eine Rückmeldung geben, wenn die
Supplier
Ware der Bestellung noch in Betrieb ist.class Feedback { public function __construct($feedbackId, Customer $customer, Order $order, Supplier $supplier, $content) { if ($customer->customerId() != $order->customerId()) { // Error } if (!$order->isPaid()) { // Error } // NEW RULE HERE if (!$supplier->isOperating()) { // Error } $this->feedbackId = $feedbackId; $this->customerId = $customerId; $this->orderId = $orderId; $this->content = $content; } }
Ich habe die Implementierung der ersten beiden Regeln im Feedback
Aggregat selbst platziert. Ich fühle mich wohl dabei, insbesondere angesichts der Feedback
Tatsache , dass das
Aggregat alle anderen Aggregate nach Identität referenziert. Zum Beispiel zeigen die Eigenschaften der Feedback
Komponente an, dass sie von der Existenz der anderen Aggregate weiß
, daher fühle ich mich wohl, wenn sie auch den schreibgeschützten Zustand dieser Aggregate kennt .
Aufgrund seiner Eigenschaften hat das Feedback
Aggregat jedoch keine Kenntnis von der Existenz des
Supplier
Aggregats. Sollte es also Kenntnis vom schreibgeschützten Zustand dieses Aggregats haben?
Die alternative Lösung zur Implementierung von Regel 3 besteht darin, diese Logik an die entsprechende Stelle zu verschieben CommandHandler
. Dies scheint jedoch die Domänenlogik vom "Zentrum" meiner zwiebelbasierten Architektur zu entfernen.
Supplier
würde der Betriebszustand eines Aggregats nicht über ein Order
Repository abgefragt . Supplier
und Order
sind zwei separate Aggregate. Zweitens gab es in der DDD / CQRS-Mailingliste eine Frage zum Übergeben von aggregierten Roots und Repositorys an andere aggregierte Root-Methoden (einschließlich des Konstruktors). Es gab verschiedene Meinungen, aber Greg Young erwähnte, dass es üblich ist, aggregierte Wurzeln als Parameter zu übergeben, während eine andere Person sagte, dass Repositories enger mit der Infrastruktur als mit der Domäne verbunden sind. ZB Repositorys "abstrakt in Speichersammlungen" und haben keine Logik.
Customer
nur zu einer eigenen Bestellung Feedback geben kann ( $order->customerId() == $customer->customerId()
), müssen wir auch die Lieferanten-ID ( $order->supplierId() == $supplier->supplierId()
) vergleichen. Die erste Regel schützt vor dem Benutzer, der falsche Werte angibt. Die zweite Regel schützt vor dem Programmierer, der falsche Werte liefert. Die Prüfung, ob der Lieferant tätig ist, muss jedoch entweder in der Feedback
Entität oder im Befehlshandler erfolgen. Wo ist die Frage?