Einfaches altes CLR-Objekt gegen Datenübertragungsobjekt

405

POCO = Normales altes CLR-Objekt (oder besser: Klasse)

DTO = Datenübertragungsobjekt

In diesem Beitrag gibt es einen Unterschied, aber ehrlich gesagt beschreiben die meisten Blogs, die ich lese, POCO in der Art und Weise, wie DTO definiert ist: DTOs sind einfache Datencontainer, die zum Verschieben von Daten zwischen den Ebenen einer Anwendung verwendet werden.

Sind POCO und DTO dasselbe?

Patrick Peters
quelle
5
"POCO = Plain Old CLR (oder besser: Class) Object". Objekte dieser Art in VB.NET wären also auch POCOs, keine POVOs.
J. Polfer

Antworten:

568

Ein POCO folgt den Regeln von OOP. Es sollte (muss aber nicht) Zustand und Verhalten haben. POCO stammt von POJO, geprägt von Martin Fowler [ Anekdote hier ]. Er benutzte den Begriff POJO, um es sexy zu machen, die rahmenlastigen EJB-Implementierungen abzulehnen. POCO sollte in .Net im selben Kontext verwendet werden. Lassen Sie sich nicht von Frameworks das Design Ihres Objekts bestimmen.

Der einzige Zweck eines DTO besteht darin, den Status zu übertragen, und sollte kein Verhalten aufweisen. Ein Beispiel für die Verwendung dieses Musters finden Sie in Martin Fowlers Erklärung eines DTO .

Hier ist der Unterschied: POCO beschreibt einen Programmieransatz (gute altmodische objektorientierte Programmierung), bei dem DTO ein Muster ist, das zum "Übertragen von Daten" mithilfe von Objekten verwendet wird.

Während Sie POCOs wie DTOs behandeln können, laufen Sie Gefahr, ein anämisches Domänenmodell zu erstellen, wenn Sie dies tun. Darüber hinaus gibt es eine Nichtübereinstimmung in der Struktur, da DTOs so konzipiert sein sollten, dass sie Daten übertragen und nicht die wahre Struktur der Geschäftsdomäne darstellen. Dies hat zur Folge, dass DTOs in der Regel flacher sind als Ihre eigentliche Domain.

In einer Domäne mit angemessener Komplexität ist es fast immer besser, separate Domänen-POCOs zu erstellen und diese in DTOs zu übersetzen. DDD (Domain Driven Design) definiert die Antikorruptionsschicht (ein weiterer Link hier , aber am besten kaufen Sie das Buch ). Dies ist eine gute Struktur, die die Trennung klar macht.

Michael Meadows
quelle
Ich weiß, dass ich hier viel auf Martin Fowler verwiesen habe, aber er hat den Begriff POJO geprägt und das Buch PoEAA geschrieben, das die endgültige Referenz für DTO ist.
Michael Meadows
Ich bin mir nicht sicher, ob ein DTO kein Verhalten haben sollte. Nach Martin Fowlers Diagramm könnte DTO Verhalten haben.
Beatles1692
39
@ Beatles1692, die abgebildeten Methoden sind Serialisierungscode. Es ist wahrscheinlich zu weit gefasst, um "kein Verhalten" zu sagen. Wie wäre es mit "keine Geschäftslogik". Serialisierungscode und Objekte auf niedriger Ebene wie Hash-Code, Gleichheit und Zeichenfolge sollten akzeptabel sein.
Michael Meadows
1
@PositiveGuy Ein Modell dient einem anderen Zweck als ein DTO. DTO sollte zum Übertragen von Daten von einer Domäne zu einer anderen dienen (es spielt keine Rolle, ob sie sich in derselben Laufzeit befinden oder nicht). Ein Modell "repräsentiert" einen Aspekt einer Domäne, z. B. einen Bildschirm, einen Dienst oder eine Datenquelle. Modelle umfassen Status und Verhalten, die repräsentativ für das sind, was sie modellieren.
Michael Meadows
2
Bitte beachten Sie, dass anämische Domain-Modelle nicht unbedingt schlecht sind, insbesondere wenn Ihre App hauptsächlich CRUD ist. Bevorzugen Sie die Einfachheit gegenüber Martin Fowler.
Mariusz Jamro
50

Es ist wahrscheinlich überflüssig für mich, einen Beitrag zu leisten, da ich meine Position bereits in meinem Blog-Artikel angegeben habe, aber der letzte Absatz dieses Artikels fasst die Dinge irgendwie zusammen:

