Wie modellieren und behandeln Sie Präsentations-DTOs, um vom komplizierten Domänenmodell zu abstrahieren?

9

Hi Ich entwickle eine Anwendung, die mit einem komplexen Domänenmodell mit Hibernate arbeiten muss. Diese Anwendung verwendet Spring MVC und die Verwendung der Domänenobjekte in der Präsentationsebene ist sehr chaotisch, daher denke ich, dass ich DTOs verwenden sollte, die zu und von meiner Serviceebene gehen, damit diese den Anforderungen in meinen Ansichten entsprechen. Nehmen wir nun an, ich hätte eine CarLease-Entität, deren Eigenschaften keine einfachen Java-Primitiven sind, sondern mit anderen Entitäten wie Make, Model usw.

%Vor%

Die meisten Eigenschaften sind auf diese Art und Weise und sie sind auswählbar mit Drop-down-Auswahl in der JSP-Ansicht, jede wird eine ID an den Controller zurückgeben.

Betrachten wir nun einige Standard-Anwendungsfälle: Erstellen, Bearbeiten, Anzeigen

Wie würden Sie die Modellierungs-DTOs entwerfen, die als Formular-Backing-Objekte und die Kommunikation zwischen Präsentations- und Service-Schichten verwendet werden?

Würden Sie für jeden Fall ein anderes DTO erstellen (erstellen, bearbeiten, anzeigen), würden Sie DTOs für die komplexen Attribute erstellen? Wenn ja, wo würden Sie die ID in eine Entität übersetzen?

Wie und wo würden Sie die Validierung, die DTO- / Domänenassemblierung, was würden Sie von den Service-Layer-Methoden zurückgeben? (Erstellen, Bearbeiten, Erhalten)

Wie Sie sehen können, werde ich jetzt davon profitieren, meine Sicht von den Domänenobjekten zu trennen (sehr komplex mit vielen Dingen, die ich nicht brauche.), aber es fällt mir schwer, echte Beispiele und Best Practices zu finden dafür. Ich brauche eine Architektur Anleitung von oben nach unten, bitte beachten Sie, dass ich Spring MVC für den Fall, dass Hebelwirkung auf Ihrem Verstärker nutzen kann.

Danke im Voraus.

    
arrages 11.04.2010, 20:36
quelle

3 Antworten

3

