2009-08-26 3 views
5

Zweiteilige FragenDDD principlers und ASP.NET MVC-Projekt Design

ich ein Produkt Aggregat haben, hat;

Preise PackagingOptions Product Produktbilder etc

ich ein Produkt Repository modelliert haben und erstellen Sie nicht einzelne Repositories für eine der untergeordneten Klassen. Alle db-Vorgänge werden über das Produkt-Repository abgewickelt.

Verstehe ich das DDD-Konzept bis jetzt richtig? Manchmal kommt mir die Frage in den Sinn, dass ein Repositorium, sagen wir, Verpackungsoptionen, mein Leben einfacher machen könnte, indem man eine Verpackungsoption direkt aus der DB mit Hilfe seiner ID holt, anstatt das Produkt-Repository nach seiner PackagingOptions-Sammlung zu fragen es mir ..

Zweiter Teil der Bearbeitung ist die Verwaltung erstellen Operationen ASP.MVC Rahmen der Arbeit

ich bin derzeit versucht, mit allen bearbeiten Entfernen dieser untergeordneten Sammlungen von Produkt durch Produkt-Controller hinzufügen zu verwalten (Ton richtig?).

Eine Herausforderung, der ich jetzt gegenüberstehe, ist;

Wenn ich eine bestimmte Verpackung Option des Produkts durch

mydomain/product/editpackagingoption/10 bearbeiten

Ich habe Zugriff auf die ID der Verpackung Option

Aber ich habe nicht die ID des Produkts selbst und dies zwingt mich, eine Anfrage zu schreiben, um zuerst das Produkt zu finden, das diese spezielle Verpackungsoption hat, und dann dieses Produkt und die Verpackungsoption zu bearbeiten. Ich kann dies tun, da alle Verpackungsoptionen ihre eindeutige ID haben, aber dies würde fehlschlagen, wenn ich Sammlungen habe, die keine eindeutige ID haben.

Das ist sehr falsch anfühlt ..

Die nächste Option, die ich gedacht wird auf die URL sowohl die Produkt- und Verpackungsoption IDs zu senden dergleichen;

mydomain/product/editpackagingoption/3/10

Aber ich bin nicht sicher, ob das entweder ein gutes Design ist.

So bin ich an einem Punkt, dass ich ein bisschen verwirrt bin. könnte grundlegende Missverständnisse um all dies haben ...

Ich würde mich freuen, wenn Sie mit der langen Frage ertragen und mir helfen, dies zusammen zu setzen. Vielen Dank!

+0

Gute Frage. Ich kann es nicht beantworten, aber auf den Punkt, dass ich die Produkt-ID nicht habe, ist das wichtig? Wenn es ein Eins-zu-eins ist, dann sollte die PackingOption vielleicht eine eigene ProductID haben? – jeef3

+0

Es hat eine Product-ID, die in der Datenbank beibehalten wird. Herausforderung ist, wie ich dorthin komme, ohne ein PackagingOption-Repository zu haben. – kaivalya

Antwort

3

In meinen Augen ist dies eines dieser schlammigen Dinge, die in DDD erscheint.

Im Code behandle ich einen Aggregatstamm als Container für alle "Beziehungen", die er hat, und alle Entitätsobjekte, die ohne den Aggregatstamm nicht existieren können.

Nehmen wir zum Beispiel das Customer-> Order-> LineItem-> Product-Beispiel, das bis jetzt totgeschlagen wurde. Der aggregierte Stamm, wie ich ihn angezeigt habe, ist in diesem Szenario Kunde. Das heißt, Sie wollen nicht immer durch den Kunden zur Bestellung kommen.Vielleicht möchten Sie Bestellungen an einem bestimmten Datum finden.

Wenn Sie es einschalten, haben Sie auch keinen Kunden, der keine Bestellung hat. Die beiden sind in einer etwas symbiotischen Beziehung, so dass man nicht die gesamte Wurzel des anderen ist.

Der Punkt ist, dass Sie nicht möchten, einen Kunden durch eine Bestellung zu laden, aber Sie möchten nicht unbedingt eine Bestellung über den Kunden auch nicht laden.

Ab Bestellung ist es jedoch unwahrscheinlich, dass Sie nur ein LineItem abrufen möchten und Sie werden sicherlich nicht ohne eine Bestellung erstellen. Zu diesem Zweck dient der Auftrag als Gateway zu LineItems. LineItems benötigen keinen eigenen Controller oder Repository. Sie existieren nur innerhalb der Order selbst und sind als solche Teil der Order (in diesem Fall wird Order zur aggregierten Wurzel) und von der Order Entity verwaltet.

Aber ein LineItem hätte wahrscheinlich eine Beziehung zu einem Produkt innerhalb des Systems. Produkte würden ihre eigenen Controller, Repositories usw. haben, da sie außerhalb des Aggregatstammverzeichnisses existieren können.

Zusammenfassend zu meinem Wandern, neige ich dazu, es auf diese Weise zu betrachten: Wenn eine Entität von selbst existieren kann, sollte sie einen Controller haben. Entitäten, die nicht alleine existieren können (LineItems in diesem Fall), sollten nur von ihrem Container (aggregierter Root) verwaltet werden.

Werden einige DDD puristische bitte korrigieren Sie mich, wenn/wo ich falsch?