Lernen Sie abschließend, den POCO zu lieben, und stellen Sie sicher, dass Sie keine Fehlinformationen darüber verbreiten, dass er mit einem DTO identisch ist. DTOs sind einfache Datencontainer, mit denen Daten zwischen den Ebenen einer Anwendung verschoben werden. POCOs sind vollwertige Geschäftsobjekte mit der einzigen Anforderung, dass sie Persistence Ignorant sind (keine Methoden zum Abrufen oder Speichern). Wenn Sie das Buch von Jimmy Nilsson noch nicht gelesen haben, holen Sie es von Ihrem örtlichen Universitätsstapel ab. Es hat Beispiele in C # und es ist eine gute Lektüre.

Übrigens, Patrick, ich habe den POCO als Lifestyle-Artikel gelesen und stimme vollkommen zu, das ist ein fantastischer Artikel. Es ist eigentlich ein Abschnitt aus dem Jimmy Nilsson-Buch, den ich empfohlen habe. Ich hatte keine Ahnung, dass es online verfügbar war. Sein Buch ist wirklich die beste Informationsquelle, die ich über POCO / DTO / Repository / und andere DDD-Entwicklungspraktiken gefunden habe.


quelle
4
Link zum Blog-Artikel: rlacovara.blogspot.com/2009/03/…
Jamie Ide
28

POCO ist einfach ein Objekt, das nicht von einem externen Framework abhängig ist. Es ist EINFACH.

Ob ein POCO Verhalten hat oder nicht, ist unerheblich.

Ein DTO kann POCO sein, ebenso wie ein Domänenobjekt (das normalerweise reich an Verhalten ist).

In der Regel nehmen DTOs für Serialisierungszwecke eher Abhängigkeiten von externen Frameworks (z. B. Attributen) auf, da sie normalerweise an der Grenze eines Systems beendet werden.

In typischen Architekturen im Zwiebelstil (häufig im Rahmen eines DDD-Ansatzes verwendet) wird die Domänenschicht in der Mitte platziert, sodass ihre Objekte zu diesem Zeitpunkt keine Abhängigkeiten außerhalb dieser Schicht aufweisen sollten.

Neil
quelle
15

Ich habe einen Artikel zu diesem Thema geschrieben: DTO vs Value Object vs POCO .

Zusamenfassend:

  • DTO! = Wertobjekt
  • DTO ⊂ POCO
  • Wertobjekt ⊂ POCO
Vladimir
quelle
6

Ich denke, ein DTO kann ein POCO sein. Bei DTO geht es mehr um die Verwendung des Objekts, während sich POCO eher um den Stil des Objekts handelt (entkoppelt von Architekturkonzepten).

Ein Beispiel, bei dem ein POCO etwas anderes als ein DTO ist, ist, wenn Sie über POCOs in Ihrem Domänenmodell / Geschäftslogikmodell sprechen, das eine schöne OO-Darstellung Ihrer Problemdomäne darstellt. Sie können die POCOs während der gesamten Anwendung verwenden, dies kann jedoch einige unerwünschte Nebenwirkungen haben, da ein solches Wissen verloren geht. DTOs werden beispielsweise von der Serviceschicht verwendet, mit der die Benutzeroberfläche kommuniziert. Die DTOs sind eine flache Darstellung der Daten und werden nur verwendet, um die Benutzeroberfläche mit Daten zu versorgen und Änderungen an die Serviceschicht zurückzusenden. Die Serviceschicht ist dafür verantwortlich, die beiden Wege des DTO den POCO-Domänenobjekten zuzuordnen.

Update Martin Fowler sagte, dass dieser Ansatz ein schwerer Weg ist und nur gewählt werden sollte, wenn zwischen der Domänenschicht und der Benutzeroberfläche eine signifikante Nichtübereinstimmung besteht.

Davy Landman
quelle
2
@ David Landman, der Link, den Sie eingefügt haben, bezieht sich auf das lokale DTO-Muster. In diesem Fall werden DTOs für den Übertragungsstatus innerhalb Ihrer Systemgrenze verwendet. In diesen Fällen sollten Sie sehr vorsichtig sein, da Sie in Ihrem System bereits eine genau definierte Domäne haben sollten, die gemeinsam genutzt werden kann. Bei der Übertragung des Status über Systemgrenzen hinweg ist das DTO schwer zu vermeiden und in allen Fällen angemessen.
Michael Meadows
@ Michael Meadows, ja, der Link spricht tatsächlich über eine andere Untergruppe von Problemen. Ich denke jedoch, dass Sie beim Übertragen eines Status über eine Systemgrenze hinweg einen Übersetzungsdienst verwenden sollten, um den POCO aus einem Kontext dem POCO aus einem anderen Kontext zuzuordnen. Oder sprechen Sie von Grenzen auf Systemebene?
Davy Landman
1