Für was es wert ist (Ich entwickle in C # .net - aber die Prinzipien sollten Ihnen hoffentlich immer noch nützlich sein) Ich habe eine Reihe von Typen (DTOs) definiert, mit denen ich Daten zwischen Geschäft und Daten austauschen kann Ebenen; und ich habe mehr als einen Typ pro Domain-Objekt / Entity. Diese sind als einfache Klassen definiert.

Jede dieser Funktionen wurde mit einer bestimmten Aufgabe erstellt, zum Beispiel:

  • Ich habe einen leichten Typ, der entworfen wurde, um Listenansichten zu füllen (viele "Zeilen", aber nicht viele "Spalten"). Ich habe auch einen entsprechenden Sammlertyp, der eine beliebige Anzahl davon enthält.
  • Ich habe eine "große" Kopie, die normalerweise alle Eigenschaften der betreffenden Entität hat - aber nur für eine Instanz. Ich kann mehr als eine davon haben, abhängig von der Größe und Komplexität der Entität im Vergleich zu den Fällen der Verwendung; Außerdem hängt es davon ab, ob Sie alle Daten, die mit einer Instanz der Entität verknüpft sind, sofort zurückgeben oder einige für spätere Anforderungen verzögern.
  • Ich habe normalerweise auch getrennte "save" (new) und "update" Typen für die Entität.

Jeder Typ enthält nur die Informationen, die für eine bestimmte Aufgabe relevant sind. Zum Beispiel gibt "big" das Datum zurück, das zuletzt geändert wurde, aber ich erwarte das nicht in meinen Speicher- und Aktualisierungstypen, weil ich diese in der Datenzugriffsebene bevölkere.

Auch für meine App existieren diese Typen in einer gemeinsamen Assembly - so dass sie zwischen jeder Ebene wiederverwendet werden können, nicht nur zwischen den Business- und Datenebenen.

Architektonischer Fit

Es gibt nichts besonderes an diesem Ansatz, es hat seine eigenen Vor- und Nachteile; Was genau diese sind und wie sie sich auf dich auswirken, hängt von vielen Dingen ab - ich schätze, deine Laufleistung wird variieren - aber es ist mir seit einigen Jahren sicher gut.

Die Leute machen oft Aufhebens um "Trennung von Sorgen" - und das ist ein wirklich kluger Schachzug; Dies bezieht sich auf DTOs, da sie zwischen Schichten (und Diensten, Komponenten usw.) ausgetauscht werden, so dass es immer Unklarheiten gibt, wo genau die Linie gezeichnet werden sollte.

Ich gehe davon aus, dass, wenn ein wenig Information zwischen den Ebenen ausgetauscht werden kann, sie wahrscheinlich zwischen beliebig vielen Ebenen ausgetauscht werden kann - warum also nicht für alle zugänglich machen? Es spart auch Informationen neu zu werfen, wenn Sie es gerade durchreichen.

Was die Komplexität betrifft, gibt es zwei Möglichkeiten, dies zu handhaben:

  1. Verwenden Sie eine verbose / menschenlesbare Namenskonvention für alle; die Typen, damit du weißt, was die Dinge sind; Es spielt keine Rolle, wie viele es sind - dafür gibt es Intelli-Sense (& Docs). Je intuitiver, desto besser.
  2. KISS - halte die Dinge einfach, wenn du kannst; Sie müssen die sinnvolle Wiederverwendung und das Prinzip der einheitlichen Verantwortung (SRP) ausbalancieren.

Würden Sie ein DTO einer komplexen Eigenschaft einer Haupteinheit erstellen?

Ich habe festgestellt, dass ich DTO's aus einem von zwei Gründen mache:

  1. Es gibt Daten, von denen ich weiß, dass ich sie enthüllen muss (Push), und das Design des DTO ist ein Kinderspiel: Es wird von den Daten gesteuert, die ich enthüllen will.
  2. Pull: Der Kunde weiß, was er will, und der DTO ist darauf ausgelegt, diese Bedürfnisse zu erfüllen.

Da sie alle in einer gemeinsamen Assembly definiert sind, die keine Komponente "besitzt", hilft sie Ihnen, aus einer Domänen-Perspektive zu denken, statt aus einer komponentenzentrierten Perspektive; in gewissem Maße wird dies die Gestaltung der DTOs (Abgleich von Wiederverwendung vs SRP) beeinflussen.

In beiden Fällen können die DTOs, die erzeugt werden, spezifisch für ein bestimmtes Bedürfnis oder generisch sein; Ein DTO, das nur ein int und eine Zeichenfolge hat, ist nicht ungewöhnlich, es ist die Art von Dingen, die Sie für das Senden an Dropdown-Listen verwenden würden.

Die meisten DTO-Sammlungen, die ich zurücksende (von DAL nach BL), sind spezifisch für ein Konzept - nicht generisch. Ich setze dazu über die von mir angebotenen Konstrukteure sehr, sehr einfache Regeln: Jeder Arg wird benötigt. Ich bin nicht sicher, ob dies Ihre Frage "Wie verwalten Sie die Montage und Validierung" beantwortet.

    
Adrian K 11.04.2010, 21:56
quelle
1

Haben Sie ein CQRS-Prinzip (Command Query Responsibility Separation) in Betracht gezogen? Kurz gesagt, es ist ein architektonisches Prinzip, das die Verwendung separater Komponenten für Lese- und Änderungsvorgänge befürwortet.

Änderungen werden mithilfe von Befehlen ausgeführt, die an das Domänenmodell gesendet werden. Ihr NewCarLeaseDTO sieht wie ein Befehl aus - CreateNewCarLeaseCommand. Sie enthalten alle Daten, die für eine bestimmte Operation benötigt werden.

Auf der anderen Seite werden Lesevorgänge (entweder für Listen- oder Detailansichten) direkt im zugrunde liegenden Datenspeicher (SQL-Datenbank) ausgeführt. Es gibt hier viele Möglichkeiten, angefangen bei den gleichen Datenspeicher-Backing-Lese- und Schreibparts bis hin zu zwei unabhängigen Datenspeichern, die über eine Publish / Subscribe-Infrastruktur verbunden sind.

Bei der Verwendung der letzteren (zwei Speicher) Ansatz, um Seite zu lesen, befürworten viele (wie Udi Dahan) mit so genannten persistenten Ansichten. Es bedeutet, Daten direkt in dem von Ihren Ansichten konsumierbaren Format zu speichern. Die Transformation (Denormalisierung) erfolgt beim Synchronisieren nach der Modellaktualisierung.

Wenn Sie mehr über den CQRS erfahren möchten, empfehle ich Ihnen, Udi Dahan und Greg Young zu lesen.

    
Szymon Pobiega 12.04.2010 02:27
quelle
1

Die Idee, dass die Service-Schicht anstelle von EJB-Objekten DTOs zurückgeben sollte, ist meist eine Idee vor der EJB3 / JPA-Ära. Während CRUD gewinnen Sie wirklich viel von der direkten Arbeit mit den Modellobjekten (a.k.a. entities).

Sie können jedoch DTOs verwenden, wenn Sie für Leistungsoptimierungen verwendet werden, beispielsweise wenn Modellobjekte zu sperrig sind oder wenn Sie Smart-Joins für die Aggregation von Modelldaten verwenden.

Wenn Sie also nicht unter SOA arbeiten, würde ich nicht empfehlen, mit DTOs für CRUD-Operationen zu arbeiten.

    
Kdeveloper 11.04.2010 22:20
quelle