Sollten Dienste immer DTOs zurückgeben, oder können sie auch Domänenmodelle zurückgeben?

174

Ich entwerfe große Anwendungen (neu). Wir verwenden eine mehrschichtige Architektur, die auf DDD basiert.

Wir haben MVC mit Datenschicht (Implementierung von Repositorys), Domänenschicht (Definition des Domänenmodells und der Schnittstellen - Repositorys, Dienste, Arbeitseinheit), Dienstschicht (Implementierung von Diensten). Bisher verwenden wir Domänenmodelle (meistens Entitäten) für alle Ebenen und DTOs nur als Ansichtsmodelle (im Controller gibt der Dienst Domänenmodelle zurück, und der Controller erstellt ein Ansichtsmodell, das an die Ansicht übergeben wird).

Ich habe unzählige Artikel über das Verwenden, Nicht-Verwenden, Zuordnen und Übergeben von DTOs gelesen. Ich verstehe, dass es keine endgültige Antwort gibt, bin mir aber nicht sicher, ob es in Ordnung ist oder nicht, Domänenmodelle von Diensten an Controller zurückzugeben. Wenn ich ein Domänenmodell zurückgebe, wird es immer noch nie an die Ansicht übergeben, da der Controller immer ein ansichtsspezifisches Ansichtsmodell erstellt - in diesem Fall scheint es legitim zu sein. Andererseits fühlt es sich nicht richtig an, wenn das Domänenmodell die Geschäftsschicht (Serviceschicht) verlässt. Manchmal muss der Dienst ein Datenobjekt zurückgeben, das nicht in der Domäne definiert wurde, und dann müssen wir entweder der Domäne, die nicht zugeordnet ist, ein neues Objekt hinzufügen oder ein POCO-Objekt erstellen (dies ist hässlich, da einige Dienste Domänenmodelle zurückgeben, andere DTOs effektiv zurückgeben).

Die Frage ist: Wenn wir ausschließlich Ansichtsmodelle verwenden, ist es in Ordnung, Domänenmodelle bis hin zu Controllern zurückzugeben, oder sollten wir immer DTOs für die Kommunikation mit der Serviceschicht verwenden? Wenn ja, ist es in Ordnung, Domänenmodelle basierend auf den Anforderungen der Dienste anzupassen? (Ehrlich gesagt glaube ich nicht, da Services die Domain verbrauchen sollten.) Wenn wir uns strikt an DTOs halten sollten, sollten sie in der Service-Schicht definiert werden? (Ich denke schon.) Manchmal ist es klar, dass wir DTOs verwenden sollten (z. B. wenn der Dienst viel Geschäftslogik ausführt und neue Objekte erstellt), manchmal ist es klar, dass wir nur Domänenmodelle verwenden sollten (z. B. wenn der Mitgliedschaftsdienst einen anämischen Benutzer zurückgibt ( s) - es scheint nicht sehr sinnvoll zu sein, ein DTO zu erstellen, das dem Domänenmodell entspricht) - aber ich bevorzuge Konsistenz und bewährte Verfahren.

Article Domain vs DTO vs ViewModel - Wie und wann werden sie verwendet? (und auch einige andere Artikel) ist meinem Problem sehr ähnlich, beantwortet aber diese Frage (n) nicht. Artikel Soll ich DTOs im Repository-Muster mit EF implementieren? ist auch ähnlich, aber es geht nicht um DDD.

Haftungsausschluss: Ich beabsichtige nicht, ein Entwurfsmuster nur zu verwenden, weil es existiert und ausgefallen ist. Andererseits möchte ich gute Entwurfsmuster und -praktiken verwenden, auch weil es beim Entwerfen der Anwendung als Ganzes und beim Trennen hilft Selbst im Moment ist es nicht "notwendig", ein bestimmtes Muster zu verwenden.

Wie immer danke.

