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?
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?
Respostas:
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.
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.
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
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.
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.
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.
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.
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.
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.
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.
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.