Ich bin ziemlich neu in der DDD-Welt und nachdem ich ein paar Bücher darüber gelesen habe (Evans DDD unter ihnen), konnte ich keine Antwort auf meine Frage im Internet finden: Was ist der richtige Weg, um Kind-Entitäten mit DDD zu erstellen? Sie sehen, viele Informationen im Internet funktionieren auf einer einfachen Ebene. Aber Teufel in den Details und sie sind aus Gründen der Einfachheit immer in Dutzenden von DDD-Proben weggelassen.
Ich komme aus mein eigenes Antwort auf Similair Frage hier auf Stackoverflow. Ich bin nicht vollständig mit meiner eigenen Vision zu diesem Problem zufrieden, also dachte ich, ich müsste etwas näher ausführen.
Zum Beispiel muss ich ein einfaches Modell erstellen, das die Namen der Autos repräsentiert: Firma, Modell und Modifikation (zum Beispiel Nissan Teana 2012 - das wird "Nissan", "Teana" -Modell und "2012" -Modifikation).
Die Skizze des Modells, das ich erstellen möchte, sieht folgendermaßen aus:
%Vor%Also, jetzt muss ich Code erstellen. Ich verwende C # als Sprache und NHibernate als ORM. Dies ist wichtig und wird normalerweise nicht in umfangreichen DDD-Beispielen im Internet angezeigt.
Der erste Ansatz.
Ich beginne mit einem einfachen Ansatz mit typischer Objekterstellung über Factory-Methoden.
%Vor%Das Schlechte an diesem Ansatz ist, dass die Erstellung des Modells es nicht zur übergeordneten Modellsammlung hinzufügt:
%Vor%Nachdem die Transaktion festgeschrieben wurde und die Sitzung geleert wurde, schreibt das ORM alle korrekt in die Datenbank und das nächste Mal, wenn wir diese Firma laden, wird das Modell von unserer Modellsammlung korrekt gehalten. Das Gleiche gilt für die Modifikation. Bei diesem Ansatz bleibt unsere übergeordnete Entität in einem inkonsistenten Zustand, bis sie von der Datenbank neu geladen wird. Nicht gehen.
Der zweite Ansatz.
Dieses Mal werden wir die sprachspezifische Option verwenden, um das Problem der Einstellung geschützter Eigenschaften anderer Klassen zu lösen. Wir werden nämlich den Modifier "protected internal" für Setter und Konstruktor verwenden.
%Vor% Diesmal belässt jede Entitätserstellung sowohl die übergeordnete als auch die untergeordnete Entität im konsistenten Zustand. Die Validierung des untergeordneten Entitätsstatus erfolgte jedoch in die übergeordnete Entität ( AddModel
und AddModification
Methoden). Da ich kein DDD-Experte bin, bin ich mir nicht sicher, ob es in Ordnung ist oder nicht. Es könnte in Zukunft weitere Probleme verursachen, wenn untergeordnete Entitätseigenschaften nicht einfach über Eigenschaften festgelegt werden könnten und das Einrichten eines Zustands basierend auf übergebenen Parametern eine komplexere Arbeit erfordern würde, die der Eigenschaft den Parameterwert zuweist. Ich hatte den Eindruck, dass wir die Logik der Entität in dieser Entität konzentrieren sollten, wo immer es möglich ist. Für mich verwandelt dieser Ansatz Elternobjekt in eine Art Entity & amp; Factory Hybrid.
Der dritte Ansatz.
Ok, wir werden die Verantwortlichkeiten für die Pflege der Eltern-Kind-Beziehungen umkehren.
%Vor%Dieser Ansatz hat alle Validierungs- / Erzeugungslogiken in entsprechenden Entitäten und ich weiß nicht, ob sie gut oder schlecht sind, aber durch einfaches Erstellen des Objekts mit der Factory-Methode fügen wir sie implizit zur übergeordneten Objekt-Child-Sammlung hinzu. Nach dem Transaktions-Commit und dem Session-Flush gibt es 3 Einfügungen in die Datenbank, obwohl ich noch nie einen "add" -Befehl in meinen Code geschrieben habe. Ich weiß nicht, vielleicht sind es nur ich und meine große Erfahrung außerhalb der DDD-Welt, aber im Moment fühlt es sich ein wenig unnatürlich an.
Was ist die korrekteste Methode zum Hinzufügen von untergeordneten Objekten mit DDD?
Ich habe eine akzeptable Antwort hier: Ссылка
Grundsätzlich ist es eine Kombination aus Methode 2 und 3 - fügen Sie die AddModel-Methode in die CarsCompany ein und rufen Sie den geschützten internen Konstruktor des CarsModel mit dem Namensparameter auf, der im Konstruktor von CarsModel validiert wird.
Hier ist eine sehr konkrete und bittlich ehrliche Antwort: alle Ihre Ansätze sind falsch, weil Sie die "erste Regel" von DDD gebrochen haben, das heißt, die DB existiert nicht.
Was Sie definieren, ist das PERSISTENCE-Modell für ein ORM (nhibernate). Um die Domänenobjekte zu entwerfen, müssen Sie zuerst die Begrenzter Kontext , sein Modell, die Entitäten und Wertobjekte für dieses Modell und die Aggregate Root (die sich intern mit den Regeln für Kinder und Unternehmen befasst).
Nhibernate oder db Schema haben hier keinen Platz, Sie brauchen nur reinen C # Code und ein klares Verständnis der Domäne.
Also, was ist die korrekteste Art, untergeordnete Objekte mit DDD hinzuzufügen?
Der dritte Ansatz heißt Tight Coupling . Company
, Car
und Modification
wissen fast alles über einander.
Der zweite Ansatz wird in DDD weithin vorgeschlagen. Ein Domänenobjekt ist dafür verantwortlich, ein geschachteltes Domänenobjekt zu erstellen und es darin zu registrieren.
Der erste Ansatz ist der klassische OOP-Stil. Die Erstellung eines Objekts wird vom Hinzufügen eines Objekts in eine Sammlung getrennt. Auf diese Weise kann der Code-Verbraucher ein Objekt einer konkreten Klasse (z. B. Auto) durch ein Objekt einer abgeleiteten Klasse (z. B. TrailerCar) ersetzen.
%Vor%Versuchen Sie, diese Geschäftslogikänderung im 2./3. Ansatz zu übernehmen.
Interessant. DDD vs Repository / ORM Navigationseigenschaften. Ich denke, die Antwort hängt davon ab, ob Sie mit einem Aggregat oder zwei arbeiten. Sollte CarsModel Teil des CarsCompany-Aggregats sein oder vielleicht sein eigenes Aggregat?
Ansatz eins ist, das Problem verschwinden zu lassen. MikeSW deutete darauf hin. Wenn CarsCompany und CarsModel nicht Teil desselben Aggregats sein müssen, sollten sie sich gegenseitig nur durch Identität referenzieren, Navigationseigenschaften sollten in der Domain nicht sichtbar sein.
Ansatz zwei ist das Behandeln des Hinzufügens zu einer Beziehung auf die gleiche Weise wie das Abrufen eines Aggregats. Lassen Sie die Anwendungsdienste eine Methode aus dem Repository aufrufen, die für Ihre ORM-spezifischen Probleme geeignet ist. Eine solche Methode könnte beide Enden der Beziehung füllen.
Tags und Links c# parent-child nhibernate domain-driven-design