Por que os DTOs (objetos de transferência de dados) são um antipadrão?

132

Eu tenho pessoas dizendo que ouviu recentemente objeto de transferência de dados (DTOs) são um anti-padrão .

Por quê? Quais são as alternativas?

Ntownsend
fonte
11
Talvez porque os próprios objetos de negócios sejam capazes de transportar seus próprios dados, muito obrigado!
Zoidberg
13
"Anti-padrão" pode muito bem ser meu candidato a "frase cujos 15 minutos se passaram há muito tempo". É sinônimo de "eu não me importo se preocupar justificando o meu pensamento" por agora, como "É bem conhecido que ..."
Craig Stuntz
6
Zoidberg, enviando objetos com métodos por fio, nos deu CORBA, DCOM e outras experiências das quais tento apagar minha memória. O problema é que, mais cedo ou mais tarde, as pessoas querem chamar esses métodos.
22710 Craig Stuntz
10
DTOs encarnam o princípio de DRY, que infelizmente em J2EE significa fazer repetir-se.
joeforker
Você pode querer ler isso: Objeto de transferência de dados é uma vergonha
yegor256

Respostas:

139

Alguns projetos têm todos os dados duas vezes . Uma vez como objetos de domínio e uma vez como objetos de transferência de dados.

Como a duplicação tem um custo enorme , a arquitetura precisa obter um benefício enorme dessa separação para valer a pena.

KLE
fonte
5
Por favor, elabore o "enorme custo". Além disso, diga por que o custo não pode ser eliminado usando técnicas de geração de código para gerar as classes DTO.
John Saunders
70
+1. Duas vezes? Somente se você tiver sorte :-) Os projetos que duplicam entidades de domínio como DTO também tendem a ter beans de interface do usuário quase o mesmo, mas tão oh sutilmente diferentes para complementá-los. Isso é 3. E se, Deus me livre, não há algum tipo de comunicação remota (web services / xml-rpc / whatever) acontecendo, você pode facilmente chegar a 4 ou 5.
ChssPly76
17
Atualmente, estou trabalhando com uma arquitetura de lasanha de 14 camadas (não brincando). Posso garantir que as 11 camadas que são principalmente para o transmissor de dados não são de graça.
KarlP
10
Além disso, embora eu goste absolutamente de geradores de código ao trabalhar com projetos estúpidos, eles são a) uma coisa certa de que você está fazendo errado de início. b) eles não vêm de graça.
KarlP
7
Desculpe, mas isso está incorreto e a resposta errada foi votada e aceita. Antes de tudo, você pode usar a reflexão para gerar DTOs em tempo real. Segundo, você pode usar uma "definição de raiz", por exemplo, em um sistema CASE ou no oAW e gerar o BO e o DTO (s). Terceiro, você pode usar um XSD e JAXB para gerar DTOs e usar o DTO como base para um BO, ou você pode gerar os dois a partir do XSD ... de qualquer maneira, se alguém se atreveria a transferir um EJB recém-obtido do banco de dados fio para um programa cliente ... nos ambientes que eu trabalho, sua cabeça estaria em uma placa de prata muito em breve ...
Anjo O'Sphere
128

DTOs não são um anti-padrão. Ao enviar alguns dados pela conexão (digamos, para uma página da Web em uma chamada Ajax), você deseja garantir a conservação da largura de banda enviando apenas os dados que o destino usará. Além disso, muitas vezes é conveniente que a camada de apresentação tenha os dados em um formato ligeiramente diferente de um objeto de negócios nativo.

Eu sei que essa é uma pergunta orientada a Java, mas nas linguagens .NET tipos anônimos, serialização e LINQ permitem que os DTOs sejam construídos on-the-fly, o que reduz a configuração e a sobrecarga de usá-los.