Robert Goldwein
quelle
28
Für diejenigen, die für Close stimmen - bitte möchten Sie erklären, warum Sie diese Frage als meinungsbasiert schließen möchten?
Robert Goldwein
20
@Aron "Code Review ist eine Frage- und Antwortseite zum Teilen von Code aus Projekten, an denen Sie für die Peer Review arbeiten." - Meine Frage bezieht sich überhaupt nicht auf Code, daher wäre sie dort kein Thema. SO: "Konzentrieren Sie sich auf Fragen zu einem tatsächlichen Problem, mit dem Sie konfrontiert sind. Geben Sie Details darüber an, was Sie versucht haben und was genau Sie versuchen zu tun." - Ich habe ein spezifisches Expertenproblem, das ich zu lösen versucht habe. Könnten Sie bitte genauer sagen, was mit dieser Frage falsch ist, da sich viele Fragen hier auf Architektur beziehen und solche Fragen anscheinend in Ordnung sind, damit ich weitere Missverständnisse vermeiden kann?
Robert Goldwein
7
Vielen Dank, dass Sie diese Frage gestellt haben. Sie haben mir einen Gefallen getan und mein Leben viel einfacher und glücklicher gemacht, danke.
Loa
9
@ RobertGoldwein, stört die SO Close Mafia nicht, deine Frage ist echt.
Hyankov
3
Vielen

Antworten:

177

Es fühlt sich nicht richtig an, wenn das Domain-Modell die Business-Schicht (Service-Schicht) verlässt.

Sie haben das Gefühl, dass Sie den Mut herausziehen, oder? Laut Martin Fowler: Der Service Layer definiert die Grenzen der Anwendung und kapselt die Domäne. Mit anderen Worten, es schützt die Domain.

Manchmal muss der Dienst ein Datenobjekt zurückgeben, das nicht in der Domäne definiert wurde

Können Sie ein Beispiel für dieses Datenobjekt angeben?

Wenn wir uns strikt an DTOs halten sollten, sollten sie in der Service-Schicht definiert werden?

Ja, da die Antwort Teil Ihrer Serviceschicht ist. Wenn es "woanders" definiert ist, muss die Serviceschicht auf "woanders" verweisen und Ihrer Lasagne eine neue Schicht hinzufügen.

Ist es in Ordnung, Domänenmodelle bis hin zu Controllern zurückzugeben, oder sollten wir immer DTOs für die Kommunikation mit der Serviceschicht verwenden?

Ein DTO ist ein Antwort- / Anforderungsobjekt. Es ist sinnvoll, wenn Sie es für die Kommunikation verwenden. Wenn Sie Domänenmodelle in Ihrer Präsentationsschicht verwenden (MVC-Controller / View, WebForms, ConsoleApp), ist die Präsentationsschicht eng mit Ihrer Domäne verbunden. Bei Änderungen in der Domäne müssen Sie Ihre Controller ändern.

Es scheint nicht sehr sinnvoll zu sein, ein DTO zu erstellen, das dem Domänenmodell entspricht.

Dies ist einer der Nachteile von DTO für neue Augen. Im Moment denken Sie an die Vervielfältigung von Code , aber wenn Ihr Projekt erweitert wird, ist dies viel sinnvoller, insbesondere in einer Teamumgebung, in der verschiedene Teams unterschiedlichen Ebenen zugewiesen sind.

DTO erhöht möglicherweise die Komplexität Ihrer Anwendung, aber auch Ihre Ebenen. DTO ist eine teure Funktion Ihres Systems, sie sind nicht kostenlos.

Warum ein DTO verwenden?

