Was ist ein Datenübertragungsobjekt?
In MVC sind die Modellklassen DTO, und wenn nicht, was sind die Unterschiede und brauchen wir beide?
Was ist ein Datenübertragungsobjekt?
In MVC sind die Modellklassen DTO, und wenn nicht, was sind die Unterschiede und brauchen wir beide?
Antworten:
Ein Datenübertragungsobjekt ist ein Objekt, mit dem Daten gekapselt und von einem Subsystem einer Anwendung an ein anderes gesendet werden.
DTOs werden am häufigsten von der Services-Schicht in einer N-Tier-Anwendung verwendet, um Daten zwischen sich selbst und der UI-Schicht zu übertragen. Der Hauptvorteil hierbei ist, dass die Datenmenge reduziert wird, die in verteilten Anwendungen über das Kabel gesendet werden muss. Sie machen auch großartige Modelle im MVC-Muster.
Eine andere Verwendung für DTOs kann darin bestehen, Parameter für Methodenaufrufe zu kapseln. Dies kann nützlich sein, wenn eine Methode mehr als 4 oder 5 Parameter akzeptiert.
Bei Verwendung des DTO-Musters würden Sie auch DTO-Assembler verwenden. Die Assembler werden verwendet, um DTOs aus Domänenobjekten zu erstellen und umgekehrt.
Die Konvertierung von Domain Object zu DTO und wieder zurück kann ein kostspieliger Prozess sein. Wenn Sie keine verteilte Anwendung erstellen, werden Sie wahrscheinlich keine großen Vorteile aus dem Muster ziehen, wie Martin Fowler hier erklärt
Die Definition für DTO finden Sie auf der Website von Martin Fowler . DTOs werden verwendet, um Parameter an Methoden und als Rückgabetypen zu übertragen. Viele Leute verwenden diese in der Benutzeroberfläche, aber andere blasen Domänenobjekte von ihnen auf.
Ein DTO ist ein dummes Objekt - es enthält nur Eigenschaften und hat Getter und Setter, aber keine andere Logik von Bedeutung (außer vielleicht einer Implementierung von compare () oder equals ()).
Typische Modellklassen in MVC (hier wird .net MVC angenommen) sind DTOs oder Sammlungen / Aggregate von DTOs
Im Allgemeinen sollten Wertobjekte unveränderlich sein. Wie Integer- oder String- Objekte in Java. Wir können sie zum Übertragen von Daten zwischen Softwareschichten verwenden. Wenn die Softwareschichten oder -dienste auf verschiedenen Remote-Knoten ausgeführt werden, z. B. in einer Microservices-Umgebung oder in einer älteren Java Enterprise-App. Wir müssen fast exakte Kopien von zwei Klassen machen. Hier haben wir DTOs getroffen.
|-----------| |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------| |--------------|
In älteren Java Enterprise Systems können DTOs verschiedene EJB-Inhalte enthalten.
Ich weiß nicht, ob dies eine bewährte Methode ist oder nicht, aber ich persönlich verwende Value Objects in meinen Spring MVC / Boot-Projekten wie folgt :
|------------| |------------------| |------------|
-> Form | | -> Form | | -> Entity | |
| Controller | | Service / Facade | | Repository |
<- View | | <- View | | <- Entity / Projection View | |
|------------| |------------------| |------------|
Die Controller- Schicht weiß nicht, um welche Entitäten es sich handelt. Es kommuniziert mit Formular- und Ansichtswertobjekten . Formularobjekte haben JSR 303 Anmerkungen Validation (zum Beispiel @NotNull) und Ansicht Wert Objekte haben Jackson Annotations für benutzerdefinierte Serialisierung. (zum Beispiel @JsonIgnore)
Die Serviceschicht kommuniziert mit der Repository-Schicht über Entity Objects. Entitätsobjekte enthalten Anmerkungen zu JPA / Hibernate / Spring Data. Jede Schicht kommuniziert nur mit der unteren Schicht. Die Kommunikation zwischen den Schichten ist aufgrund der zirkulären / zyklischen Abhängigkeit verboten.
User Service ----> XX CANNOT CALL XX ----> Order Service
Einige ORM- Frameworks können über zusätzliche Schnittstellen oder Klassen projiziert werden. So können Repositorys View-Objekte direkt zurückgeben. Dort brauchen Sie für Sie keine zusätzliche Transformation.
Zum Beispiel ist dies unsere Benutzerentität:
@Entity
public final class User {
private String id;
private String firstname;
private String lastname;
private String phone;
private String fax;
private String address;
// Accessors ...
}
Sie sollten jedoch eine paginierte Liste von Benutzern zurückgeben, die nur ID, Vorname und Nachname enthalten. Anschließend können Sie ein Ansichtswertobjekt für die ORM-Projektion erstellen.
public final class UserListItemView {
private String id;
private String firstname;
private String lastname;
// Accessors ...
}
Sie können das paginierte Ergebnis leicht aus der Repository-Schicht abrufen. Dank der Feder können Sie auch nur Schnittstellen für Projektionen verwenden.
List<UserListItemView> find(Pageable pageable);
Keine Sorge, andere Konvertierungsvorgänge BeanUtils.copy
funktionieren einwandfrei.
GET
/ POST
/ was auch immer) von irgendwoher aufrufen oder einen Webservice mit SOA usw. verwenden), möchten Sie das große Objekt nicht mit Code übertragen, für den dies nicht erforderlich ist Der Endpunkt verbraucht Daten und verlangsamt die Übertragung.Mit MVC werden Datenübertragungsobjekte häufig verwendet, um Domänenmodelle einfacheren Objekten zuzuordnen, die letztendlich von der Ansicht angezeigt werden.
Aus Wikipedia :
Das Datenübertragungsobjekt (DTO), früher als Wertobjekte oder VO bekannt, ist ein Entwurfsmuster, das zum Übertragen von Daten zwischen Softwareanwendungssubsystemen verwendet wird. DTOs werden häufig in Verbindung mit Datenzugriffsobjekten verwendet, um Daten aus einer Datenbank abzurufen.
Das Datenübertragungsobjekt (DTO) beschreibt „ein Objekt, das Daten zwischen Prozessen überträgt“ (Wikipedia) oder ein „Objekt, mit dem Daten gekapselt und von einem Subsystem einer Anwendung an ein anderes gesendet werden“ (Stack Overflow-Antwort).
DefN
Ein DTO ist ein fest codiertes Datenmodell. Es löst nur das Problem der Modellierung eines Datensatzes, der von einem fest codierten Produktionsprozess verarbeitet wird, bei dem alle Felder zur Kompilierungszeit bekannt sind und daher über stark typisierte Eigenschaften aufgerufen werden.
Im Gegensatz dazu löst ein dynamisches Modell oder ein "Property Bag" das Problem der Modellierung eines Datensatzes, wenn der Produktionsprozess zur Laufzeit erstellt wird.
Der Cvar
Ein DTO kann mit Feldern oder Eigenschaften modelliert werden, aber jemand hat einen sehr nützlichen Datencontainer namens Cvar erfunden. Es ist eine Referenz auf einen Wert. Wenn ein DTO mit den von mir als Referenz bezeichneten Eigenschaften modelliert wird , können Module so konfiguriert werden, dass sie den Heapspeicher gemeinsam nutzen und gemeinsam daran arbeiten. Dadurch werden die Parameterübergabe und die O2O-Kommunikation aus Ihrem Code vollständig eliminiert. Mit anderen Worten, DTOs mit Referenzeigenschaften ermöglichen es dem Code, eine Nullkopplung zu erreichen .
class Cvar { ... }
class Cvar<T> : Cvar
{
public T Value { get; set; }
}
class MyDTO
{
public Cvar<int> X { get; set; }
public Cvar<int> Y { get; set; }
public Cvar<string> mutableString { get; set; } // >;)
}
Quelle: http://www.powersemantics.com/
Dynamische DTOs sind eine notwendige Komponente für dynamische Software. Um einen dynamischen Prozess zu instanziieren, besteht ein Compilerschritt darin, jeden Computer im Skript an die vom Skript definierten Referenzeigenschaften zu binden. Ein dynamisches DTO wird erstellt, indem die Cvars einer Sammlung hinzugefügt werden.
// a dynamic DTO
class CvarRegistry : Dictionary<string, Cvar> { }
Einwände
Hinweis: Da Wix die Verwendung von DTOs zum Organisieren von Parametern als "Anti-Pattern" bezeichnet hat, werde ich eine maßgebliche Stellungnahme abgeben.
return View(model); // MVC disagrees
Meine kollaborative Architektur ersetzt Entwurfsmuster. Siehe meine Webartikel.
Parameter ermöglichen die sofortige Steuerung einer Stapelrahmenmaschine. Wenn Sie eine kontinuierliche Steuerung verwenden und daher keine sofortige Steuerung benötigen, benötigen Ihre Module keine Parameter. Meine Architektur hat keine. Die In-Process-Konfiguration von Maschinen (Methoden) erhöht die Komplexität, aber auch den Wert (die Leistung), wenn die Parameter Werttypen sind. Referenztypparameter führen jedoch dazu, dass der Konsument Cache-Fehler verursacht, um die Werte ohnehin vom Heap zu entfernen. Konfigurieren Sie den Konsumenten daher einfach mit Referenzeigenschaften. Fakt aus dem Maschinenbau: Die Abhängigkeit von Parametern ist eine Art Voroptimierung, da die Verarbeitung (Herstellung von Bauteilen) selbst Abfall ist. Weitere Informationen finden Sie in meinem W-Artikel. http://www.powersemantics.com/w.html .
Fowler und das Unternehmen könnten die Vorteile von DTOs außerhalb der verteilten Architektur erkennen, wenn sie jemals eine andere Architektur gekannt hätten. Programmierer kennen nur verteilte Systeme. Integrierte kollaborative Systeme (auch bekannt als Produktion oder Fertigung) musste ich als meine eigene Architektur bezeichnen, da ich der erste bin, der Code auf diese Weise schreibt.
Einige betrachten das DTO als ein anämisches Domänenmodell, was bedeutet, dass ihm die Funktionalität fehlt. Dies setzt jedoch voraus, dass ein Objekt die Daten besitzen muss, mit denen es interagiert. Dieses konzeptionelle Modell zwingt Sie dann dazu, die Daten zwischen Objekten zu liefern. Dies ist das Modell für die verteilte Verarbeitung. In einer Fertigungslinie kann jedoch jeder Schritt auf das Endprodukt zugreifen und es ändern, ohne es zu besitzen oder zu steuern. Das ist der Unterschied zwischen verteilter und integrierter Verarbeitung. Die Herstellung trennt das Produkt von Betrieb und Logistik.
Es ist an sich nichts Falsches daran, die Verarbeitung als eine Gruppe nutzloser Büroangestellter zu modellieren, die per E-Mail miteinander arbeiten, ohne einen E-Mail-Pfad zu führen, abgesehen von all der zusätzlichen Arbeit und den Kopfschmerzen, die bei der Behandlung von Logistik- und Rückgabeproblemen entstehen. Ein ordnungsgemäß modellierter verteilter Prozess fügt dem Produkt ein Dokument (aktives Routing) hinzu, in dem beschrieben wird, von welchen Vorgängen es stammt und wohin es gehen wird. Das aktive Routing ist eine Kopie des Prozessquellen-Routings, das vor Beginn des Prozesses geschrieben wird. Im Falle eines Defekts oder einer anderen Notfalländerung wird das aktive Routing so geändert, dass es die Betriebsschritte enthält, an die es gesendet wird. Dies erklärt dann die gesamte Arbeit, die in die Produktion ging.