Objeto CLR antigo simples versus objeto de transferência de dados


405

POCO = Objeto CLR antigo simples (ou melhor: classe)

DTO = Objeto de Transferência de Dados

Neste post, há uma diferença, mas, francamente, a maioria dos blogs que eu leio descreve o POCO da maneira como o DTO é definido: os DTOs são simples recipientes de dados usados ​​para mover dados entre as camadas de um aplicativo.

POCO e DTO são a mesma coisa?


5
"POCO = Objeto CLR antigo simples (ou melhor: classe)". Assim, objetos dessa natureza no VB.NET também seriam POCOs, não POVOs.
precisa

Respostas:


568

Um POCO segue as regras do POO. Deveria (mas não precisa) ter estado e comportamento. O POCO vem do POJO, cunhado por Martin Fowler [ anedota aqui ]. Ele usou o termo POJO como uma maneira de tornar mais sexy a rejeição das implementações pesadas de EJB da estrutura. O POCO deve ser usado no mesmo contexto em .Net. Não permita que estruturas ditem o design do seu objeto.

O único objetivo de um DTO é transferir o estado e não deve ter comportamento. Veja a explicação de Martin Fowler sobre um DTO para obter um exemplo do uso desse padrão.

Aqui está a diferença: o POCO descreve uma abordagem de programação (boa programação orientada a objetos à moda antiga), em que DTO é um padrão usado para "transferir dados" usando objetos.

Embora você possa tratar POCOs como DTOs, você corre o risco de criar um modelo de domínio anêmico, se o fizer. Além disso, há uma incompatibilidade na estrutura, pois os DTOs devem ser projetados para transferir dados, não para representar a verdadeira estrutura do domínio comercial. O resultado disso é que os DTOs tendem a ser mais simples que o seu domínio real.

Em um domínio de complexidade razoável, é quase sempre melhor criar POCOs de domínio separados e traduzi-los para DTOs. DDD (design controlado por domínio) define a camada anticorrupção (outro link aqui , mas a melhor coisa a fazer é comprar o livro ), que é uma boa estrutura que torna clara a segregação.


Sei que fiz muita referência a Martin Fowler aqui, mas ele cunhou o termo POJO e escreveu o livro PoEAA, que é a referência definitiva para o DTO.
267 Michael Meadows

Não sei se um DTO não deve ter comportamentos. A julgar pelo diagrama de Martin Fowler, o DTO pode ter comportamentos.
Beatles1692

39
@ Beatles1692, os métodos descritos são código de serialização. É provavelmente uma declaração muito ampla para dizer "sem comportamento". Que tal "sem lógica de negócios". Código de serialização e objetos de baixo nível, como código hash, igualdade e tostring, devem ser aceitáveis.
Michael Meadows

1
@PositiveGuy Um modelo serve a uma finalidade diferente de um DTO. O DTO deve ser para transferir dados de um domínio para outro (se eles estão no mesmo tempo de execução ou não é irrelevante). Um modelo "representa" um aspecto de um domínio, como uma tela, serviço ou fonte de dados. Os modelos incluem estado e comportamento, representativos do que estão modelando.
Michael Meadows

2
Observe que os modelos de domínio anêmicos não são necessariamente ruins, principalmente se o seu aplicativo for principalmente CRUD. Favorecer a simplicidade sobre Martin Fowler.
Mariusz Jamro

50

Provavelmente é redundante para mim contribuir, pois já afirmei minha posição no artigo do meu blog, mas o parágrafo final desse artigo resume as coisas:

Portanto, em conclusão, aprenda a amar o POCO e certifique-se de não espalhar informações erradas sobre a mesma coisa que um DTO. DTOs são recipientes de dados simples usados ​​para mover dados entre as camadas de um aplicativo. Os POCOs são objetos de negócios completos com o único requisito de que eles sejam ignorantes da persistência (sem métodos de obtenção ou salvamento). Por fim, se você ainda não leu o livro de Jimmy Nilsson, compre-o nas estantes da universidade local. Tem exemplos em C # e é uma ótima leitura.

Aliás, Patrick Li o POCO como um artigo sobre estilo de vida e concordo plenamente que é um artigo fantástico. Na verdade, é uma seção do livro de Jimmy Nilsson que eu recomendei. Eu não tinha ideia de que estava disponível online. Seu livro é realmente a melhor fonte de informação que eu encontrei sobre POCO / DTO / Repository / e outras práticas de desenvolvimento de DDD.