Dieser Artikel bietet sowohl Vor- als auch Nachteile der Verwendung eines DTO ( http://guntherpopp.blogspot.com/2010/09/to-dto-or-not-to-dto.html)

Zusammenfassung wie folgt:

Wann zu verwenden

  • Für große Projekte.
  • Die Projektlaufzeit beträgt 10 Jahre und mehr.
  • Strategische, geschäftskritische Anwendung.
  • Große Teams (mehr als 5)
  • Entwickler sind geografisch verteilt.
  • Die Domain und Präsentation sind unterschiedlich.
  • Reduzieren Sie den Overhead-Datenaustausch (der ursprüngliche Zweck von DTO)

Wann nicht verwenden

  • Kleines bis mittelgroßes Projekt (max. 5 Mitglieder)
  • Die Projektlaufzeit beträgt ca. 2 Jahre.
  • Kein separates Team für GUI, Backend usw.

Argumente gegen DTO

Argumente mit DTO

  • Ohne DTO sind Präsentation und Domain eng miteinander verbunden. (Dies ist in Ordnung für kleine Projekte.)
  • Schnittstellen- / API-Stabilität
  • Kann eine Optimierung für die Präsentationsschicht bereitstellen, indem ein DTO zurückgegeben wird, das nur die Attribute enthält, die unbedingt erforderlich sind. Mit linq-projection müssen Sie nicht eine ganze Entität ziehen.
  • Verwenden Sie Tools zur Codegenerierung, um die Entwicklungskosten zu senken
Yorro
quelle
3
Hallo, danke für deine Antwort, es ist wirklich eine gute Zusammenfassung für und auch danke für die Links. Mein Satz "Manchmal muss der Dienst ein Datenobjekt zurückgeben, das nicht in der Domäne definiert wurde" wurde schlecht ausgewählt. Dies bedeutet, dass der Dienst mehrere DOs aus einem Repository (z. B. Attribute) kombiniert und einen POCO als Zusammensetzung dieser Attribute (basierend) erzeugt auf Geschäftslogik). Nochmals vielen Dank für die wirklich schöne Antwort.
Robert Goldwein
1
Eine wichtige Überlegung zur Leistung ist, wie diese Domänenmodelle oder DTOs von Ihrem Dienst zurückgegeben werden. Wenn Sie mit EF eine Abfrage zur Rückgabe einer konkreten Sammlung von Domänenmodellen (z. B. mit .ToArray () oder ToList ()) realisieren, wählen Sie alle Spalten aus, um die realisierten Objekte zu füllen. Wenn Sie stattdessen das DTO in die Abfrage projizieren, ist EF klug genug, nur die Spalten auszuwählen, die zum Auffüllen Ihres DTO erforderlich sind. In einigen Fällen können erheblich weniger Daten übertragen werden.
schnauben
10
Sie können Ihre Objekte "von Hand" zuordnen. Ich weiß, langweiliges Zeug, aber es dauert 2-3 Minuten pro Modell und es gibt immer die Möglichkeit, viele Probleme zu verursachen, wenn Sie viel Reflexion verwenden (AutoMapper usw.)
Razvan Dumitru
1
Danke, dass du so einfach und mit solchen Inhalten geantwortet hast. Sie haben mir einen Gefallen getan und mein Leben viel einfacher und glücklicher gemacht, danke.
Loa
1
Wir hatten ein 10-Millionen-Projekt abgesagt, weil es zu langsam war ... Warum war es langsam? Übertragen des DTO-Objekts überall durch erneutes Auswählen. Achtung. Automapper verwendet auch Reflexion.
RayLoveless
11

Es scheint, dass Ihre Anwendung groß und komplex genug ist, da Sie sich für den DDD-Ansatz entschieden haben. Geben Sie Ihre Poco-Entitäten oder so genannten Domain-Entitäten und Wertobjekte in Ihrer Service-Schicht nicht zurück. Wenn Sie dies tun möchten, löschen Sie Ihre Service-Schicht, da Sie sie nicht mehr benötigen! Modell- oder Datenübertragungsobjekte anzeigen sollten sich in der Serviceebene befinden, da sie Domänenmodellmitgliedern zugeordnet werden sollten und umgekehrt. Warum brauchen Sie DTO? In einer komplexen Anwendung mit vielen Szenarien sollten Sie die Belange der Domäne und Ihrer Präsentationsansichten trennen. Ein Domänenmodell kann in mehrere DTOs unterteilt werden, und mehrere Domänenmodelle können zu einem DTO zusammengefasst werden. Es ist daher besser, Ihr DTO in einer mehrschichtigen Architektur zu erstellen, auch wenn es mit Ihrem Modell identisch ist.

Sollten wir immer DTOs für die Kommunikation mit der Serviceschicht verwenden? Ja, Sie müssen DTO von Ihrer Service-Schicht zurückgeben, da Sie mit Mitgliedern des Domänenmodells mit Ihrem Repository in der Service-Schicht gesprochen haben, diese DTO zuordnen und zum MVC-Controller zurückkehren und umgekehrt.

Ist es in Ordnung, Domain-Modelle basierend auf den Anforderungen der Services anzupassen? Ein Service kommuniziert nur mit Repository- und Domain-Methoden und Domain-Services. Sie sollten das Geschäft in Ihrer Domain basierend auf Ihren Anforderungen lösen und es ist nicht die Service-Aufgabe, der Domain mitzuteilen, was benötigt wird.

Wenn wir uns strikt an DTOs halten sollten, sollten sie in der Service-Schicht definiert werden? Ja, versuchen Sie, DTO oder ViewModel erst später in Betrieb zu nehmen, da sie Domänenmitgliedern in der Serviceschicht zugeordnet werden sollten. Es ist keine gute Idee, DTO in Controllern Ihrer Anwendung zu platzieren (versuchen Sie, das Anforderungsantwortmuster in Ihrer Serviceschicht zu verwenden) !

