O que é o objeto de transferência de dados?

217

O que é um objeto de transferência de dados?

No MVC, as classes de modelo são DTO e, se não, quais são as diferenças e precisamos de ambas?

Yaron Naveh
fonte
@ yegor256 e o ​​fato de que o livro desse artigo sabe como recuperar dados da API e também como armazenar dados no banco de dados, violando o SRP, está bem?
Betlista 9/01/19

Respostas:

222

Um objeto de transferência de dados é um objeto usado para encapsular dados e enviá-los de um subsistema de um aplicativo para outro.

Os DTOs são mais comumente usados ​​pela camada Serviços em um aplicativo N-Tier para transferir dados entre si e a camada da interface do usuário. O principal benefício aqui é que ele reduz a quantidade de dados que precisa ser enviada através da conexão em aplicativos distribuídos. Eles também são ótimos modelos no padrão MVC.

Outro uso para DTOs pode ser o de encapsular parâmetros para chamadas de método. Isso pode ser útil se um método tiver mais de 4 ou 5 parâmetros.

Ao usar o padrão DTO, você também usaria montadores de DTO. Os montadores são usados ​​para criar DTOs a partir de Objetos de Domínio e vice-versa.

A conversão do objeto de domínio para DTO e vice-versa pode ser um processo caro. Se você não estiver criando um aplicativo distribuído, provavelmente não verá grandes benefícios com o padrão, como Martin Fowler explica aqui

Benny Hallett
fonte
7
"O DTO cria ótimos modelos no padrão MVC" - mas um modelo não deve conter todos os dados do objeto e o DTO deve ser otimizado com parte dos dados? Se eu tenho o modelo A e preciso passá-lo para dois subsistemas, haverá A_DTO_1 e A_DTO_2 com os campos relevantes de cada um? "DTOs podem ser para encapsular parâmetros para chamadas de método" -> Então, toda classe que agrupa parâmetros é DTO, mesmo que este não seja um sistema distribuído? Os modelos no MVC não são o objeto de domínio?
Yaron Naveh 30/06/09
2
Em resposta à sua primeira pergunta, acho que não estávamos falando da mesma coisa. O modelo no MVC não precisa necessariamente ser uma classe do seu Modelo de Domínio. Dito isto, bem poderia ser. O uso do DTO retira todo o material desnecessário. Depende da arquitetura que você está procurando. Não sei exatamente como responder à sua segunda pergunta. Seja através do fio ou não, ainda é um objeto que encapsula um monte de dados a serem transferidos entre (sub) sistemas, então eu diria que é um DTO.
9119 Benny Hallett
12
"Outro uso para DTOs pode ser o de encapsular parâmetros para chamadas de método. Isso pode ser útil se um método tiver mais de 4 ou 5 parâmetros." Na verdade, esse é um anti-padrão chamado classe Poltergeist ou Gypsy Wagon. Se seu método precisar de 4 argumentos, dê 4, não crie uma classe apenas para mover um objeto para um método ou uma classe.
Wix
2
@ Wix, bom ponto. Eu argumentaria, no entanto, que tudo está bem se estiver semanticamente correto (digamos, se você passa uma classe de configurações com propriedades, e não as próprias propriedades como valores). O que você não deve fazer é apresentar todos os argumentos para passar um único objeto, pois eles podem muito bem não estar relacionados e causar pesadelos desembaraçados mais tarde.
Aram Kocharyan
3
DTOs não deve ser usado para parâmetros Encapsular para chamadas de métodos (que seria torná-los LocalDTOs), eles foram introduzidos no contexto de interfaces remotas: martinfowler.com/bliki/LocalDTO.html
Rui
28

A definição para DTO pode ser encontrada no site de Martin Fowler . DTOs são usados ​​para transferir parâmetros para métodos e como tipos de retorno. Muitas pessoas as usam na interface do usuário, mas outras inflam objetos de domínio a partir delas.

azul
fonte
22

Um DTO é um objeto idiota - ele apenas contém propriedades e possui getters e setters, mas nenhuma outra lógica de qualquer significado (exceto talvez uma implementação compare () ou igual ()).

Normalmente, as classes de modelo no MVC (assumindo .net MVC aqui) são DTOs ou coleções / agregados de DTOs

Eric Petroelje
fonte
3
O que você está descrevendo é um LocalDTO: martinfowler.com/bliki/LocalDTO.html
Rui
3
Um caso em que é útil usar algo como um DTO é quando você tem uma incompatibilidade significativa entre o modelo na camada de apresentação e o modelo de domínio subjacente. Nesse caso, faz sentido criar uma fachada / gateway específico da apresentação que mapeie a partir do modelo de domínio e apresente uma interface conveniente para a apresentação.
Amitābha
14