Ein primärer Anwendungsfall für ein DTO ist die Rückgabe von Daten von einem Webdienst. In diesem Fall sind POCO und DTO gleichwertig. Jedes Verhalten im POCO wird entfernt, wenn es von einem Webdienst zurückgegeben wird. Es spielt also keine Rolle, ob es ein Verhalten aufweist oder nicht.

John Saunders
quelle
5
Ich denke, Ihre Antwort stellt falsch dar, was ein wenig passiert. Im Fall eines Webdienstes wird ein Proxy basierend auf dem exponierten Status eines Objekts generiert. Dies bedeutet, dass ein DTO getrennt vom POCO erstellt wird, das zufällig denselben öffentlichen Status wie der POCO hat. Es mag subtil erscheinen, aber es ist wichtig. Der Grund dafür ist, dass der Proxy, selbst wenn er mit dem Original identisch ist, nicht aus derselben Klasse besteht.
Michael Meadows
Oh nein. Man verwendet ein DTO, um Daten zwischen Ebenen zurückzugeben / zu empfangen, in diesem Fall einen Webdienst. Man wählt ein DTO, weil es nur Daten und kein Verhalten hat. Es ist wahr, dass die Proxy-Klasse wahrscheinlich auch ein DTO sein wird, und dass, wenn Sie stattdessen eine POCO-Klasse verwendet hätten, ein Proxy erstellt worden wäre. In diesem Fall ist die POCO-Klasse jedoch effektiv ein DTO, da ihr Verhalten nicht übersetzt wird. Ich sage immer noch, benutze ein DTO, weil du kein Verhalten verpassen wirst, das es nie gab.
John Saunders
5
** Semantisch: Webdienste machen Objektstatusbeutel mithilfe von WSDL verfügbar. Daraus werden Proxies generiert. Diese können kein Verhalten beinhalten. Wenn Sie einen Webdienst verwenden, besteht die einzige Beziehung zwischen Ihrem Objekt und dem exponierten Domänenobjekt darin, dass derselbe öffentliche Status basierend auf der Überprüfung erstellt wurde.
Michael Meadows
7
@ John, ich denke du reagierst über. Ich sage, Sie haben Recht, aber Ihre Formulierung ist irreführend. "In diesem Fall sind POCO und DTO gleichwertig." Semantisch ist das nicht wahr. POCOs können als DTOs verwendet werden und umgekehrt, aber das bedeutet nicht, dass sie gleichwertig sind. Nicht mehr als ein Auto und ein Pickup sind gleichwertig, obwohl beide verwendet werden können, um Sie zum Lebensmittelgeschäft zu fahren. Sie haben überlappende Funktionen, aber es fällt Ihnen schwer, jemanden zu finden, der Ihnen einen Einblick gibt, der einem F350 entspricht, selbst im Rahmen der Lebensmittelreise.
Michael Meadows
3
Diese Antwort ist so falsch, dass ein Webdienst für einen nicht generisch genug ist. Vor allem ist es eine bekannte Tatsache, dass DTO KEIN POCO ist. DTO ist ein Datencontainer, während POCO Objekte als Eigenschaften sind und keine Persistenz aufweisen (keine Methoden zum Abrufen oder Speichern).
Tom Stickel
1

Hier ist die allgemeine Regel: DTO == böse und Indikator für überentwickelte Software. POCO == gut. Unternehmensmuster haben das Gehirn vieler Menschen in der Java EE-Welt zerstört. Bitte wiederholen Sie den Fehler nicht in .NET Land.

benmmurphy
quelle
7
Könnten Sie bitte näher darauf eingehen? DTO sind erforderlich, wenn Daten von einem Webdienst zurückgegeben werden, um Implementierungs- und Plattformspezifikationen im Vertrag zu vermeiden.
John Saunders
1
Ja, John DTOs sind für das konzipiert, was Sie sagen, und funktionieren gut. Leider werden sie häufig verwendet, wenn sie in einstufigen Web-Apps nicht benötigt werden, und haben nur einen geringen Wert.
Craig
9
Ich denke, @drscroogemcduck, dass Sie DTOs vielleicht nicht mögen, weil sie eher als erstes als als letztes Mittel verwendet werden, aber sie sind nicht von Natur aus böse ... nicht mehr als die berüchtigten Singleton- oder Fabrikmuster. Was böse ist, sind die Architekten, die den Entwicklern Frameworks in den Rachen schieben, die sie dazu zwingen, DTOs für alles zu erstellen. Für das, was sie tun, Daten zu übertragen, sind DTOs (wenn sie umsichtig durchgeführt werden) die perfekte Lösung.
Michael Meadows
0