4
Link para o artigo do blog: rlacovara.blogspot.com/2009/03/…
Jamie Ide

28

O POCO é simplesmente um objeto que não depende de uma estrutura externa. É SIMPLES.

Se um POCO tem comportamento ou não, é irrelevante.

Um DTO pode ser POCO, assim como um objeto de domínio (que normalmente seria rico em comportamento).

Normalmente, os DTOs são mais propensos a ter dependências em estruturas externas (por exemplo, atributos) para fins de serialização, pois normalmente saem nos limites de um sistema.

Nas arquiteturas típicas do estilo Onion (geralmente usadas em uma abordagem amplamente DDD), a camada de domínio é colocada no centro e, portanto, seus objetos não devem, neste ponto, ter dependências fora dessa camada.



6

Eu acho que um DTO pode ser um POCO. O DTO é mais sobre o uso do objeto, enquanto o POCO é mais sobre o estilo do objeto (dissociado dos conceitos de arquitetura).

Um exemplo em que um POCO é algo diferente do DTO é quando você está falando sobre o POCO dentro do modelo de domínio / modelo de lógica de negócios, que é uma boa representação OO do domínio do problema. Você pode usar os POCOs em todo o aplicativo, mas isso pode ter algum efeito colateral indesejável, como um vazamento de conhecimento. Os DTOs são usados, por exemplo, a partir da Camada de Serviço com a qual a interface do usuário se comunica, os DTOs são uma representação plana dos dados e são usados ​​apenas para fornecer dados à interface do usuário e comunicar as alterações de volta à camada de serviço. A camada de serviço é responsável por mapear as duas maneiras do DTO para os objetos de domínio POCO.

A atualização Martin Fowler disse que essa abordagem é um caminho pesado a seguir e só deve ser adotada se houver uma incompatibilidade significativa entre a camada de domínio e a interface do usuário.


2
@ David Landman, o link que você incluiu é para o padrão DTO Local, que é quando os DTOs são usados ​​para o estado de transferência dentro dos limites do sistema. Nesses casos, você deve ter muito cuidado, pois no seu sistema você já deve ter um domínio bem definido que possa ser compartilhado. Ao transferir o estado através dos limites do sistema, é difícil evitar o DTO e bastante apropriado em todos os casos.
Michael Meadows

@ Michael Meadows, sim, o link realmente fala sobre um subconjunto diferente de problemas. Mas acho que, no caso de transferência de estado através de um limite do sistema, você deve usar um serviço de tradução para mapear o POCO de um contexto para o POCO de outro contexto. Ou você está falando de limites no nível do sistema?
Davy Landman

1

Um caso de uso primário para um DTO é retornar dados de um serviço da web. Nesse caso, POCO e DTO são equivalentes. Qualquer comportamento no POCO seria removido quando retornado de um serviço da Web, portanto, não importa se ele possui ou não comportamento.


5
Eu acho que sua resposta deturpa o que acontece um pouco. No caso de um serviço da Web, um proxy é gerado com base no estado exposto de um objeto. Isso significa que um DTO é criado separado do POCO que, por acaso, possui o mesmo estado público que o POCO. Pode parecer sutil, mas é importante. O motivo é que, mesmo que o proxy seja idêntico ao original, ele não é realmente construído a partir da mesma classe.
267 Michael Meadows

Oh não. Um usa um DTO para retornar / receber dados entre camadas, nesse caso, um serviço da web. Um escolhe um DTO porque ele possui apenas dados e nenhum comportamento. É verdade que a classe de proxy provavelmente também será um DTO e, se você tivesse usado uma classe POCO, esse proxy teria sido criado. Mas, nesse caso, a classe POCO é efetivamente um DTO, pois seu comportamento não se traduz. Ainda digo que use um DTO porque você não perderá comportamentos que nunca existiram.
3126 John Saunders

5
** Semântica: os serviços da Web expõem pacotes de estado do objeto usando WSDL. Os proxies são gerados a partir deles. Isso não pode incluir comportamento. Ao consumir um serviço da Web, o único relacionamento entre seu objeto e o objeto de domínio exposto é que ele possui o mesmo estado público criado com base na inspeção.
Michael Meadows

