Objeto CLR antiguo simple versus objeto de transferencia de datos

405

POCO = Objeto CLR antiguo simple (o mejor: clase)

DTO = Objeto de transferencia de datos

En esta publicación hay una diferencia, pero, francamente, la mayoría de los blogs que leo describen POCO en la forma en que se define el DTO: los DTO son contenedores de datos simples que se utilizan para mover datos entre las capas de una aplicación.

¿Son POCO y DTO lo mismo?

Patrick Peters
fuente
55
"POCO = Objeto CLR antiguo simple (o mejor: clase)". Por lo tanto, los objetos de esta naturaleza en VB.NET también serían POCO, no POVO.
J. Polfer

Respuestas:

568

Un POCO sigue las reglas de OOP. Debe (pero no tiene que) tener estado y comportamiento. POCO proviene de POJO, acuñado por Martin Fowler [ anécdota aquí ]. Utilizó el término POJO como una forma de hacer que sea más sexy rechazar las implementaciones pesadas de EJB del marco. POCO debe usarse en el mismo contexto en .Net. No permita que los marcos dicten el diseño de su objeto.

El único propósito de un DTO es transferir el estado y no debe tener ningún comportamiento. Vea la explicación de Martin Fowler de un DTO para un ejemplo del uso de este patrón.

Aquí está la diferencia: POCO describe un enfoque de programación (buena programación orientada a objetos a la antigua), donde DTO es un patrón que se usa para "transferir datos" usando objetos.

Si bien puede tratar a los POCO como DTO, corre el riesgo de crear un modelo de dominio anémico si lo hace. Además, hay una falta de coincidencia en la estructura, ya que los DTO deben diseñarse para transferir datos, no para representar la verdadera estructura del dominio empresarial. El resultado de esto es que los DTO tienden a ser más planos que su dominio real.

En un dominio de cualquier complejidad razonable, casi siempre es mejor crear POCO de dominio separados y traducirlos a DTO. DDD (diseño impulsado por dominio) define la capa anticorrupción (otro enlace aquí , pero lo mejor que puede hacer es comprar el libro ), que es una buena estructura que aclara la segregación.

Michael Meadows
fuente
Sé que hice referencia a Martin Fowler mucho aquí, pero acuñó el término POJO y escribió el libro PoEAA que es la referencia definitiva para DTO.
Michael Meadows el
No estoy seguro de si un DTO no debería tener comportamientos. A juzgar por el diagrama de Martin Fowler, DTO podría tener comportamientos.
Beatles1692
39
@ Beatles1692, los métodos representados son el código de serialización. Probablemente sea una declaración demasiado amplia para decir "no comportamiento". ¿Qué tal "sin lógica de negocios"? El código de serialización y los objetos de bajo nivel como el código hash, la igualdad y la cadena deberían ser aceptables.
Michael Meadows
1
@PositiveGuy Un modelo tiene un propósito diferente al de un DTO. El DTO debe ser para transferir datos de un dominio a otro (ya sea que estén o no en el mismo tiempo de ejecución es irrelevante). Un modelo "representa" un aspecto de un dominio, como una pantalla, servicio o fuente de datos. Los modelos incluyen estado y comportamiento, que son representativos de lo que están modelando.
Michael Meadows
2
Tenga en cuenta que los modelos de dominio anémico no son necesariamente malos, especialmente si su aplicación es principalmente CRUD. Favorezca la simplicidad sobre Martin Fowler.
Mariusz Jamro
50

Probablemente sea redundante para mí contribuir, ya que dije mi posición en el artículo de mi blog, pero el párrafo final de ese artículo resume las cosas:

Entonces, en conclusión, aprenda a amar al POCO y asegúrese de no difundir ninguna información errónea sobre si es lo mismo que un DTO. Los DTO son contenedores de datos simples que se utilizan para mover datos entre las capas de una aplicación. Los POCO son objetos comerciales completos con el único requisito de que sean ignorantes de persistencia (sin métodos de obtención o guardado). Por último, si aún no ha revisado el libro de Jimmy Nilsson, recójalo en las pilas de su universidad local. Tiene ejemplos en C # y es una gran lectura.

Por cierto, Patrick, leí el POCO como un artículo de estilo de vida, y estoy completamente de acuerdo, es un artículo fantástico. En realidad es una sección del libro de Jimmy Nilsson que recomendé. No tenía idea de que estaba disponible en línea. Su libro es realmente la mejor fuente de información que he encontrado sobre POCO / DTO / Repository / y otras prácticas de desarrollo DDD.