Ehsan
quelle
1
Das tut mir leid! Sie können es hier sehen ehsanghanbari.com/blog/Post/7/…
Ehsan
10

Nach meiner Erfahrung sollten Sie das tun, was praktisch ist. "Das beste Design ist das einfachste Design, das funktioniert" - Einstein. Damit ist Verstand ...

Wenn wir ausschließlich Ansichtsmodelle verwenden, ist es in Ordnung, Domänenmodelle bis hin zu Controllern zurückzugeben, oder sollten wir immer DTOs für die Kommunikation mit der Serviceschicht verwenden?

Absolut ok! Wenn Sie über Domänenentitäten, DTOs und Ansichtsmodelle verfügen und Datenbanktabellen enthalten, werden alle Felder in der Anwendung an vier Stellen wiederholt. Ich habe an großen Projekten gearbeitet, bei denen Domain Entities und View Models einwandfrei funktionierten. Die einzige Ausnahme besteht darin, dass die Anwendung verteilt ist und sich die Serviceschicht auf einem anderen Server befindet. In diesem Fall müssen DTOs aus Serialisierungsgründen über das Kabel senden.

Wenn ja, ist es in Ordnung, Domänenmodelle basierend auf den Anforderungen der Dienste anzupassen? (Ehrlich gesagt denke ich nicht, da Dienste verbrauchen sollten, was Domain hat.)

Im Allgemeinen würde ich zustimmen und Nein sagen, da das Domain-Modell normalerweise die Geschäftslogik widerspiegelt und normalerweise nicht vom Verbraucher dieser Logik geprägt wird.

Wenn wir uns strikt an DTOs halten sollten, sollten sie in der Service-Schicht definiert werden? (Ich glaube schon.)

Wenn Sie sich für die Verwendung entscheiden, würde ich zustimmen und sagen, dass die Service-Schicht der perfekte Ort ist, da sie die DTOs am ​​Ende des Tages zurückgibt.

Viel Glück!

Justin Ricketts
quelle
8

Ich bin zu spät zu dieser Party, aber dies ist eine so häufige und wichtige Frage, dass ich mich gezwungen fühlte zu antworten.

Mit "Services" meinen Sie die "Application Layer", die Evan im Blue Book beschrieben hat ? Ich gehe davon aus, dass Sie dies tun. In diesem Fall lautet die Antwort, dass sie keine DTOs zurückgeben sollten. Ich schlage vor, Kapitel 4 im blauen Buch mit dem Titel "Isolating the Domain" zu lesen.

In diesem Kapitel sagt Evans Folgendes zu den Ebenen:

Partitionieren Sie ein komplexes Programm in Ebenen. Entwickeln Sie in jeder Ebene ein Design, das zusammenhängend ist und nur von den darunter liegenden Ebenen abhängt.

Dafür gibt es gute Gründe. Wenn Sie das Konzept der Teilreihenfolge als Maß für die Softwarekomplexität verwenden , erhöht die Abhängigkeit einer Schicht von einer darüber liegenden Schicht die Komplexität, wodurch die Wartbarkeit verringert wird.

Wenn Sie dies auf Ihre Frage anwenden, sind DTOs wirklich ein Adapter, der ein Anliegen der Benutzeroberfläche / Präsentationsschicht ist. Denken Sie daran, dass Remote- / prozessübergreifende Kommunikation genau der Zweck eines DTO ist (es ist erwähnenswert, dass Fowler in diesem Beitrag auch dagegen spricht, dass DTOs Teil einer Serviceschicht sind, obwohl er nicht unbedingt DDD-Sprache spricht).

Wenn Ihre Anwendungsschicht von diesen DTOs abhängt, hängt sie von einer Schicht über sich ab und Ihre Komplexität nimmt zu. Ich kann garantieren, dass dies die Schwierigkeit der Wartung Ihrer Software erhöht.

Was ist beispielsweise, wenn Ihr System mit mehreren anderen Systemen oder Client-Typen verbunden ist, für die jeweils ein eigenes DTO erforderlich ist? Woher wissen Sie, welches DTO eine Methode Ihres Anwendungsdienstes zurückgeben soll? Wie würden Sie dieses Problem überhaupt lösen, wenn Ihre bevorzugte Sprache das Überladen einer Methode (in diesem Fall der Servicemethode) basierend auf dem Rückgabetyp nicht zulässt? Und selbst wenn Sie einen Weg finden, warum sollten Sie Ihre Anwendungsschicht verletzen, um ein Problem mit der Präsentationsschicht zu unterstützen?