Em geral, os Objetos de Valor devem ser Imutáveis. Como objetos Inteiros ou String em Java. Podemos usá-los para transferir dados entre as camadas de software. Se os serviços ou camadas de software em execução em nós remotos diferentes, como em um ambiente de microsserviços ou em um Java Enterprise App herdado. Devemos fazer cópias quase exatas de duas classes. Foi aqui que conhecemos os DTOs.

|-----------|                                                   |--------------|
| SERVICE 1 |--> Credentials DTO >--------> Credentials DTO >-- | AUTH SERVICE |
|-----------|                                                   |--------------|

No Java Enterprise Systems legado, os DTOs podem ter várias coisas de EJB.

Não sei se essa é uma prática recomendada ou não, mas eu pessoalmente uso o Value Objects nos meus projetos Spring MVC / Boot como este:

        |------------|         |------------------|                             |------------|
-> Form |            | -> Form |                  | -> Entity                   |            |
        | Controller |         | Service / Facade |                             | Repository |
<- View |            | <- View |                  | <- Entity / Projection View |            |
        |------------|         |------------------|                             |------------|

A camada do controlador não sabe quais são as entidades. Ele se comunica com os objetos Form e View Value . Objetos de formulário possuem anotações de validação JSR 303 (por exemplo, @NotNull) e Objetos de valor de exibição têm anotações de Jackson para serialização personalizada. (por exemplo, @JsonIgnore)

A camada de serviço se comunica com a camada de repositório usando o Entity Objects. Os objetos de entidade possuem anotações JPA / Hibernate / Spring Data. Cada camada se comunica apenas com a camada inferior. A comunicação entre camadas é proibida devido à dependência circular / cíclica.

User Service ----> XX CANNOT CALL XX ----> Order Service

Algumas estruturas ORM têm a capacidade de projetar usando interfaces ou classes adicionais. Portanto, os repositórios podem retornar objetos View diretamente. Lá para você não precisa de uma transformação adicional.

Por exemplo, esta é a nossa entidade Usuário:

@Entity
public final class User {
    private String id;
    private String firstname;
    private String lastname;
    private String phone;
    private String fax;
    private String address;
    // Accessors ...
}

Mas você deve retornar uma lista paginada de usuários que inclui apenas identificação, nome e sobrenome. Em seguida, você pode criar um objeto de valor de exibição para a projeção ORM.

public final class UserListItemView {
    private String id;
    private String firstname;
    private String lastname;
    // Accessors ...
}

Você pode facilmente obter o resultado paginado da camada de repositório. Graças à primavera, você também pode usar apenas interfaces para projeções.

List<UserListItemView> find(Pageable pageable);

Não se preocupe, pois o outro BeanUtils.copymétodo de operações de conversão funciona bem.

Fırat KÜÇÜK
fonte
11
  1. Para mim, a melhor resposta para a pergunta que é um DTO é que os DTOs são objetos simples que não devem conter nenhuma lógica de negócios ou implementação de métodos que exijam testes .
  2. Normalmente, seu modelo (usando o padrão MVC) são modelos inteligentes e podem conter muitos / alguns métodos que realizam operações diferentes especificamente para esse modelo (não a lógica de negócios, isso deve estar nos controladores). No entanto, quando você transfere dados (por exemplo, chamar um ponto de extremidade REST ( GET/ POSTqualquer que seja) de algum lugar ou consumir um serviço da Web usando SOA, etc ...), não deseja transmitir o objeto de tamanho grande com código que não é necessário para o terminal, consumirá dados e diminuirá a transferência.
Thiago Burgos
fonte
Por que a lógica comercial deve estar nos controladores?
AlexioVay 30/01
6

Com o MVC, os objetos de transferência de dados costumam ser usados ​​para mapear modelos de domínio para objetos mais simples que serão exibidos pela exibição.

Da Wikipedia :

O objeto de transferência de dados (DTO), anteriormente conhecido como objetos de valor ou VO, é um padrão de design usado para transferir dados entre subsistemas de aplicativos de software. DTOs são frequentemente usados ​​em conjunto com objetos de acesso a dados para recuperar dados de um banco de dados.

Dan
fonte
3
Um objeto de valor não é um DTO .
Coderpc 22/01/19
0

