Ich überarbeite derzeit Code für ein Projekt, das gerade fertiggestellt wird, und habe schließlich viel Geschäftslogik in Serviceklassen und nicht in die Domänenobjekte eingefügt. Zu diesem Zeitpunkt sind die meisten Domänenobjekte nur Datencontainer. Ich hatte beschlossen, den Großteil der Geschäftslogik in Serviceobjekte zu schreiben und alles danach in bessere, wiederverwendbarere und besser lesbare Formen umzuwandeln. Auf diese Weise konnte ich entscheiden, welcher Code in Domänenobjekte eingefügt werden sollte und welcher Code in neue eigene Objekte aufgeteilt werden sollte und welcher Code in einer Serviceklasse verbleiben sollte. Also habe ich einen Code:
%Vor%Dieser Code scheint eine gute Ergänzung zu einem Domain-Objekt zu sein, da es nur der Eingabeparameter ist, der das Domain-Objekt selbst ist. Scheint wie ein perfekter Kandidat für ein Refactoring. Das einzige Problem ist, dass dieses Objekt das Repository eines anderen Objekts aufruft. Was mich dazu bringt, es in der Serviceklasse zu belassen.
Meine Fragen sind also:
Danke für Ihre Zeit.
Bearbeiten Hinweis: Kann kein ORM für dieses verwenden, daher kann ich keine Lazy-Loading-Lösung verwenden.
Edit Note2: Ich kann den Konstruktor nicht ändern, um Parameter aufzunehmen, weil die Möchtegern-Datenschicht die Domänenobjekte durch Reflexion instanziiert (nicht meine Idee).
Bearbeiten Hinweis3: Ich glaube nicht, dass ein Batch-Objekt in der Lage sein sollte, nur eine Liste von Anwendungen zusammenzufassen, es scheint, dass es nur in der Lage sein sollte, Anwendungen, die sich in diesem bestimmten Stapel befinden, zusammenzufassen. Sonst macht es mehr Sinn, die Funktion in der Serviceklasse zu belassen.
Sie sollten nicht einmal Zugriff auf die Repositorys vom Domänenobjekt haben.
Was Sie tun können, ist, entweder dem Dienst das Domain-Objekt die entsprechenden Informationen geben zu lassen oder einen Delegaten im Domain-Objekt zu haben, der von einem Service oder im Konstruktor gesetzt wird.
%Vor%Ich bin kein DDD-Experte, aber ich erinnere mich an einen Artikel des großartigen Jeremy Miller, der genau diese Frage für mich beantwortet hat. Normalerweise möchten Sie eine Logik, die sich auf Ihre Domänenobjekte bezieht - innerhalb dieser Objekte, aber Ihre Serviceklasse würde die Methoden ausführen, die diese Logik enthalten. Dies hat mir geholfen, domänenspezifische Logik in die Entity-Klassen zu schieben und meine Serviceklassen weniger sperrig zu halten (da ich mich selbst zu viel Logik in den Service-Klassen gesetzt habe, wie du erwähnt hast)
Bearbeiten: Beispiel
Ich benutze die Enterprise-Bibliothek für die einfache Validierung, also werde ich in der Entity-Klasse ein Attribut wie folgt setzen:
%Vor%Die Entität erbt von einer Basisklasse mit der folgenden "IsValid" -Methode, die sicherstellt, dass jedes Objekt die Validierungskriterien
erfüllt %Vor%Als nächstes müssen wir diese "IsValid" -Methode in der Serviceklassen-Save-Methode ausführen, so:
%Vor%Ein komplexeres Beispiel könnte ein Bankkonto sein. Die Einzahlungslogik wird innerhalb des Kontoobjekts gespeichert, aber die Serviceklasse ruft diese Methode auf.
Warum nicht eine IList <VendorApplication>
als Parameter anstelle einer VendorApplicationBatch übergeben? Der Aufrufcode dafür würde vermutlich von einem Dienst stammen, der Zugriff auf die AppRepo hätte. Auf diese Weise ist Ihr Repository-Zugriff dort, wo er hingehört, während Ihre Domain-Funktion glücklicherweise nicht weiß, woher diese Daten stammen.
Wie ich es verstehe (nicht genug Informationen, um zu wissen, ob dies das richtige Design ist). VendorApplicationBatch sollte eine Lazy Loaded IList innerhalb des Domain-Objekts enthalten, und die Logik sollte in der Domain bleiben.
Zum Beispiel (Luftcode):
%Vor%Dies ist leicht mit einem ORM wie NHibernate möglich und ich denke, es wäre die beste Lösung.
Es scheint mir, dass Ihr CalculateTotal ein Service für Sammlungen von VendorApplication ist, und dass die Rückgabe der VendorApplication für einen Batch natürlich als eine Eigenschaft der Batch-Klasse passt. So würde ein anderer Dienst / Controller / was auch immer die entsprechende Sammlung von VendorApplication aus einem Stapel abrufen und sie an den VendorApplicationTotalCalculator-Dienst (oder etwas Ähnliches) übergeben. Aber das kann einige DDD-Aggregat-Root-Service-Regeln oder etwas, von dem ich nichts weiß (DDD-Novize), brechen.
Tags und Links c# service design-patterns domain-driven-design