DTO-Klassen werden zum Serialisieren / Deserialisieren von Daten aus verschiedenen Quellen verwendet. Wenn Sie ein Objekt aus einer Quelle deserialisieren möchten, spielt es keine Rolle, um welche externe Quelle es sich handelt: Dienst, Datei, Datenbank usw. Möglicherweise möchten Sie nur einen Teil davon verwenden, aber Sie möchten eine einfache Möglichkeit, diese Daten in eine zu deserialisieren Objekt. Danach kopieren Sie diese Daten in das XModel, das Sie verwenden möchten. Ein Serializer ist eine schöne Technologie zum Laden von DTO-Objekten. Warum? Sie benötigen nur eine Funktion, um das Objekt zu laden (zu deserialisieren).

Herman Van Der Blom
quelle
0

TL; DR:

Ein DTO beschreibt das Muster der Zustandsübertragung. Ein POCO beschreibt nichts. Es ist eine andere Art, in OOP "Objekt" zu sagen. Es stammt von POJO (Java), geprägt von Martin Fowler, der es buchstäblich nur als schickeren Namen für "Objekt" beschreibt, weil "Objekt" nicht sehr sexy ist.

Ein DTO ist ein Objektmuster, das zum Übertragen des Zustands zwischen betroffenen Schichten verwendet wird. Sie können Verhalten haben (dh technisch gesehen ein Poco sein), solange dieses Verhalten den Zustand nicht mutiert. Beispielsweise kann es eine Methode geben, die sich selbst serialisiert.

Ein POCO ist ein einfaches Objekt, aber was mit "einfach" gemeint ist, ist, dass es nichts Besonderes ist. Es bedeutet nur, dass es sich um ein CLR-Objekt ohne implizites Muster handelt. Ein Oberbegriff. Es ist nicht dafür gemacht, mit einem anderen Framework zu arbeiten. Wenn Ihr POCO beispielsweise über [JsonProperty]alle Eigenschaften hinweg EF-Dekorationen aufweist, würde ich argumentieren, dass es sich nicht um einen POCO handelt.

Hier einige Beispiele für verschiedene Arten von Objektmustern zum Vergleichen:

  • Modell anzeigen : zum Modelldaten für eine Ansicht. Verfügt normalerweise über Datenanmerkungen, um die Bindung und Validierung zu unterstützen. In MVVM fungiert es auch als Controller. Es ist mehr als ein DTO
  • Wertobjekt : Wird zur Darstellung von Werten verwendet
  • Gesamtwurzel : Wird zum Verwalten von Status und Invarianten verwendet
  • Handler : zum Antworten auf ein Ereignis / eine Nachricht
  • Attribute : werden als Dekoration verwendet, um sich mit Querschnittsthemen zu befassen
  • Service : Wird zur Ausführung komplexer Aufgaben verwendet
  • Controller : Wird verwendet, um den Fluss von Anforderungen und Antworten zu steuern
  • Factory : Wird verwendet, um komplexe Objekte für die Verwendung zu konfigurieren und / oder zusammenzusetzen, wenn ein Konstruktor nicht gut genug ist. Wird auch verwendet, um Entscheidungen darüber zu treffen, welche Objekte zur Laufzeit erstellt werden müssen.
  • Repository / DAO : Wird verwendet, um auf Daten zuzugreifen

Dies sind alles nur Objekte, aber beachten Sie, dass die meisten von ihnen im Allgemeinen an ein Muster gebunden sind. Sie könnten sie also "Objekte" nennen oder ihre Absicht genauer beschreiben und sie so nennen, wie sie ist. Dies ist auch der Grund, warum wir Designmuster haben. komplexe Konzepte in wenigen Werken zu beschreiben. DTO ist ein Muster. Die aggregierte Wurzel ist ein Muster, das Ansichtsmodell ist ein Muster (z. B. MVC & MVVM). POCO ist kein Muster.

Ein POCO beschreibt kein Muster. Es ist nur eine andere Art, auf Klassen / Objekte in OOP zu verweisen. Betrachten Sie es als ein abstraktes Konzept; Sie können sich auf alles beziehen. IMO, es gibt jedoch eine Einbahnstraßenbeziehung, denn sobald ein Objekt den Punkt erreicht, an dem es nur noch einem Zweck sauber dienen kann, ist es kein POCO mehr. Wenn Sie beispielsweise Ihre Klasse mit Dekorationen versehen, damit sie mit einem bestimmten Framework funktioniert, ist sie kein POCO mehr. Deshalb:

  • Ein DTO ist ein POCO
  • Ein POCO ist kein DTO
  • Ein Ansichtsmodell ist ein POCO
  • Ein POCO ist kein Ansichtsmodell

