¿Por qué los objetos de transferencia de datos (DTO) son un antipatrón?

132

Recientemente escuché a personas decir que los objetos de transferencia de datos (DTO) son un antipatrón .

¿Por qué? Cuales son las alternativas?

ntownsend
fuente
11
Quizás porque los objetos comerciales son capaces de transportar sus propios datos, ¡muchas gracias!
Zoidberg
13
"Anti-patrón" bien podría ser mi candidato para "frase cuyos 15 minutos terminaron hace mucho tiempo". Es sinónimo de "No me molesto en justificar mi pensamiento" por ahora, como "Es bien sabido que ..."
Craig Stuntz
66
Zoidberg, enviar objetos con métodos por cable nos dio CORBA, DCOM y otras experiencias que intento borrar de mi memoria. El problema es que, tarde o temprano, la gente quiere llamar a esos métodos.
Craig Stuntz
10
Los DTO encarnan el principio DRY, que desafortunadamente en J2EE significa que se repita.
joeforker
Es posible que desee leer esto: El objeto de transferencia de datos es una pena
yegor256

Respuestas:

139

Algunos proyectos tienen todos los datos dos veces . Una vez como objetos de dominio, y una vez como objetos de transferencia de datos.

Esta duplicación tiene un costo enorme , por lo que la arquitectura necesita obtener un gran beneficio de esta separación para que valga la pena.

KLE
fuente
55
Por favor, explique el "gran costo". Además, diga por qué el costo no se puede eliminar mediante el uso de técnicas de generación de código para generar las clases DTO.
John Saunders
70
+1. ¿Dos veces? Solo si tiene suerte :-) Los proyectos que duplican entidades de dominio como DTO también tienden a tener beans UI casi iguales pero sutilmente diferentes para complementarlos. Eso es 3. Y si, Dios no lo quiera, hay algún tipo de comunicación remota (servicios Web / XML-RPC / lo que sea) en marcha, se puede llegar fácilmente a 4 o 5.
ChssPly76
17
Actualmente estoy trabajando con una arquitectura de lasaña emprendedora de 14 capas (NO KIDDING). Les puedo asegurar que las 11 capas más o menos que son principalmente para la transferencia de datos no son gratuitas.
KarlP
10
Además, si bien me encantan los generadores de código cuando trabajo con diseños estúpidos, son a) una cosa segura con la que estás haciendo mal para empezar. b) no vienen gratis.
KarlP
77
Lo sentimos, pero esto es incorrecto y la respuesta incorrecta fue votada alta y aceptada. En primer lugar, puede usar la reflexión para generar DTO sobre la marcha. En segundo lugar, puede usar una "definición raíz", por ejemplo, en un sistema CASE o en oAW y generar el BO y el DTO (s). En tercer lugar, puede usar un XSD y JAXB para generar DTO y usar el DTO como base para un BO, o puede generar ambos desde el XSD ... de todos modos, si alguien se atreviera a transferir un EJB recién obtenido del DB sobre cable a un programa de cliente ... en los entornos en los que trabajo, su cabeza estaría en una placa de plata muy pronto ...
Angel O'Sphere
128

Los DTO no son un antipatrón. Cuando envía algunos datos a través del cable (por ejemplo, a una página web en una llamada Ajax), desea asegurarse de conservar el ancho de banda enviando solo datos que utilizará el destino. Además, a menudo es conveniente que la capa de presentación tenga los datos en un formato ligeramente diferente al de un objeto comercial nativo.

Sé que esta es una pregunta orientada a Java, pero en los lenguajes .NET, los tipos anónimos, la serialización y LINQ permiten que los DTO se construyan sobre la marcha, lo que reduce la configuración y la sobrecarga de usarlos.