In der Praxis ist dies ein Schritt auf einem Weg, der in einer Spaghetti-Architektur enden wird. Ich habe diese Art der Verschiebung und ihre Ergebnisse in meiner eigenen Erfahrung gesehen.

Wo ich derzeit arbeite, geben Dienste in unserer Anwendungsschicht Domänenobjekte zurück. Wir betrachten dies nicht als Problem, da die Schnittstellenschicht (dh Benutzeroberfläche / Präsentation) von der Domänenschicht abhängt, die sich unten befindet . Außerdem wird diese Abhängigkeit auf einen Abhängigkeitstyp "Nur Referenz" minimiert, weil:

a) Die Schnittstellenschicht kann nur als schreibgeschützte Rückgabewerte auf diese Domänenobjekte zugreifen, die durch Aufrufe der Anwendungsschicht erhalten werden

b) Methoden für Dienste in der Anwendungsschicht akzeptieren als Eingabe nur "rohe" Eingaben (Datenwerte) oder Objektparameter (um die Anzahl der Parameter zu reduzieren, falls erforderlich), die in dieser Schicht definiert sind. Insbesondere akzeptieren Anwendungsdienste niemals Domänenobjekte als Eingabe.

Die Schnittstellenschicht verwendet Zuordnungstechniken, die in der Schnittstellenschicht selbst definiert sind, um Domänenobjekte DTOs zuzuordnen. Auch hier konzentrieren sich DTOs darauf, Adapter zu sein, die von der Schnittstellenschicht gesteuert werden.

BitMask777
quelle
1
Schnelle Frage. Ich überlege gerade, was ich von meiner Anwendungsschicht zurückgeben soll. Das Zurückgeben von Domänenentitäten aus der Anwendungsschicht fühlt sich falsch an. Möchte ich die Domain wirklich nach "außen" lecken? Also habe ich über DTOs aus der Anwendungsschicht nachgedacht. Aber das fügt ein anderes Modell hinzu. In Ihrer Antwort sagten Sie, dass Sie Domain-Modelle als "schreibgeschützte Rückgabewerte" zurückgeben. Wie machst du das? Dh wie lässt du sie nur lesen?
Michael Andrews
Ich denke, ich werde nur Ihre Position einnehmen. Anwendungsdienste geben Domänenmodelle zurück. Die Portadapterebenen (REST, Präsentation usw.) übersetzen sie dann in ihr eigenes Modell (Ansichtsmodell oder Darstellungen). Das Hinzufügen eines DTO-Modells zwischen der Anwendung und den Portadaptern scheint übertrieben. Zurückgebende Domänenmodelle halten sich weiterhin an DIP, und die Domänenlogik bleibt innerhalb des begrenzten Kontexts (nicht unbedingt innerhalb der Anwendungsgrenze. Dies scheint jedoch ein guter Kompromiss zu sein).
Michael Andrews
@ MichaelAndrews, froh zu hören, dass meine Antwort geholfen hat. Betreff: Ihre Frage, ob die zurückgegebenen Objekte schreibgeschützt sind, die Objekte selbst sind nicht wirklich schreibgeschützt (dh unveränderlich). Was ich meine ist, dass es in der Praxis nicht passiert (zumindest nach meiner Erfahrung). Um ein Domänenobjekt zu aktualisieren, müsste die Schnittstellenschicht entweder a) auf das Repository des Domänenobjekts verweisen oder b) die Anwendungsschicht zurückrufen, um das gerade empfangene Objekt zu aktualisieren. Beides sind so eindeutige Verstöße gegen die gute DDD-Praxis, dass ich finde, dass sie sich selbst durchsetzen. Fühlen Sie sich frei, die Antwort zu bewerten, wenn Sie möchten.
BitMask777
Diese Antwort ist für mich aus mehreren Gründen sehr intuitiv. Erstens können wir dieselbe Anwendungsschicht für mehrere Benutzeroberflächen (APIs, Controller) wiederverwenden und jede kann das Modell nach Belieben transformieren. Zweitens, wenn wir Model-to-DTO in App transformieren würden. Ebene, das würde bedeuten, dass DTO in App definiert ist. Layer, was wiederum bedeutet, dass DTO jetzt Teil unseres Bounded Context ist (nicht unbedingt Domain!) - das fühlt sich einfach falsch an.
Robotron
1
Ich wollte Ihnen gerade eine Folgefrage stellen und sah dann, dass Sie diese bereits beantwortet haben: "Anwendungsdienste akzeptieren niemals Domänenobjekte als Eingabe". Ich würde wieder +1 geben, wenn ich könnte.
Robotron
4

