2016-06-19 18 views
3

Welche Schicht sollte für das Überprüfen der Existenz einer Entität in der Datenbank verantwortlich sein? Nehmen wir an, ich habe einen Auftrag als Aggregat und dieser Auftrag kann mehrere Elemente enthalten. Logik bedeutet, dass ich nur existierende Artikel zur Bestellung hinzufügen kann.DDD-Child-Entity-Validierung

Sollte ich schreibe es so in der Anwendung Service:

var item = ItemRepository.GetByID(id); 

//throws exception if the item is null 
order.AddItem(item); 

oder

//validate item existence inside aggregate function 
order.AddItem(item, IItemRepository repo); 

Antwort

5

Weder, wirklich.

Einheiten überschreiten Aggregatgrenzen nicht. Entweder ist die Entität Teil des Aggregats, in diesem Fall verwaltet das Aggregat seinen eigenen Lebenszyklus, oder der Artikel ist Teil eines anderen Aggregats. In diesem Fall teilen Sie die Entität nicht, Sie teilen eine Referenz.

order.AddItem(id) 

Teil der Definition von Aggregat ist, dass Änderungen in verschiedenen Aggregaten unabhängig voneinander auftreten können. Mit anderen Worten, es gibt keine Möglichkeit, dass dieses Aggregat wissen kann, was in passiert, dass Aggregat "jetzt".

Mit anderen Worten, Sie können nicht gewährleisten, Transaktionskonsistenz über eine Aggregatgrenze.

Die richtige Antwort, wenn Sie bereit sind, ein Datenrennen zu akzeptieren, besteht darin, einen Domänenservice zu verwenden, um den Status außerhalb der Grenze abzufragen.

interface InventoryService{ 
    boolean currentlyInStock(Item id); 
} 

// ... 

order.addItem(id, inventoryService); 

Einige Punkte: einen Domain-Service verwenden eher als in der anderen Repository vorbei, weil er kommuniziert besser, was los ist. Der Domänenservice dient als Beschreibung des Vertrags, den das Aggregat tatsächlich benötigt. Wenn Sie sich weigern, das Repository weiterzugeben, schließen Sie außerdem die Möglichkeit aus, dass das Auftragsaggregat versucht, in das Nachrichten-Repository zu schreiben.

(Die triviale Implementierung dieses Domain-Service besteht darin, den Aufruf nur an das Repository weiterzuleiten, aber das Auftragsaggregat muss das nicht wissen). Der Domain-Service sollte in diesem Fall nicht "helfend" sein, indem er eine Aktion basierend auf der Verfügbarkeit des Inventars wählt - vielleicht sollte das Aggregat werfen, vielleicht sollte das Aggregat für niedrige Volumenaufträge/niedrig werfen Priority-Käufer, aber verwenden Sie andere Regeln, wenn die Bestellung über eine Million Dollar ist. Es ist der Auftrag des Auftrags, das herauszufinden, der Domain-Service liefert nur die Daten.

Angesichts des Datenrennens können einige Fehlalarme durchgehen; Erkennung und Minderung ist eine gute Idee.

Wenn Sie nicht bereit sind, das Datenrennen zu akzeptieren (sind Sie sicher? Amazon akzeptiert Bestellung für nicht mehr lieferbare Artikel die ganze Zeit ...), dann müssen Sie das Design Ihres Modells und wo Sie überdenken habe deine aggregierten Grenzen gesetzt.

Das Null-Design eines Modells besteht darin, den gesamten Geschäftszustand in einem einzigen Aggregat zu erfassen. sein eigener Zustand ist intern konsistent, aber möglicherweise nicht konsistent mit dem externen Zustand. Wenn Sie mit dem Zerlegen des Modells in separate Aggregate beginnen, machen Sie die gleiche Aussage - das Aggregat muss intern konsistent sein, aber es ist möglicherweise nicht konsistent mit dem Zustand außerhalb des Aggregats.

Wenn das nicht akzeptabel ist, dann drehen Sie das Bild von Mother an die Wand und implementieren Ihre Geschäftsregeln direkt im Buch des Datensatzes (dh Einschränkungen in Ihrem RDBMS).

+0

Also ist es vollkommen in Ordnung, Service so zu injizieren, um die notwendigen Kontrollen zu machen? – Robert

+1

Ich würde es vorziehen, eine ganze 'Item'-Instanz an die' add'-Methode zu übergeben. Es ist mehr auf die allgegenwärtige Sprache ausgerichtet und Sie erhalten die Item Existence-Prüfung kostenlos oder fast, da wir wahrscheinlich davon ausgehen können, dass niemand eine manuell aktualisierte "Item" -Instanz übergeben würde. Dann hält die 'Order' die ID intern fest. Es gibt auch Nachteile bei diesem Ansatz, aber bei DDD sollte die allgegenwärtige Sprache vorherrschen. – plalx