Gabe Moothart
fonte
15
@ John, isso está incorreto. Eu faço isso o tempo todo. A serialização usa reflexão, que funciona bem em tipos anônimos. Apenas passe para o serializador como um objeto. E uma vez serializado (para xml ou json, por exemplo), é claro que você pode devolvê-lo a partir de um método.
Gabe Moothart 17/09/09
8
John, isso não é verdade. Você pode serializar tipos anônimos para JSON muito bem. Experimente em um aplicativo MVC: retorne Json (novo {Foo = "Olá!); Prometo que funciona muito bem. Melhor, talvez, que os tipos não anônimos, pois os tipos anônimos geralmente não têm ciclos em seus gráficos de objetos , que quebram o serializador JSON.
Craig Stuntz 17/09/09
1
A serialização Json não é um DTO nesse sentido e, portanto, não se aplica. Então, é claro, meus argumentos acima se aplicam também, em algum momento, eles simplesmente param de valer a pena.
21310 Jim Barrows
1
Gabe está certo, o DTO não é um anti-padrão em si (mas pode ser usado incorretamente!) Quando não há duplicação de dados. Por exemplo, o BO pode agregar dados de diferentes fontes em um DTO.
Astro
3
+1. Além de conservação da largura de banda, existem muitas outras razões pelas quais você deseja DTOs. Você PERMITIDA (pela política ou lei da empresa) enviar todos os campos pela rede? Além disso, em nossa empresa, nosso DAO é muito complexo, pois precisa fazer todas essas otimizações - trabalhando na camada de serviço, estou muito feliz que eles usem um DTO e não nos preocupem com o relacionamento que o Objeto X tem para alguma outra tabela n-para-n.
user64141
25

O DTO um AntiPattern no EJB 3.0 diz:

A natureza pesada dos Entity Beans nas especificações EJB anteriores ao EJB 3.0 resultou no uso de padrões de design, como Data Transfer Objects (DTO). Os DTOs se tornaram os objetos leves (que deveriam ter sido os beans de entidade em primeiro lugar), usados ​​para enviar os dados pelas camadas ... agora a especificação do EJB 3.0 torna o modelo do bean de entidade o mesmo que o objeto Java antigo simples (POJO). Com esse novo modelo de POJO, você não precisará mais criar um DTO para cada entidade ou para um conjunto de entidades ... Se desejar enviar as entidades do EJB 3.0 para toda a camada, basta implementar o java.io.Serialiazable

aem
fonte
6
É verdade quando você está transferindo objetos entre métodos na mesma JVM, na memória. Não é verdade quando você está realmente serializando por cabo e deseja controlar a profundidade da serialização e / ou preservar o carregamento lento.
wrschneider
Sim, e mesmo na mesma JVM, você deve ter o cuidado de permanecer na mesma situação se usar o gerenciamento transacional JEE / Spring.
Marc
20

Não acho que os DTOs sejam um antipadrão em si, mas existem antipadrões associados ao uso de DTOs. Bill Dudney refere-se à explosão do DTO como um exemplo:

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

Há também vários abusos de DTOs mencionados aqui:

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

Eles se originaram por causa de sistemas de três camadas (normalmente usando EJB como tecnologia) como um meio de passar dados entre camadas. A maioria dos sistemas Java modernos baseados em estruturas como o Spring adotam uma visão simplificada alternativa usando POJOs como objetos de domínio (geralmente anotados com JPA etc ...) em uma única camada ... O uso de DTOs aqui é desnecessário.

Jon
fonte
3
Você está completamente certo de que os DTOs são um bom padrão , não um antipadrão, quando usados ​​em seu contexto apropriado. Seu segundo link parece morto no momento, mas o maior abuso que eu vi foi onde todos os objetos de domínio tinham um "DTO" correspondente para interação com o banco de dados, que não agregava valor e não era um DTO!
David
19

Os puristas de OO diriam que o DTO é antipadrão porque os objetos se tornam representações da tabela de dados em vez de objetos de domínio real.

Darin Dimitrov
fonte
9

Alguns consideram os DTOs um antipadrão devido a seus possíveis abusos. Eles são frequentemente usados ​​quando não deveriam / não precisam.

Este artigo descreve vagamente alguns abusos.

Ben S
fonte
1
O artigo descreve com muito mais precisão os DTOs como um padrão que pode ser abusado.
22715 Craig Stuntz
Isso equivale a uma resposta apenas de link; ele realmente precisa de pelo menos uma citação do artigo. não sei como isso conseguiu não ser sinalizado como Não é uma resposta.
Nathan Hughes
7

Se você está construindo um sistema distribuído, os DTOs certamente não são um antipadrão. Nem todo mundo se desenvolverá nesse sentido, mas se você tiver um aplicativo Open Social (por exemplo) todo executando JavaScript.

Ele publicará uma carga de dados na sua API. Isso é desserializado para alguma forma de objeto, geralmente um objeto DTO / Request. Isso pode ser validado para garantir que os dados inseridos estejam corretos antes de serem convertidos em um objeto de modelo.

Na minha opinião, é visto como um anti-padrão porque é mal utilizado. Se você não constrói um sistema distribuído, é provável que não precise deles.

Bealer
fonte
4

A intenção de um objeto de transferência de dados é armazenar dados de diferentes fontes e depois transferi-los para um banco de dados (ou Fachada Remota ) de uma só vez.

No entanto, o padrão do DTO viola o Princípio de Responsabilidade Única , uma vez que o DTO não apenas armazena dados, mas também os transfere de ou para o banco de dados / fachada.

A necessidade de separar objetos de dados dos objetos de negócios não é um antipadrão, pois provavelmente é necessário separar a camada do banco de dados de qualquer maneira.

Em vez de DTOs, você deve usar os Padrões agregados e de repositório, que separam a coleção de objetos ( Agregado ) e a transferência de dados ( Repositório). ).

Para transferir um grupo de objetos, você pode usar o padrão Unidade de Trabalho , que contém um conjunto de Repositórios e um contexto de transação; para transferir cada objeto no agregado separadamente dentro da transação.

MovGP0
fonte
4

O DTO se torna uma necessidade e não um ANTI-PADRÃO quando todos os seus objetos de domínio carregam objetos associados EAGERly.

Se você não criar DTOs, terá objetos transferidos desnecessariamente da camada comercial para a camada cliente / web.

Para limitar a sobrecarga nesse caso, transfira os DTOs.

javadev
fonte
1

A questão não deve ser "por que", mas " quando ".

Definitivamente, é antipadrão quando o único resultado do uso é o custo mais alto - tempo de execução ou manutenção. Trabalhei em projetos com centenas de DTOs idênticos às classes de entidade do banco de dados. Cada vez que você deseja adicionar um único campo, você adiciona um ID como quatro vezes - ao DTO, à entidade, à conversão do DTO para classes ou entidades de domínio, a conversão inversa, ... Você esqueceu alguns dos locais e dados obtidos inconsistente.

Não é antipadrão quando você realmente precisa de uma representação diferente de classes de domínio - mais plana, mais rica, mais estreita, ...

Pessoalmente, começo com a classe de domínio e passo-a, com a devida verificação nos lugares certos. Posso anotar e / ou adicionar algumas classes "auxiliares" para fazer mapeamentos, banco de dados, formatos de serialização como JSON ou XML ... Sempre posso dividir uma classe para duas, se achar necessário.

É sobre o seu ponto de vista - prefiro olhar para um objeto de domínio como um único objeto desempenhando várias funções, em vez de vários objetos criados um do outro. Se a única função que um objeto tem é o transporte de dados, é o DTO.

Rostislav Matl
fonte
1

Acho que as pessoas querem dizer que poderia ser um anti-padrão se você implementar todos os objetos remotos como DTOs. Um DTO é apenas um conjunto de atributos e, se você tiver objetos grandes, sempre transferirá todos os atributos, mesmo que não precise ou os use. Neste último caso, prefira usar um padrão Proxy.

jdehaan
fonte