7
@ John, acho que você está exagerando. Estou dizendo que você está certo, mas sua formulação é enganosa. "Nesse caso, POCO e DTO são equivalentes." Semântica, isso não é verdade. Os POCOs podem ser usados ​​como DTOs e vice-versa, mas isso não significa que eles sejam equivalentes ... não mais que um carro e uma caminhonete são equivalentes, mesmo que ambos possam ser usados ​​para levá-lo ao supermercado. Eles têm função sobreposta, mas seria difícil encontrar alguém para lhe dizer que uma percepção é equivalente a um F350, mesmo no contexto da viagem ao supermercado.
Michael Meadows

3
Esta resposta está muito errada, um serviço da Web não é genérico o suficiente para um. Mais importante ainda, é um fato bem estabelecido que o DTO NÃO é um POCO. O DTO é um contêiner de dados, enquanto o POCO é um objeto como propriedade e é persistente ignorante (sem métodos get ou save).
quer

1

aqui está a regra geral: DTO == mal e indicador de software com excesso de engenharia. POCO == bom. Os padrões de 'empresa' destruíram o cérebro de muitas pessoas no mundo Java EE. por favor, não repita o erro no .NET land.


7
Você poderia elaborar, por favor? O DTO é necessário ao retornar dados de um serviço da Web, a fim de evitar implementação e plataforma específicas no contrato.
318 John Saunders

1
Sim, os DTOs da John foram projetados para o que você diz e funciona bem. Infelizmente, eles costumam ser usados ​​quando não são necessários em aplicativos da web de camada única e têm pouco valor.
Craig

9
Eu acho, @drscroogemcduck, que talvez você não goste de DTOs porque eles são usados ​​como primeiro recurso e não como último recurso, mas não são inerentemente maus ... não mais do que os infames padrões de singleton ou fábrica. O que é mau são os arquitetos que enfiam as estruturas nas gargantas dos desenvolvedores que os forçam a criar DTOs para tudo. Para o que eles fazem, na transferência de dados, os DTOs (se feitos com prudência) são o ajuste perfeito.
Michael Meadows

0

As classes DTO são usadas para serializar / desserializar dados de diferentes fontes. Quando você deseja desserializar um objeto de uma fonte, não importa qual fonte externa seja: serviço, arquivo, banco de dados etc., você pode querer usar apenas parte disso, mas deseja uma maneira fácil de desserializar esses dados para um objeto. depois disso, você copia esses dados para o XModel que deseja usar. Um serializador é uma bela tecnologia para carregar objetos DTO. Por quê? você só precisa de uma função para carregar (desserializar) o objeto.


0

TL; DR:

Um DTO descreve o padrão de transferência de estado. Um POCO não descreve nada. É outra maneira de dizer "objeto" no OOP. Ele vem do POJO (Java), cunhado por Martin Fowler, que literalmente o descreve como um nome mais sofisticado para 'objeto' porque 'objeto' não é muito sexy.

Um DTO é um padrão de objeto usado para transferir o estado entre as camadas de preocupação. Eles podem ter comportamento (ou seja, tecnicamente, pode ser um poco), desde que esse comportamento não mude o estado. Por exemplo, ele pode ter um método que se serializa.

Um POCO é um objeto simples, mas o que se entende por "simples" é que ele não é especial. Apenas significa que é um objeto CLR sem padrão implícito. Um termo genérico. Não foi feito para funcionar com outra estrutura. Portanto, se o seu POCO tiver[JsonProperty] decorações EF em todas as suas propriedades, por exemplo, eu diria que não é um POCO.

Aqui estão alguns exemplos de diferentes tipos de padrões de objetos para comparar:

  • Ver modelo : usado para modelar dados para uma vista. Geralmente possui anotações de dados para ajudar na ligação e validação. No MVVM, ele também atua como um controlador. É mais que um DTO
  • Objeto Valor : usado para representar valores
  • Raiz Agregada : usada para gerenciar estado e invariantes
  • Manipuladores : usados ​​para responder a um evento / mensagem
  • Atributos : usados ​​como decoração para lidar com preocupações transversais
  • Serviço : usado para executar tarefas complexas
  • Controlador : usado para controlar o fluxo de solicitações e respostas
  • Fábrica : usado para configurar e / ou montar objetos complexos para uso quando um construtor não é bom o suficiente. Também usado para tomar decisões sobre quais objetos precisam ser criados em tempo de execução.
  • Repositório / DAO : usado para acessar dados