Was den zweiten Teil Ihrer Frage betrifft, würde ich mehr Details darüber benötigen, wie Sie sich vorstellen, dass diese anderen Entitäten funktionieren. Mit dem, was Sie hier gesagt haben, würde ich mir vorstellen, dass PackagingOptions mit einem Produkt in Verbindung stehen und Teil eines Produktgesamtstamms sein würden. Wenn Sie nun angeben, dass Sie sie bearbeiten, stellt sich die Frage, ob es sich um eine Nachschlagetabelle im System handelt oder ob es sich um einmalige Werte handelt, die als Wertobjekte behandelt werden sollten.

+0

Danke für Ihre Antwort. Es hört sich an, als wären wir auf der gleichen Seite, bis ich mich selbst zu einer radikaleren Herangehensweise gebracht habe, um Wurzeln zu sammeln, die all diese Fragen aufgeworfen haben. In Bezug auf deine Frage; packagingoption Ich denke, es sollten Wertobjekte sein, ich werde es nochmal untersuchen. Aber meine Frage bleibt, wie man Szenarien für die Entitäten eines aggregierten root bearbeitet, wo ich dem Controller die ID der untergeordneten Entität übergebe und es dem aggregierten Controller obliegt, den Rest zu verarbeiten - ich schwinge irgendwie mit dem Senden der beiden Aggregat-ID und Kind-ID für diese Fälle, aber immer noch fühlt sich unordentlich – kaivalya

+0

Ich würde argumentieren, dass, wenn eine Kind-Entität eine ID hat und diese Entität bearbeitet werden muss, garantiert es seinen eigenen Controller. Um die Elternbeziehung zu erhalten, wenn sie 1: 1 ist, dann speichere die Eltern-ID mit dem Kind und schnappe sie einfach, aber das Elternteil zu speichern, um ein Kind zu ändern, das seine eigene ID hat, ist ein wenig unangenehm für mich. Wenn Sie das Objekt selbst bearbeiten, bearbeiten Sie das Aggregat nicht und Sie haben etwas, das eigenständig stehen kann. Es scheint mir, als ob Sie das Produkt bearbeiten möchten, indem Sie eine Bestellung laden und das wird nicht funktionieren. Außerdem haben Wertobjekte keine Identität - nun, normalerweise. – andymeadows

+0

Siehe http://devlicio.us/blogs/casey/archive/2009/02/13/ddd-entities-and-value-objects.aspx als Ausgangspunkt für eine Diskussion über Entitäten und Wertobjekte. – andymeadows

1

Kaivalya,

Bezüglich Ihrer letzten Kommentar (stateless http):

Es hängt vom Kontext ab. Bevor ich auf die Details eingehe, sollte ich Ihnen ein grundlegendes Prinzip zu Aggregaten geben:

Aggregate definieren eine Gruppe verwandter Objekte, die zum Zweck der Datenänderung als eine Einheit behandelt werden sollen.

Dies ist äußerst wichtig. Der Zweck von Aggregaten besteht darin, Invarianten zu erzwingen. Beispielsweise haben Sie möglicherweise eine Richtlinie wie "Eine Bestellung kann 500 $ nicht überschreiten". Um diese Richtlinie durchzusetzen, fügen Sie Order und OrderItem dann im Order-Aggregat zusammen. Auf diese Weise sollte jedes Mal, wenn Sie ein neues OrderItem hinzufügen, dieses über das Order-Objekt hinzugefügt werden. Dort können Sie den Gesamtpreis überprüfen und sicherstellen, dass er 500 $ nicht überschreitet. Wenn Sie in Ihrer Domäne keine solchen Invarianten haben, ist es nicht sinnvoll, alle diese Objekte zusammen zu laden.

Nun, um Ihren Kommentar immer wieder:

Wenn Sie Invarianten tun haben, die erzwungen werden sollen, dann ist es in Ordnung, das gesamte Aggregat zu laden, obwohl es einigen Aufwand hat. Ja, HTTP ist zustandslos und Sie laden Ihr gesamtes Aggregat nur, um eines seiner untergeordneten Objekte zu ändern und es dann zu löschen. Das ist in Ordnung. Was am wichtigsten ist, ist, dass Sie Ihre Invarianten durchsetzen. Dafür ist DDD da.

Der Zweck DDD ist es, alle Geschäftslogik in Ihrer Domain zu erfassen.Sie könnten definitiv eine bessere Leistung erzielen, wenn Sie nicht das gesamte Aggregat laden müssten, aber wie würden Sie Ihre Invarianten erzwingen? Sie müssen es wahrscheinlich in Ihrer gespeicherten Prozedur tun. Ja, es funktioniert, und es ist schnell, aber der Umgang mit Geschäftslogik in gespeicherten Prozeduren während der Wartung ist ein Albtraum. Aus diesem Grund hat sich DDD weiterentwickelt. So können Sie Ihre Geschäftsanforderungen mithilfe objektorientierter Sprachen/Tools modellieren, sodass sie leichter zu verstehen und zu ändern sind.

Denken Sie daran, DDD ist ein großartiger Ansatz, aber nicht für alle Arten von Projekten. Wenn Sie mit einem Projekt zu tun haben, in dem es viele Geschäftslogiken gibt und die Chancen, dass sie sich aufgrund der Art eines Unternehmens ändern, hoch sind, sollten Sie DDD verwenden. Wenn Ihr Projekt jedoch eher "etwas lesen/etwas schreiben" ist, ohne dass viel Geschäftslogik involviert ist, ist die Verwendung von DDD ein Kopfzerbrechen. Sie können einfach LINQ to SQL (oder SqlDataAdapters) verwenden und Ihre Objekte an Ihre Ansichten senden. Sie müssen nicht einmal über die Suche nach Entitäten Sorge, Wert Objekte, Aggregate, Repositorys usw.

hoffe, das hilft,

Mosh