2016-06-06 1 views
10

In DDD lädt ein Repository ein ganzes Aggregat - wir laden entweder alles oder nichts davon. Dies bedeutet auch, dass Lazy Loading vermieden werden sollte.DDD: Muss ich wirklich alle Objekte in einem Aggregat laden? (Leistungsbedenken)

Mein Anliegen ist die Leistung. Was passiert, wenn Tausende von Objekten in den Speicher geladen werden? Zum Beispiel kommt ein Aggregat für Customer mit zehntausend Orders zurück.

Kann es in solchen Fällen bedeuten, dass ich meine Aggregate neu gestalten und überdenken muss? Bietet DDD Vorschläge zu diesem Thema?

+2

Wenn Ihr 'Customer' Aggregat enthält zehntausend' Order' Objekte zu finden, die Chancen sind 'Order' ist ein Aggregat für sich. – theDmi

+1

[Diese Antwort von mir] (http://Stackoverflow.com/a/31585706/219187) fasst die primären Designtreiber für Aggregate zusammen. – theDmi

+0

Sie können Ihre begrenzten Kontexte auch neu denken. –

Antwort

12

Werfen Sie einen Blick auf diese Effective Aggregate Design Serie von drei Artikeln aus Vernon. Ich fand sie ziemlich nützlich, um zu verstehen, wann und wie man kleinere Aggregate als ein Aggregat mit großem Cluster entwerfen kann.

EDIT

Ich möchte ein paar Beispiele geben, meine Antwort zu verbessern, können Sie Ihre Gedanken über sie zu teilen.

Zuerst wird eine schnelle Definition über ein Aggregat (entnahm Muster, Prinzipien und Praktiken der Domain Entwurf Buch von Scott Millet Driven)

Entitäten und Wertobjekte zusammenarbeiten komplexe Beziehungen zu bilden, die Invarianten treffen innerhalb das Domänenmodell. Bei großen zusammenhängenden Zuordnungen von Objekten ist es häufig schwierig, Konsistenz und Gleichzeitigkeit sicherzustellen, wenn Aktionen für Domänenobjekte ausgeführt werden. Domänengesteuertes Design verfügt über das Aggregatmuster, um die Konsistenz zu gewährleisten und transaktionale Parallelitätsgrenzen für Objektdiagramme zu definieren. Große Modelle werden durch Invarianten geteilt und in Aggregate von Entitäten und Wertobjekten gruppiert, die als konzeptionelles Ganzes behandelt werden.

Lassen Sie uns mit einem Beispiel gehen, um die Definition in der Praxis zu sehen.

Einfaches Beispiel

Das erste Beispiel zeigt, wie die Definition ein Aggregat Wurzel hilft Konsistenz sicherzustellen, wenn Maßnahmen gegen Domain-Objekten durchführen.

das nächste Geschäftsregel Gegeben:

Gewinnen Auktion Gebote müssen immer gesetzt werden, bevor die Auktion endet. Wenn nach dem Ende einer Auktion ein erfolgreiches Gebot abgegeben wird, befindet sich die Domäne in einem ungültigen Status, da eine Invariante unterbrochen wurde und das Modell Domänenregeln nicht ordnungsgemäß anwenden konnte.

Hier gibt es ein Aggregat, bestehend aus Auktion und Gebote, wobei die Auktion die Aggregatwurzel ist.

Wenn wir sagen, dass Bid auch ein getrenntes Aggregat Root ist man hätte ein , und Sie leicht tun könnten:

var newBid = new Bid(money); 
BidsRepository->save(auctionId, newBid); 

Und Sie ohne das Bestehen der definierten Geschäftsregeln eine Bid sparen. Um jedoch die Auktion als einziges Aggregat Wurzel Sie Ihr Design erzwingen, weil man so etwas tun müssen:

var newBid = new Bid(money); 
auction.placeBid(newBid); 
auctionRepository.save(auction); 

Daher können Sie Ihre invariant innerhalb der Methode überprüfen placeBid und niemand kann es überspringen, wenn sie wollen Platziere ein neues Gebot.

Hier ist es ziemlich klar, dass der Zustand eines Gebots vom Zustand einer Auktion abhängt.

Komplex Beispiel

Zurück zu Ihrem Beispiel von Aufträgen an einem Kunden zugeordnet ist, sehen aus wie es nicht Invarianten ist, die wir eine riesige Summe machen definieren einen Kunden aus und all ihre Aufträge, können wir nur halten die Beziehung zwischen beiden Entitäten durch eine Bezeichnerreferenz. Dadurch vermeiden wir, dass alle Bestellungen geladen werden, wenn ein Kunde abgeholt wird, und wir vermeiden Nebenläufigkeitsprobleme.

aber sagen, dass nun Unternehmen die nächsten invariant definiert:

Wir wollen Kunden mit einer Tasche zur Verfügung zu stellen, damit sie es mit Geld, Produkte zu kaufen aufladen können. Wenn ein Kunde nun ein Produkt kaufen möchte, muss es daher genug Geld haben, um es zu machen.

Gesagt, Tasche ist ein VO innerhalb der Customer-Aggregat-Root. Es scheint jetzt, dass zwei getrennte Aggregatwurzeln, eine für Kunden und eine andere für Ordnung, nicht die beste ist, um die neue Invariante zu erfüllen, da wir eine neue Reihenfolge speichern könnten, ohne die Regel zu überprüfen. Sieht so aus, als müssten wir den Kunden als Wurzel betrachten. Das hat Auswirkungen auf unsere Leistung, Skalierbarkeit und Nebenläufigkeitsprobleme usw.

Lösung? Eventuelle Konsistenz. Was ist, wenn wir dem Kunden erlauben, das Produkt zu kaufen? Das heißt, ein Aggregat Root für Aufträge, die so schaffen wir den Auftrag und speichern Sie es:

var newOrder = new Order(customerId, ...); 
orderRepository.save(newOrder); 

veröffentlichen wir ein Ereignis, wenn der Auftrag erstellt wird und dann überprüfen wir asynchron, wenn der Kunde genügend Mittel hat:

class OrderWasCreatedListener: 
    var customer = customerRepository.findOfId(event.customerId); 
    var order = orderRepository.findOfId(event.orderId); 
    customer.placeOrder(order); //Check business rules 
    customerRepository.save(customer); 

Wenn alles gut war, haben wir unsere Invarianten erfüllt, während wir am Anfang unser Design beibehalten haben, indem wir nur eine Aggregatwurzel pro Anfrage geändert haben. Andernfalls senden wir eine E-Mail an den Kunden, in der er sie über das unzureichende Geldmittel informiert.Wir können davon profitieren, indem wir zu den E-Mail-Alternativen Optionen hinzufügen, die sie mit ihrem aktuellen Budget kaufen und sie ermutigen kann, die Tasche zu belasten.

Berücksichtigen Sie, dass die Benutzeroberfläche uns helfen kann, Kunden zu vermeiden, die ohne genügend Geld bezahlen, aber wir können nicht blind auf die Benutzeroberfläche vertrauen.

Hoffe, dass Sie beide Beispiele nützlich finden, und lassen Sie mich wissen, wenn Sie bessere Lösungen für die belichteten Szenarien :-)

+1

Vielen Dank für Ihre Mühe, dies mir zu erklären. Ich war gezwungen, Ihnen die Antwort zu geben. Vielen Dank! – user11081980

10

Kann es in solchen Fällen bedeuten, dass ich meine Aggregate neu entwerfen und überdenken muss?

Fast sicher.

Der Treiber für Aggregatentwurf ist nicht Struktur, sondern Verhalten. Es ist uns egal, dass "ein Benutzer Tausende von Bestellungen hat". Was uns interessiert, ist, welche Teile des Zustands überprüft werden müssen, wenn Sie versuchen, eine Änderung zu verarbeiten - welche Daten müssen Sie laden, um zu wissen, ob eine Änderung gültig ist.

Normalerweise werden Sie feststellen, dass das Ändern einer Bestellung nicht vom Zustand anderer Bestellungen im System abhängt (oder nicht), was ein guter Hinweis darauf ist, dass zwei verschiedene Bestellungen nicht Teil davon sein sollten das gleiche Aggregat.

Verwandte Themen