Estes são apenas objetos, mas observe que a maioria deles geralmente está vinculada a um padrão. Então você pode chamá-los de "objetos" ou pode ser mais específico sobre sua intenção e chamá-lo pelo que é. É também por isso que temos padrões de design; descrever conceitos complexos em alguns trabalhos. DTO é um padrão. A raiz agregada é um padrão, o View Model é um padrão (por exemplo, MVC e MVVM). POCO não é um padrão.

Um POCO não descreve um padrão. É apenas uma maneira diferente de se referir a classes / objetos no OOP. Pense nisso como um conceito abstrato; eles podem estar se referindo a qualquer coisa. Na IMO, existe um relacionamento unidirecional, porque, uma vez que um objeto atinge o ponto em que só pode servir a um propósito de maneira limpa, ele não é mais um POCO. Por exemplo, depois de marcar sua classe com decorações para fazê-la funcionar com alguma estrutura, ela não é mais um POCO. Portanto:

  • Um DTO é um POCO
  • Um POCO não é um DTO
  • Um modelo de exibição é um POCO
  • Um POCO não é um modelo de exibição

O objetivo de fazer uma distinção entre os dois é manter padrões claros e consistentes no esforço de não cruzar preocupações e levar a um acoplamento rígido. Por exemplo, se você possui um objeto de negócios que possui métodos para alterar o estado, mas também é decorado com decorações EF para salvar no SQL Server AND JsonProperty, para que possa ser enviado de volta por um ponto de extremidade da API. Esse objeto seria intolerante a alterações e provavelmente estaria repleto de variantes de propriedades (por exemplo, UserId, UserPk, UserKey, UserGuid, onde alguns deles estão marcados para não serem salvos no banco de dados e outros marcados para não serem serializados para JSON no terminal da API).

Então, se você me dissesse que algo era um DTO, provavelmente teria certeza de que nunca foi usado para outra coisa senão mudar o estado. Se você me dissesse que algo era um modelo de exibição, provavelmente teria certeza de que não estava sendo salvo em um banco de dados. Se você me dissesse que algo era um modelo de domínio, provavelmente teria certeza de que não dependesse de nada fora do domínio. Mas se você me dissesse que algo era um POCO, não estaria realmente me dizendo muito.


-13

Nem os chame de DTOs. Eles são chamados de Modelos .... Período. Modelos nunca têm comportamento. Não sei quem criou esse DTO estúpido, mas deve ser uma coisa do .NET. Pense em ver modelos no MVC, mesmo problema **, os modelos são usados ​​para transferir o estado entre as camadas do lado do servidor ou durante o período de conexão, todos eles são modelos. Propriedades com dados. Esses são modelos pelos quais você passa o fio. Modelos, modelos de modelos. É isso aí.

Eu gostaria que o termo estúpido DTO se afastasse do nosso vocabulário.


1
não sei de onde você tirou essa ideia de que os modelos nunca têm comportamento. Como você modela algo diferente de CRUD sem modelar o comportamento? Até os ViewModels têm comportamento em muitos casos, principalmente nos aplicativos MVVM. DTO é um termo útil porque descreve com precisão o objetivo; para transferir dados.
Gerald

9
votado por ser factualmente incorreto e pela atitude pontificadora.
joedotnot

Absurdo. Os modelos devem ser recipientes estúpidos. Não existe DTO, é um termo inventado pelos Estados-Membros. Você transfere modelos entre domínios, serviços e aplicativos. Período. DTO é um desperdício de prazo que não é necessário e apenas confunde mais as coisas. Modelos, modelos e mais modelos é isso. Os modelos podem ou não ter comportamento. Os modelos de exibição não devem. Esse comportamento deve estar em um BL, não na classe Model.
PositiveGuy

Concordo que os DTOs são funcionalmente modelos. Os ViewModels têm comportamento e é a que você se liga no MVVM. No entanto, escrevi um aplicativo em que meus modelos eram mais inteligentes (basicamente VMs, mas eu não queria chamá-los) e eles "aceitaram" um objeto DTO. Isso me permitiu ter mais opções com o framework. Assim, a partir do CRUD (ou mesmo EF), eu transmitia o objeto pelos serviços WCF e recebia o objeto DTO e o encapsulava (adicionando a alteração OnProp, etc.). O My ViewModels executou um encapsulamento adicional e pode ter aceito dois (ou uma lista) de "Modelos". A definição rígida seria VMs.
SQLMason 16/09/2015

"Você transfere modelos entre domínios, serviços e aplicativos" Por que o termo modelo é mais apropriado e adequado do que o termo DTO para esse comportamento que você descreve?
caa
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.