Was ist ein Datenübertragungsobjekt?

217

Was ist ein Datenübertragungsobjekt?

In MVC sind die Modellklassen DTO, und wenn nicht, was sind die Unterschiede und brauchen wir beide?

Yaron Naveh
quelle
@ yegor256 und die Tatsache, dass dieses Buch in diesem Artikel weiß, wie man Daten von der API abruft und wie man Daten in der Datenbank speichert und so gegen SRP verstößt, ist in Ordnung?
Betlista

Antworten:

222

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

Benny Hallett
quelle
7
"DTO macht großartige Modelle im MVC-Muster" - sollte ein Modell nicht alle Daten des Objekts enthalten und DTO mit einem Teil der Daten optimiert werden? Wenn ich Modell A habe und es an zwei Subsysteme übergeben muss, gibt es dann A_DTO_1 und A_DTO_2 mit den entsprechenden Feldern von jedem? "DTOs können darin bestehen, Parameter für Methodenaufrufe zu kapseln" -> Jede Klasse, die Parameter umschließt, ist DTO, auch wenn dies kein verteiltes System ist? Sind Modelle in MVC nicht das Domänenobjekt?
Yaron Naveh
2
Als Antwort auf Ihre erste Frage habe ich nicht über dasselbe gesprochen. Das Modell in MVC muss nicht unbedingt eine Klasse aus Ihrem Domänenmodell sein. Trotzdem könnte es gut sein. Mit dem DTO werden alle unnötigen Dinge entfernt. Kommt nur auf die Architektur an, die du suchst. Ich bin mir nicht sicher, wie ich Ihre zweite Frage genau beantworten soll. Unabhängig davon, ob es sich um eine drahtlose Verbindung handelt oder nicht, es handelt sich immer noch um ein Objekt, das eine Reihe von Daten einschließt, die zwischen (Sub-) Systemen übertragen werden sollen. Ich würde also behaupten, dass es sich um ein DTO handelt.
Benny Hallett
12
"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." Dies ist eigentlich ein Anti-Muster, das als Poltergeist- oder Gypsy Wagon-Klasse bezeichnet wird. Wenn Ihre Methode 4 Argumente benötigt, geben Sie 4 an. Erstellen Sie keine Klasse, nur um ein Objekt in eine Methode oder eine Klasse zu verschieben.
Wix
2
@ Wix, guter Punkt. Ich würde jedoch argumentieren, dass dies in Ordnung ist, wenn es semantisch korrekt ist (sagen wir, wenn Sie eine Einstellungsklasse mit Eigenschaften anstelle der Eigenschaften selbst als Werte übergeben). Was Sie nicht tun sollten, ist, alle Argumente einzubringen, um ein einzelnes Objekt zu übergeben, da sie möglicherweise nicht miteinander zusammenhängen und später zu Albträumen führen.
Aram Kocharyan
3
DTOs sollten nicht verwendet werden, um Parameter für Methodenaufrufe zu kapseln (was sie zu LocalDTOs machen würde). Sie wurden im Kontext von Remote-Schnittstellen eingeführt: martinfowler.com/bliki/LocalDTO.html
Rui
28

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.

blau
quelle
22

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

Eric Petroelje
quelle
3
Was Sie beschreiben, ist ein LocalDTO: martinfowler.com/bliki/LocalDTO.html
Rui
3
Ein Fall, in dem es nützlich ist, so etwas wie ein DTO zu verwenden, besteht darin, dass zwischen dem Modell in Ihrer Präsentationsebene und dem zugrunde liegenden Domänenmodell eine erhebliche Nichtübereinstimmung besteht. In diesem Fall ist es sinnvoll, eine präsentationsspezifische Fassade / ein Gateway zu erstellen, die bzw. das dem Domänenmodell zugeordnet ist und eine für die Präsentation geeignete Schnittstelle bietet.
Amitābha
14

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.copyfunktionieren einwandfrei.

Fırat KÜÇÜK
quelle
11
  1. Für mich ist die beste Antwort auf die Frage, was ein DTO ist, dass DTOs einfache Objekte sind, die keine Geschäftslogik oder Methodenimplementierung enthalten sollten, die getestet werden müssten .
  2. Normalerweise handelt es sich bei Ihrem Modell (unter Verwendung des MVC-Musters) um intelligente Modelle, die viele / einige Methoden enthalten können, die speziell für dieses Modell unterschiedliche Operationen ausführen (keine Geschäftslogik, dies sollte sich auf den Controllern befinden). Wenn Sie jedoch Daten übertragen (z. B. einen REST- Endpunkt ( 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.
Thiago Burgos
quelle
Warum sollte Geschäftslogik in Controllern sein?
AlexioVay
6

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.

Dan
quelle
3
Ein Wertobjekt ist kein DTO .
Coderpc
0

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).

Mostafa Kazemi
quelle
0

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.

RBJ
quelle