Gabe Moothart
fuente
15
@ John, esto es incorrecto. Lo hago todo el tiempo. La serialización utiliza la reflexión, que funciona bien en tipos anónimos. Simplemente páselo al serializador como un objeto. Y una vez que se serializa (a xml o json, por ejemplo), por supuesto, puede devolverlo desde un método.
Gabe Moothart
8
Um, John, eso no es cierto. Puede serializar tipos anónimos a JSON muy bien. Pruébelo en una aplicación MVC: devuelva Json (nuevo {Foo = "¡Hola!}); Le prometo que funciona bien. Mejor, tal vez, que los tipos no anónimos, ya que los tipos anónimos generalmente no tienen ciclos en sus gráficos de objetos. , que rompen el serializador JSON.
Craig Stuntz
1
La serialización de Json no es un DTO en este sentido y, por lo tanto, no se aplica. Entonces, por supuesto, mis argumentos anteriores también se aplican, en algún momento, simplemente dejan de valer la pena.
Jim Barrows
1
Gabe tiene razón, DTO no es un antipatrón per se (¡pero puede serlo si se usa incorrectamente!) Cuando no hay duplicación de datos. Por ejemplo, BO puede agregar datos de diferentes fuentes en un DTO.
astro
3
+1. Y hay muchas otras razones además de la conservación del ancho de banda por las que querrás DTO. ¿Está incluso PERMITIDO (por política o ley de la compañía) enviar todos los campos a través del cable? Además, en nuestra empresa, nuestro DAO es muy complejo porque necesita hacer todas estas optimizaciones: trabajando en la capa de servicio, estoy realmente contento de que usen un DTO y no nos preocupen por la relación que tiene Object X a alguna otra tabla n-n.
user64141
25

DTO un AntiPattern en EJB 3.0 dice:

La naturaleza pesada de Entity Beans en las especificaciones EJB anteriores a EJB 3.0, resultó en el uso de patrones de diseño como Data Transfer Objects (DTO). Los DTO se convirtieron en los objetos ligeros (que deberían haber sido los beans de entidad en sí mismos), utilizados para enviar los datos a través de los niveles ... ahora la especificación EJB 3.0 hace que el modelo de bean Entity sea el mismo objeto Java simple (POJO). Con este nuevo modelo POJO, ya no necesitará crear un DTO para cada entidad o para un conjunto de entidades ... Si desea enviar las entidades EJB 3.0 a través del nivel, simplemente implemente java.io.Serialiazable

aem
fuente
66
Es cierto cuando transfiere objetos entre métodos en la misma JVM, en la memoria. No es cierto cuando realmente está serializando a través del cable y desea controlar la profundidad de la serialización y / o preservar la carga diferida.
wrschneider
Sí, e incluso en la misma JVM, realmente debe tener cuidado de mantenerse en la misma situación si usa la gestión transaccional JEE / Spring.
Marc
20

No creo que los DTO sean un antipatrón per se, pero hay antipatrones asociados con el uso de DTO. Bill Dudney se refiere a la explosión de DTO como un ejemplo:

http://www.softwaresummit.com/2003/speakers/DudneyJ2EEAntiPatterns.pdf

También hay una serie de abusos de DTO mencionados aquí:

http://anirudhvyas.com/root/2008/04/19/abuses-of-dto-pattern-in-java-world/

Se originaron debido a los sistemas de tres niveles (típicamente usando EJB como tecnología) como un medio para pasar datos entre niveles. La mayoría de los sistemas Java modernos basados ​​en marcos como Spring toman una vista simplificada alternativa utilizando POJO como objetos de dominio (a menudo anotados con JPA, etc.) en un solo nivel ... El uso de DTO aquí es innecesario.

Jon
fuente
3
Tiene toda la razón en que los DTO son un buen patrón , no un antipatrón, cuando se usan en su contexto adecuado. Su segundo enlace parece muerto en este momento, pero el mayor abuso que he visto es donde cada objeto de dominio tenía un "DTO" correspondiente para la interacción de la base de datos que no agregaba valor y no era un DTO en absoluto.
David
19

Los puristas de OO dirían que DTO es antipatrón porque los objetos se convierten en representaciones de tablas de datos en lugar de objetos de dominio real.

Darin Dimitrov
fuente
9

Algunos consideran que los DTO son un antipatrón debido a sus posibles abusos. A menudo se usan cuando no deberían ser / no necesitan ser.

Este artículo describe vagamente algunos abusos.

Ben S
fuente
1
El artículo describe con mucha más precisión los DTO como un patrón que puede ser abusado.
Craig Stuntz
Esto equivale a una respuesta de solo enlace, realmente necesita al menos una cita del artículo. no sé cómo esto logró que no se marcara como No una respuesta.
Nathan Hughes
7

Si está creando un sistema distribuido, los DTO ciertamente no son un antipatrón. No todos se desarrollarán en ese sentido, pero si tienes una (por ejemplo) aplicación Open Social que se ejecute sin JavaScript.

Publicará una carga de datos en su API. Esto luego se deserializa en alguna forma de objeto, típicamente un objeto DTO / Solicitud. Esto se puede validar para garantizar que los datos ingresados ​​sean correctos antes de convertirlos en un objeto modelo.

En mi opinión, se ve como un antipatrón porque se usa mal. Si no está creando un sistema distribuido, es probable que no los necesite.

Bealer
fuente
4

La intención de un Objeto de transferencia de datos es almacenar datos de diferentes fuentes y luego transferirlos a una base de datos (o Fachada remota ) a la vez.

Sin embargo, el patrón DTO viola el Principio de Responsabilidad Única , ya que el DTO no solo almacena datos, sino que también los transfiere desde o hacia la base de datos / fachada.

La necesidad de separar los objetos de datos de los objetos comerciales no es un antipatrón, ya que de todos modos es probable que sea necesario separar la capa de la base de datos .

En lugar de DTO, debe usar los Patrones de Agregado y Repositorio, que separa la colección de objetos ( Agregado ) y la transferencia de datos ( Repositorio ).

Para transferir un grupo de objetos, puede usar el patrón Unidad de trabajo , que contiene un conjunto de repositorios y un contexto de transacción; para transferir cada objeto en el agregado por separado dentro de la transacción.

MovGP0
fuente
4

DTO se convierte en una necesidad y no en un ANTI-PATRÓN cuando tiene todos sus objetos de dominio cargan EAGERly objetos asociados.

Si no realiza DTO, tendrá objetos transferidos innecesarios desde su capa empresarial a su capa cliente / web.

Para limitar los gastos generales para este caso, transfiera los DTO.

javadev
fuente
1

La pregunta no debería ser "por qué", sino " cuándo ".

Definitivamente es antipatrón cuando el único resultado de usarlo es un mayor costo : tiempo de ejecución o mantenimiento. Trabajé en proyectos que tenían cientos de DTO idénticos a las clases de entidad de base de datos. Cada vez que deseaba agregar un solo campo, agregaba la identificación como cuatro veces: a DTO, a entidad, a conversión de DTO a clases o entidades de dominio, la conversión inversa, ... Olvidó algunos de los lugares y datos obtenidos inconsistente.

No es antipatrón cuando realmente necesita una representación diferente de las clases de dominio. : más plana, más rica, más estrecha, ...

Personalmente, comienzo con la clase de dominio y la paso, con la verificación adecuada en los lugares correctos. Puedo anotar y / o agregar algunas clases "auxiliares" para hacer asignaciones, a bases de datos, a formatos de serialización como JSON o XML ... Siempre puedo dividir una clase en dos si siento la necesidad.

Se trata de su punto de vista: prefiero ver un objeto de dominio como un solo objeto que desempeña varios roles, en lugar de múltiples objetos creados entre sí. Si el único rol que tiene un objeto es transportar datos, entonces es DTO.

Rostislav Matl
fuente
1

Creo que la gente quiere decir que podría ser un antipatrón si implementa todos los objetos remotos como DTO. Un DTO es simplemente un conjunto de atributos y si tiene objetos grandes, siempre transferirá todos los atributos, incluso si no los necesita o no los usa. En este último caso, prefiera usar un patrón Proxy.

jdehaan
fuente