O objeto de transferência de dados (DTO) descreve "um objeto que transporta dados entre processos" (Wikipedia) ou "um objeto usado para encapsular dados e enviá-los de um subsistema de um aplicativo para outro" (resposta do Stack Overflow).

mostafa kazemi
fonte
0

DefN

Um DTO é um modelo de dados codificado . Ele apenas resolve o problema de modelar um registro de dados tratado por um processo de produção codificado , onde todos os campos são conhecidos em tempo de compilação e, portanto, acessados ​​por meio de propriedades fortemente tipadas.

Por outro lado, um modelo dinâmico ou "pacote de propriedades" resolve o problema de modelar um registro de dados quando o processo de produção é criado em tempo de execução.

The Cvar

Um DTO pode ser modelado com campos ou propriedades, mas alguém inventou um recipiente de dados muito útil chamado Cvar. É uma referência a um valor. Quando um DTO é modelado com o que chamo de propriedades de referência , os módulos podem ser configurados para compartilhar memória heap e, assim, trabalhar em conjunto. Isso elimina completamente a passagem de parâmetros e a comunicação O2O do seu código. Em outras palavras, os DTOs com propriedades de referência permitem que o código atinja zero acoplamento .

    class Cvar { ... }

    class Cvar<T> : Cvar
    {
        public T Value { get; set; }
    }

    class MyDTO
    {
        public Cvar<int> X { get; set; }
        public Cvar<int> Y { get; set; }
        public Cvar<string> mutableString { get; set; } // >;)
    }

Fonte: http://www.powersemantics.com/

DTOs dinâmicos são um componente necessário para software dinâmico. Para instanciar um processo dinâmico, uma etapa do compilador é vincular cada máquina no script às propriedades de referência que o script define. Um DTO dinâmico é criado adicionando os Cvars a uma coleção.

    // a dynamic DTO
    class CvarRegistry : Dictionary<string, Cvar> { }

Contenções

Nota: como o Wix rotulou o uso de DTOs para organizar parâmetros como um "anti-padrão", darei uma opinião autorizada.

    return View(model);  // MVC disagrees

Minha arquitetura colaborativa substitui os padrões de design. Consulte meus artigos na web.

Os parâmetros fornecem controle imediato de uma máquina de estrutura de pilha. Se você usa controle contínuo e, portanto, não precisa de controle imediato, seus módulos não precisam de parâmetros. Minha arquitetura não tem nenhuma. A configuração de máquinas (métodos) em processo adiciona complexidade, mas também valor (desempenho) quando os parâmetros são tipos de valor. No entanto, os parâmetros do tipo de referência fazem com que o consumidor faça com que as falhas do cache obtenham os valores do heap de qualquer maneira - portanto, basta configurar o consumidor com propriedades de referência. Fato da engenharia mecânica: confiar em parâmetros é um tipo de pré-otimização, porque o processamento (fabricação de componentes) é um desperdício. Consulte o meu artigo W para mais informações. http://www.powersemantics.com/w.html .

Fowler e empresa podem obter os benefícios dos DTOs fora da arquitetura distribuída, se alguma vez conhecerem outra arquitetura. Os programadores conhecem apenas sistemas distribuídos. Sistemas colaborativos integrados (também conhecidos como produção ou manufatura) são algo que tive que reivindicar como minha própria arquitetura, porque sou o primeiro a escrever código dessa maneira.

Alguns consideram o DTO um modelo de domínio anêmico, o que significa que não possui funcionalidade, mas isso pressupõe que um objeto deva possuir os dados com os quais interage. Esse modelo conceitual o força a entregar os dados entre os objetos, que é o modelo para processamento distribuído. No entanto, em uma linha de fabricação, cada etapa pode acessar o produto final e alterá-lo sem possuí-lo ou controlá-lo. Essa é a diferença entre processamento distribuído e integrado. A fabricação separa o produto das operações e da logística.

Não há nada inerentemente errado no processamento de modelagem como um grupo de funcionários inúteis de escritório que trabalham por e-mail sem manter um rastro de e-mail, exceto por todo o trabalho extra e dor de cabeça que ele cria ao lidar com problemas de logística e retorno. Um processo distribuído modelado corretamente anexa um documento (roteamento ativo) ao produto, descrevendo de quais operações ele veio e irá para. O roteamento ativo é uma cópia do roteamento da origem do processo, que é gravada antes do início do processo. No caso de um defeito ou outra alteração de emergência, o roteamento ativo é modificado para incluir as etapas da operação para as quais será enviado. Isso então responde por todo o trabalho que foi produzido.

RBJ
fonte