fuente
44
Enlace al artículo del blog: rlacovara.blogspot.com/2009/03/…
Jamie Ide
28

POCO es simplemente un objeto que no depende de un marco externo. Es llano.

Si un POCO tiene comportamiento o no, es irrelevante.

Un DTO puede ser POCO al igual que un objeto de dominio (que normalmente sería rico en comportamiento).

Por lo general, es más probable que los DTO tomen dependencias de marcos externos (p. Ej., Atributos) con fines de serialización, ya que generalmente salen del límite de un sistema.

En las arquitecturas típicas de estilo Onion (a menudo utilizadas dentro de un enfoque ampliamente DDD), la capa de dominio se coloca en el centro y, por lo tanto, sus objetos no deberían tener dependencias fuera de esa capa.

Neil
fuente
6

Creo que un DTO puede ser un POCO. DTO es más sobre el uso del objeto, mientras que POCO es más sobre el estilo del objeto (desacoplado de los conceptos arquitectónicos).

Un ejemplo en el que un POCO es algo diferente al DTO es cuando habla de los POCO dentro de su modelo de dominio / modelo de lógica de negocios, que es una buena representación OO de su dominio problemático. Podría usar los POCO en toda la aplicación, pero esto podría tener algunos efectos secundarios indeseables, tales filtraciones de conocimiento. Los DTO se utilizan, por ejemplo, desde la capa de servicio con la que se comunica la IU, los DTO son una representación plana de los datos, y solo se utilizan para proporcionar datos a la IU y comunicar los cambios a la capa de servicio. La capa de servicio se encarga de asignar las dos formas del DTO a los objetos de dominio POCO.

Actualización Martin Fowler dijo que este enfoque es un camino difícil de tomar, y solo debe tomarse si hay una falta de coincidencia significativa entre la capa de dominio y la interfaz de usuario.

Davy Landman
fuente
2
@David Landman, el enlace que incluyó es para el patrón DTO local, que es cuando se utilizan DTO para el estado de transferencia dentro de los límites de su sistema. En estos casos, debe tener mucho cuidado, ya que dentro de su sistema ya debe tener un dominio bien definido que se pueda compartir. Al transferir el estado a través de los límites del sistema, el DTO es difícil de evitar y bastante apropiado en todos los casos.
Michael Meadows
@Michal Meadows, sí, el enlace habla de un subconjunto diferente de problemas. Pero creo que en el caso de transferir el estado a través de un límite del sistema, debe usar un servicio de traducción para asignar el POCO de un contexto al POCO de otro contexto. ¿O estás hablando de limites a nivel de sistema?
Davy Landman
1

Un caso de uso primario para un DTO es devolver datos de un servicio web. En este caso, POCO y DTO son equivalentes. Cualquier comportamiento en el POCO se eliminará cuando se devuelva desde un servicio web, por lo que realmente no importa si tiene o no comportamiento.

John Saunders
fuente
55
Creo que su respuesta tergiversa lo que sucede un poco. En el caso de un servicio web, se genera un proxy basado en el estado expuesto de un objeto. Esto significa que se crea un DTO separado del POCO que simplemente tiene el mismo estado público que el POCO. Puede parecer sutil, pero es importante. La razón es que, incluso si el proxy es idéntico al original, en realidad no está construido a partir de la misma clase.
Michael Meadows
UH no. Uno usa un DTO para devolver / recibir datos entre niveles, en este caso, un servicio web. Uno elige un DTO porque solo tiene datos y no tiene comportamiento. Es cierto que la clase proxy también será un DTO, y que si hubiera utilizado una clase POCO, se habría creado un proxy. Pero en este caso, la clase POCO es efectivamente un DTO, ya que su comportamiento no se traducirá. Todavía digo que use un DTO porque no se perderá el comportamiento que nunca existió.
John Saunders
55
** Semánticamente: los servicios web exponen bolsas de estado de objetos usando WSDL. Los poderes se generan a partir de estos. Estos no pueden incluir el comportamiento. Si consume un servicio web, la única relación entre su objeto y el objeto de dominio expuesto es que tiene el mismo estado público creado en función de la inspección.
Michael Meadows
77
@ John, creo que estás exagerando. Estoy diciendo que tienes razón, pero tu redacción es engañosa. "En este caso, POCO y DTO son equivalentes". Semánticamente, eso no es cierto. Los POCO se pueden usar como DTO y viceversa, pero eso no significa que sean equivalentes ... no más que un automóvil y una camioneta son equivalentes, aunque ambos se pueden usar para llevarlo a la tienda de comestibles. Tienen una función superpuesta, pero sería difícil encontrar a alguien que le diga que una idea es equivalente a un F350, incluso en el contexto del viaje de supermercado.
Michael Meadows
3
Esta respuesta es muy incorrecta, un servicio web no es lo suficientemente genérico para uno. Lo más importante es un hecho bien establecido de que DTO NO es un POCO. DTO es un contenedor de datos, mientras que POCO son objetos como propiedades y son ignorantes de persistencia (no hay métodos get o save).
Tom Stickel
1

