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.
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:
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:
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:
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.
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.
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.
Tags und Links java architecture spring-mvc n-tier-architecture