Bei der Unterscheidung zwischen den beiden geht es darum, die Muster klar und konsistent zu halten, um Bedenken nicht zu überschreiten und zu einer engen Kopplung zu führen. Zum Beispiel, wenn Sie ein Geschäftsobjekt haben, das Methoden zum Mutieren des Status enthält, aber auch mit EF-Dekorationen zum Speichern in SQL Server UND JsonProperty zur Hölle dekoriert ist, damit es über einen API-Endpunkt zurückgesendet werden kann. Dieses Objekt würde Änderungen nicht tolerieren und wahrscheinlich mit Varianten von Eigenschaften übersät sein (z. B. UserId, UserPk, UserKey, UserGuid, wobei einige von ihnen als nicht in der Datenbank gespeichert und andere als nicht serialisiert markiert sind JSON am API-Endpunkt).

Wenn Sie mir also sagen würden, dass etwas ein DTO ist, würde ich wahrscheinlich sicherstellen, dass es nie für etwas anderes als das Bewegen des Zustands verwendet wird. Wenn Sie mir sagen würden, dass etwas ein Ansichtsmodell ist, würde ich wahrscheinlich sicherstellen, dass es nicht in einer Datenbank gespeichert wird. Wenn Sie mir sagen würden, dass etwas ein Domain-Modell ist, würde ich wahrscheinlich sicherstellen, dass es keine Abhängigkeiten von irgendetwas außerhalb der Domain hat. Aber wenn Sie mir sagen würden, dass etwas ein POCO ist, würden Sie mir nicht wirklich viel erzählen.

Sinaesthetic
quelle
-13

Nennen Sie sie nicht einmal DTOs. Sie heißen Models ... Periode. Modelle haben niemals Verhalten. Ich weiß nicht, wer auf diesen dummen Begriff DTO gekommen ist, aber es muss eine .NET-Sache sein, das ist alles, was ich mir vorstellen kann. Denken Sie an Ansichtsmodelle in MVC, dasselbe Dam **, Modelle werden verwendet, um den Status zwischen Schichten auf der Serverseite oder über die Drahtperiode zu übertragen. Sie sind alle Modelle. Eigenschaften mit Daten. Dies sind Modelle, die Sie über den Draht führen. Modelle, Modelle Modelle. Das ist es.

Ich wünschte, der blöde Begriff DTO würde aus unserem Wortschatz verschwinden.

PositiveGuy
quelle
1
Ich weiß nicht, woher du diese Idee hast, dass Modelle niemals Verhalten haben. Wie modelliert man etwas anderes als CRUD ohne Modellierungsverhalten? Sogar ViewModels verhalten sich in vielen Fällen, insbesondere in MVVM-Apps. DTO ist ein nützlicher Begriff, da er den Zweck genau beschreibt. Daten übertragen.
Gerald
9
für sachlich falsch und für die päpstliche Haltung herabgestimmt.
Joedotnot
Unsinn. Modelle sollten dumme Container sein. Es gibt kein DTO, es ist ein MS-Begriff. Sie übertragen Modelle zwischen Domänen, Diensten und Apps. Zeitraum. DTO ist eine Verschwendung von Begriffen, die nicht benötigt wird und die Dinge nur noch mehr verwirrt. Modelle, Modelle und mehr Modelle das war's. Modelle können Verhalten haben oder nicht. Modelle anzeigen sollte nicht. Dieses Verhalten sollte in einem BL erfolgen, nicht in der Model-Klasse.
PositiveGuy
Ich bin damit einverstanden, dass DTOs funktionale Modelle sind. ViewModels haben Verhalten und sind das, woran Sie in MVVM binden. Ich habe jedoch eine App geschrieben, in der meine Modelle intelligenter waren (im Grunde genommen VMs, aber ich wollte sie nicht aufrufen als) und sie ein DTO-Objekt "akzeptierten". Dies ermöglichte mir mehr Optionen mit dem Framework. Von CRUD (oder sogar EF) würde ich das Objekt über WCF-Dienste übertragen und das DTO-Objekt empfangen und kapseln (Hinzufügen von OnProp Change usw.). Meine ViewModels haben eine weitere Kapselung durchgeführt und möglicherweise zwei (oder eine Liste) von "Modellen" akzeptiert. Die starre Definition wäre VMs.
SQLMason
"Sie übertragen Modelle zwischen Domänen, Diensten und Apps" Warum ist der Begriff Modell für dieses von Ihnen beschriebene Verhalten geeigneter und passender als der Begriff DTO?
Ca.