Bisher verwenden wir Domänenmodelle (meistens Entitäten) über alle Ebenen hinweg und verwenden DTOs nur als Ansichtsmodelle (im Controller gibt der Dienst Domänenmodelle zurück und der Controller erstellt ein Ansichtsmodell, das an die Ansicht übergeben wird).

Da das Domain-Modell eine Terminologie ( Ubiquitous Language ) für Ihre gesamte Anwendung bereitstellt, ist es besser, das Domain-Modell in großem Umfang zu verwenden.

Der einzige Grund für die Verwendung von ViewModels / DTOs ist die Implementierung eines MVC-Musters in Ihrer Anwendung, um View(jede Art von Präsentationsschicht) und Model( Domänenmodell) zu trennen . In diesem Fall sind Ihre Präsentation und Ihr Domain-Modell lose miteinander verbunden.

Manchmal muss der Dienst ein Datenobjekt zurückgeben, das nicht in der Domäne definiert wurde, und dann müssen wir entweder der Domäne, die nicht zugeordnet ist, ein neues Objekt hinzufügen oder ein POCO-Objekt erstellen (dies ist hässlich, da einige Dienste Domänenmodelle zurückgeben, andere DTOs effektiv zurückgeben).

Ich gehe davon aus, dass Sie über Anwendungs- / Geschäfts- / Domänenlogikdienste sprechen.

Ich schlage vor, dass Sie Domain-Entitäten zurückgeben, wenn Sie können. Wenn zusätzliche Informationen zurückgegeben werden müssen, kann DTO zurückgegeben werden, das mehrere Domänenentitäten enthält.

Manchmal haben Benutzer, die Frameworks von Drittanbietern verwenden, die Proxys über Domänenentitäten generieren, Schwierigkeiten, Domänenentitäten aus ihren Diensten zu entfernen, aber es handelt sich nur um eine falsche Verwendung.

Die Frage ist: Wenn wir ausschließlich Ansichtsmodelle verwenden, ist es in Ordnung, Domänenmodelle bis hin zu Controllern zurückzugeben, oder sollten wir immer DTOs für die Kommunikation mit der Serviceschicht verwenden?

Ich würde sagen, dass es in 99,9% der Fälle ausreicht, Domain-Entitäten zurückzugeben.

Um die Erstellung von DTOs und die Zuordnung Ihrer Domänenentitäten zu diesen zu vereinfachen, können Sie AutoMapper verwenden .

Ilya Palkin
quelle
4

Wenn Sie einen Teil Ihres Domain-Modells zurückgeben, wird dieser Teil eines Vertrags. Ein Vertrag ist schwer zu ändern, da Dinge außerhalb Ihres Kontexts davon abhängen. Daher würden Sie es schwierig machen, einen Teil Ihres Domain-Modells zu ändern.

Ein sehr wichtiger Aspekt eines Domänenmodells ist, dass es leicht zu ändern ist. Dies macht uns flexibel an die sich ändernden Anforderungen der Domain.

Timo
quelle
4

Spät zur Party, aber ich stehe vor genau der gleichen Architektur und neige zu „nur DTOs aus dem Dienst“. Dies liegt hauptsächlich daran, dass ich mich entschieden habe, nur Domänenobjekte / -aggregate zu verwenden, um die Gültigkeit innerhalb des Objekts aufrechtzuerhalten, also nur beim Aktualisieren, Erstellen oder Löschen. Wenn wir nach Daten fragen, verwenden wir EF nur als Repository und ordnen das Ergebnis DTOs zu. Auf diese Weise können wir Leseabfragen optimieren und nicht an Geschäftsobjekte anpassen. Oft werden Datenbankfunktionen verwendet, da diese schnell sind.

Jede Servicemethode definiert ihren eigenen Vertrag und ist daher im Laufe der Zeit einfacher zu warten. Ich hoffe.