Aquí está la regla general: DTO == mal e indicador de software sobre-diseñado. POCO == bueno. Los patrones de 'empresa' han destruido los cerebros de muchas personas en el mundo Java EE. por favor no repita el error en .NET land.

benmmurphy
fuente
77
¿Podrías dar más detalles, por favor? Se requieren DTO cuando se devuelven datos de un servicio web, para evitar la implementación y los detalles de la plataforma en el contrato.
John Saunders, el
1
Sí, los DTO de John están diseñados para lo que usted dice y funcionan bien. Pero desafortunadamente a menudo se usan cuando no se requieren en aplicaciones web de un solo nivel y tienen poco valor.
Craig
99
Creo, @drscroogemcduck, que quizás no te gustan los DTO porque se usan como primer recurso en lugar de un último recurso, pero no son intrínsecamente malvados ... no más que los infames patrones singleton o de fábrica. Lo que es malo son los arquitectos que empujan los marcos por las gargantas de los desarrolladores que los obligan a hacer DTO para todo. Para lo que hacen, la transferencia de datos, los DTO (si se hace con prudencia) son el ajuste perfecto.
Michael Meadows
0

Las clases DTO se utilizan para serializar / deserializar datos de diferentes fuentes. Cuando desee deserializar un objeto de una fuente, no importa de qué fuente externa se trate: servicio, archivo, base de datos, etc. Es posible que solo desee utilizar alguna parte de eso, pero desea una manera fácil de deserializar esos datos a un objeto. después de eso, copie esos datos en el XModel que desea usar. Un serializador es una hermosa tecnología para cargar objetos DTO. ¿Por qué? solo necesita una función para cargar (deserializar) el objeto.

Herman Van Der Blom
fuente
0

TL; DR:

Un DTO describe el patrón de transferencia de estado. Un POCO no describe nada. Es otra forma de decir "objeto" en OOP. Proviene de POJO (Java), acuñado por Martin Fowler, quien literalmente lo describe como un nombre más elegante para 'objeto' porque 'objeto' no es muy sexy.

Un DTO es un patrón de objeto utilizado para transferir el estado entre capas de interés. Pueden tener un comportamiento (es decir, técnicamente puede ser un poco) siempre que ese comportamiento no mute el estado. Por ejemplo, puede tener un método que se serialice a sí mismo.

Un POCO es un objeto simple, pero lo que se entiende por 'simple' es que no es especial. Simplemente significa que es un objeto CLR sin patrón implícito. Un término genérico No está hecho para trabajar con algún otro marco. Entonces, si tu POCO tiene[JsonProperty] o decoraciones EF en todas sus propiedades, por ejemplo, entonces diría que no es un POCO.

Aquí hay algunos ejemplos de diferentes tipos de patrones de objetos para comparar:

  • Ver modelo : se utiliza para modelar datos para una vista. Por lo general, tiene anotaciones de datos para ayudar al enlace y la validación. En MVVM, también actúa como un controlador. Es más que un DTO
  • Objeto de valor : se usa para representar valores
  • Raíz Agregada : se usa para administrar estados e invariantes
  • Manipuladores : utilizados para responder a un evento / mensaje
  • Atributos : se usan como decoraciones para tratar problemas transversales
  • Servicio : utilizado para realizar tareas complejas.
  • Controlador : se usa para controlar el flujo de solicitudes y respuestas
  • Fábrica : se usa para configurar y / o ensamblar objetos complejos para usar cuando un constructor no es lo suficientemente bueno. También se usa para tomar decisiones sobre qué objetos deben crearse en tiempo de ejecución.
  • Repositorio / DAO : utilizado para acceder a datos

Todos estos son solo objetos, pero tenga en cuenta que la mayoría de ellos generalmente están vinculados a un patrón. Entonces podría llamarlos "objetos" o podría ser más específico sobre su intención y llamarlo por lo que es. Por eso también tenemos patrones de diseño; para describir conceptos complejos en algunas obras. DTO es un patrón. La raíz agregada es un patrón, Ver modelo es un patrón (por ejemplo, MVC y MVVM). POCO no es un patrón.