Niklas Wulff
quelle
1
Nach Jahren kamen wir genau aus den hier genannten Gründen zu dem gleichen Ergebnis.
Robert Goldwein
@ RobertGoldwein Das ist großartig! Ich bin jetzt sicherer in meiner Entscheidung. :-)
Niklas Wulff
@NiklasWulff: Die fraglichen Dtos sind nun Teil des Application Layer-Vertrags, dh Teil des Kerns / der Domäne. Was ist mit den Web-API- Rückgabetypen ? Stellen Sie die in Ihrer Antwort genannten Dtos bereit oder haben Sie dedizierte Ansichtsmodelle in der Web-API-Ebene definiert? Oder anders ausgedrückt: Ordnen Sie die Dtos View Models zu?
Robotron
1
@Robotron Wir haben keine Web-API, wir verwenden MVC. Also ja, wir ordnen die dto: s verschiedenen Ansichtsmodellen zu. Oft enthält ein Ansichtsmodell viele andere Elemente zum Anzeigen der Webseite, sodass die Daten aus den dto: s nur einen Teil des Ansichtsmodells ausmachen
Niklas Wulff
2

Ich würde vorschlagen, diese beiden Fragen zu analysieren:

  1. Verbrauchen Ihre oberen Ebenen (dh Ansichts- und Ansichtsmodelle / Controller) die Daten auf eine andere Weise als die Domänenebene? Wenn viel Mapping durchgeführt wird oder sogar Logik erforderlich ist, schlage ich vor, Ihr Design zu überdenken: Es sollte wahrscheinlich näher an der tatsächlichen Verwendung der Daten liegen.

  2. Wie wahrscheinlich ist es, dass Sie Ihre oberen Schichten tief verändern? (zB ASP.NET gegen WPF tauschen). Wenn dies sehr unterschiedlich ist und Ihre Architektur nicht sehr komplex ist, ist es möglicherweise besser, so viele Domänenentitäten wie möglich verfügbar zu machen.

Ich fürchte, es ist ein ziemlich breites Thema und es kommt wirklich darauf an, wie komplex Ihr System ist und welche Anforderungen es stellt.

jnovo
quelle
In unserem Fall wird sich die obere Schicht sicherlich nicht ändern. In einigen Fällen gibt der Dienst ein ziemlich eindeutiges POCO-Objekt zurück (das aus mehreren Domänen besteht - z. B. Benutzer und Dateien, die er besitzt). In einigen Fällen gibt ein Dienst einfach ein Domänenmodell zurück - z. B. das Ergebnis von "FindUserByEmail () sollte das Benutzerdomänenmodell zurückgeben - und Hier ist mein Anliegen, manchmal geben unsere Dienste das Domain-Modell zurück, manchmal das neue DTO - und ich mag diese Inkonsistenz nicht, ich lese so viele Artikel wie möglich und die Mehrheit scheint dem zuzustimmen, obwohl das Mapping-Domain-Modell <-> DTO ist 1: 1, Domain-Modell sollte Service-Schicht nicht verlassen - also bin ich hin und her gerissen.
Robert Goldwein
In einem solchen Szenario und vorausgesetzt, Sie können den zusätzlichen Entwicklungsaufwand tragen, würde ich mich auch für das Mapping entscheiden, damit Ihre Schichtung konsistenter wird.
jnovo
1

Nach meiner Erfahrung ist es eine schlechte Idee, die Domänenobjekte der Benutzeroberfläche auszusetzen, es sei denn, Sie verwenden ein OO-UI-Muster (wie nackte Objekte). Dies liegt daran, dass sich mit dem Wachstum der Anwendung die Anforderungen der Benutzeroberfläche ändern und Ihre Objekte dazu zwingen, diese Änderungen zu berücksichtigen. Am Ende dienen Sie zwei Meistern: UI und DOMAIN, was eine sehr schmerzhafte Erfahrung ist. Glauben Sie mir, Sie wollen nicht dort sein. Das UI-Modell hat die Funktion, mit dem Benutzer zu kommunizieren, das DOMAIN-Modell zum Speichern der Geschäftsregeln und das Persistenzmodell zum effektiven Speichern von Daten. Sie alle richten sich an unterschiedliche Anforderungen der Anwendung. Ich bin gerade dabei, einen Blog-Beitrag darüber zu schreiben. Ich werde ihn hinzufügen, wenn er fertig ist.

max_cervantes
quelle