Un POCO no describe un patrón. Es solo una forma diferente de referirse a clases / objetos en OOP. Piense en ello como un concepto abstracto; Pueden referirse a cualquier cosa. En mi opinión, hay una relación unidireccional porque una vez que un objeto alcanza el punto donde solo puede cumplir un propósito de manera limpia, ya no es un POCO. Por ejemplo, una vez que marca su clase con decoraciones para que funcione con algún marco, ya no es un POCO. Por lo tanto:

  • Un DTO es un POCO
  • Un POCO no es un DTO
  • Un modelo de vista es un POCO
  • Un POCO no es un modelo de vista

El punto de hacer una distinción entre los dos es mantener patrones claros y consistentes en un esfuerzo por no cruzar preocupaciones y conducir a un acoplamiento estrecho. Por ejemplo, si tiene un objeto comercial que tiene métodos para mutar el estado, pero también está decorado al infierno con decoraciones EF para guardar en SQL Server Y JsonProperty para que pueda enviarse de regreso a través de un punto final API. Ese objeto sería intolerante a los cambios y probablemente estaría lleno de variantes de propiedades (por ejemplo, UserId, UserPk, UserKey, UserGuid, donde algunos de ellos están marcados para no guardarse en la base de datos y otros marcados para no ser serializados en JSON en el punto final de la API).

Entonces, si me dijeras que algo es un DTO, entonces probablemente me aseguraría de que nunca se usara para otra cosa que no sea mover el estado. Si me dijiste que algo era un modelo de vista, entonces probablemente me aseguraría de que no se guardara en una base de datos. Si me dijiste que algo era un Modelo de dominio, entonces probablemente me aseguraría de que no tuviera dependencias de nada fuera del dominio. Pero si me dijeras que algo es un POCO, realmente no me estarías diciendo mucho.

Sinestésico
fuente
-13

Ni siquiera los llames DTO. Se llaman Modelos ... Punto. Las modelos nunca tienen comportamiento. No sé quién se le ocurrió este término tonto DTO, pero debe ser una cosa .NET es todo lo que puedo imaginar. Piense en ver modelos en MVC, lo mismo, los modelos se usan para transferir el estado entre las capas del lado del servidor o durante el período de conexión, todos son modelos. Propiedades con datos. Estos son modelos que pasas por encima del cable. Modelos, Modelos Modelos. Eso es.

Desearía que el estúpido término DTO desapareciera de nuestro vocabulario.

PositivoGuy
fuente
1
No sé de dónde sacaste esta idea de que las modelos nunca tienen comportamiento. ¿Cómo modelas algo que no sea CRUD sin modelar el comportamiento? Incluso ViewModels tienen comportamiento en muchos casos, particularmente en aplicaciones MVVM. DTO es un término útil porque describe con precisión el propósito; para transferir datos.
Gerald
99
rechazado por ser objetivamente incorrecto y por la actitud pontificante.
joedotnot
Disparates. Los modelos deben ser contenedores estúpidos. No hay DTO, es un término inventado por la EM. Transfiere modelos entre dominios, servicios y aplicaciones. Período. DTO es una pérdida de tiempo que no es necesaria y solo confunde más las cosas. Modelos, Modelos y más Modelos eso es todo. Los modelos pueden o no tener comportamiento. Ver modelos no debería. Ese comportamiento debe estar en un BL, no en la clase Modelo.
PositiveGuy
Estoy de acuerdo en que los DTO son modelos funcionales. ViewModels tiene un comportamiento y es a lo que se une en MVVM. SIN EMBARGO, escribí una aplicación donde mis modelos eran más inteligentes (básicamente máquinas virtuales, pero no quería llamarlos) y "aceptaron" un objeto DTO. Esto me permitió tener más opciones con el marco. Entonces, desde CRUD (o incluso EF), transmitiría el objeto a través de servicios WCF y recibiría el objeto DTO y lo encapsularía (agregando OnProp Change, etc.). My ViewModels realizó una encapsulación adicional y puede haber aceptado dos (o una lista) de "Modelos". La definición rígida sería VM.
SQLMason
"Transfiere modelos entre dominios, servicios y aplicaciones" ¿Por qué cree que el término modelo es más apropiado y adecuado que el término DTO para este comportamiento que describe?
caa