Anemic Domain Model e sistemas sérios

47 respostas
sergiotaborda

Quando nos ensinam OO sempre nos dizem que os objetos devem traduzir a realidade. Se o sistema é bancáro deve existir Conta e Banco e assim vai. E a isso se chama domain model (modelo de dominio). Mas as tecnologias java , especialmente jee , mas não só não nos levam a criar esse tipo de objetos, mas sim objetos que representam registros (linhas no banco de dados) e objetos que representam operações sobre eles. Isso gera os famosos DO , TO , DTO … escolham … e os Façades/Statless bean etc… modelo que se chamou de Anemic Domain model , modelo de dominio anémico.

Ora isso é muito bonito e concerteza eu gostaria de usar um domain model puro, mas :

  1. O usuário aperta o botão de salvar … o que acontece ? O que é que se invoca ? concerteza não dá para invocar o objeto de dominio directamente

  2. Os dados nos objetos gráficos (inputs) viram objetos do dominio ? e nesse caso eles existem com a mesma “realidade” que os objetos que já estavam no dominio (prevalencia/persistencia) ? O que é um objecto de dominio “salvo” e um " a salvar" ?

  3. Onde ficam as validações ? controlo de tela , mensagens , transação , persistencia , etc … ?

Ou seja, é sério pensar que um sistema complexo , distribuido, com swing , multicamada, encapsulado, etc etc … pode ser baseado no dominio que não seja anémico. Se sim , como ? Que exemplos de aplicações reais existem que não usem um modelo anémico ?

47 Respostas

pcalcado

Dar dá, estude Naked Objects que é uma abordagem que lida exatamente com isso.

De qualquer forma, arquitetura de Camadas existe exatamente para que ao clicar o botão existam direcionadores de fluxo que levam a mensagem até os objetos de domínio. A mensagem entra pela Camada de Apresentação e segue até a de Negócios, sofrendo transofmrações no caminho.

Os dados digitados pelo usuário ou obtidos de qualquer outra forma vão popular objetos de domínio. Antes, provavelmente, eles vão popular objetos da Camada de Apresentação (como os próprios formulários) e aí sim temos este tipod e objeto que representa um botão, um controle gráfico, etc.

Acho que a dificuldade que você está tendo é separar objetos em Camadas.

Um objeto deve obedecer a um contrato que lhe define as invariantes, pre e pos condições. O objeto eh responsavel por obedecer estas regras, se nao sao seguidas ele esta em estado invalido e deve prosseguir como tal (provavelmente lançando uma excecao).

Resumindo: validacao eh feita pelo objeto de negocios, por conveniencia ou desempenho pode-se replicar validacao na interface, o que geralmente eh feito em sistemas web.

Sim, o problema é exatamente que seus exemplos não estão separando as aplicações em Camadas.

Dos exemplos reais eu posso citar os sistemas de um dos maiores provedores de conteudo e Internet do Brasil, o software utilizado para comercializacao de commodities da maior empresa de energia eletrica do mundo, sistemas pre-pagos que provavelmente rodam na sua operadora de telefonia movel, gerencia da maior ferrovia do Brasil, sistemas de gestao de RH de uma das maiores empresas de hardware do mundo… soh o que lembro dentre os projetos que ja trabalhei.

E mais: trabalhar com Swing (ou qualquer coisa desktop) é ainda mais fácil do que web quando se trata de um domínio rico já que existe uma JVM no cliente.

Como falei, é uma questão de separar em Camadas.

SadNess

excelente post pcalcado
tb tava em dúvida em relação a alguns aspectos assim

tem algum link pra artigos sobre isso?

pcalcado

http://www.fragmental.com.br/wiki

sergiotaborda

pcalcado:
sergiotaborda:

  1. O usuário aperta o botão de salvar … o que acontece ? O que é que se invoca ? concerteza não dá para invocar o objeto de dominio directamente

Dar dá, estude Naked Objects que é uma abordagem que lida exatamente com isso.

Mas o problema é por ai mesmo. No fim parece que o objeto é tão naked(despido) que temos que o vestir com um monte de camadas…

O problema é esse. Se eu populo outros objetos que depois populam os de dominio isso vai dar no mesmo que usar TO pois esses objetos intermédios acabam sendo TO (mesmo que eles não pareçam TO, como um Map ou o Request)

Para que o Domain Model funcione ele tem que estar na camada de negocio, mas até lá tem um monte de logicas a serem feitas e os dados têm que transistar por elas. Isso leva à necessidade de TO, que é exactamente o que o anemic model não quer. Parece contraditório.
Num domain model verdadeiro os ppr objetos de modelo seriam os TO e eu poderia invocar seus métodos em qualquer ponto do sistema.
O exemplo classico é a validação. Eu poderia fazer ela no cliente (no caso de swing) mas uma exceção não é suficiente, eu preciso de um framework de validação para isso. Mais uma vez vestindo o objeto e retirando dele a capacidade de se validar (colocando numa annotation por exemplo)

O famoso controlo de tela se o campo A = x , desabilita B não pode ficar no objeto de dominio mas é uma regra de negocio. Então no fim o objeto de dominio não tem qualquer importância face à quantidade de outros objetos em outras camadas. Ou seja: não é possivel de apenas uma classe inferir todo o comportamento relativo à entidade de negocio que ela representa em todas as camadas do sistema.

Mas é exactamente ao separar em camadas que preciso dos TO e é exactamente ai que nasce o modelo anémico. Parece uma contradição. Não é ?

Não tem nenhum open source ?

pcalcado

Acho que você não entendeu. procure no Google sobre Naked Objects, é uma técnica de desenvolvimento apoiada por alguns frameworks como JMatter.

Não. Um TO é um objeto de transferência, ele possui responsabilidade de transferir dados de um canto para outro.

Um objeto de interface tem por responsabilidade lidar com input do usuário, não transferir dados. Um TO e um Request são muito diferentes, o Request representa a solicitação feita pelo usuário, que inclui dados e metadados.

Não há necessidade de TO. Por que haveria?

Os objetos da Camada de Aplicação recebem os dados ‘crus’ e os transformam em objetos que são passados para a Camada de Negócios invocando fluxos específicos (como chamar métodos em um Service Layer). Novamente: d~e uma cofnerida na literatura sobre camadas.

Você pode fazer isso, depende apenas de como modela suas camadas.

Como mencionei já trabalhei muito com Swing (não na construção do frontend mas na respsota aos eventos) e não vi necessidade de framework de validação. O controlados dos componentes de tela dispara métodos nos objetos de negócio, por exemplo tentando criar um objeto usuario. O objeto usuario, que é da Camada de Negócios, percebe que foi criado, digamos, sem um atributo login. Neste momento ele dispara uma exceção que é pega pelo controlador e tratada na interface. Esse é o padrão MVC original (sem estas aberrações web).

Como mencionado acima isto não é o que se espera de um padrão MVC. O Model vai gerar exceções que são tratadas pela View, a View é quem vai desabilitar campos, exibir alertas, etc. em resposta a estas solicitações.

Não há esta necessidade. Leia sobre Camadas. Mundo Java #15 tem um artigo sobre isso.

É difícil achar aplicativos J2EE como open-source, eu não lembro de nenhum caso notável.

Uma dúvida: voce trabalhava antes com Delphi, VB ou algo parecido?

sergiotaborda

pcalcado:
sergiotaborda:

Mas o problema é por ai mesmo. No fim parece que o objeto é tão naked(despido) que temos que o vestir com um monte de camadas…

Acho que você não entendeu. procure no Google sobre Naked Objects, é uma técnica de desenvolvimento apoiada por alguns frameworks como JMatter.


Cara, eu sei o que é…

Ora , e se eu crio o objeto na camada de view do swing, populo com os dados dos inputs, passo à camada de delegação do swing, que serializa o objecto e passa ao servidor, que desserializa e passa à camada de serviços que passa à camada de domino e à de persistência, não é transferência que eu estou fazendo ? Se não é, o que é então ?

Eu discordo disso. Mas o ponto não é esse. O ponto é que em algum lugar do sistema eu preciso condensar inputs num objeto só. Seja qual for e implemente o padrão que for esse objecto não é um objeto de dominio.
Ele é um objecto auxiliar, um objeto de framework. Ora os objetos auxiliares são exactamente o que o Anemic Domain Model (ADM) não quer ter.
Então parece-me que existe uma contradição entre dizer que ADM é ruim e que devemos ter objetos de dominio com todas as regras dentro deles quando isso não é compatível com sistemas distribuídos.

Você afirma que sim. Ok. Então por favor me dê um exemplo de um objecto de dominio que vc tenha criado, que siga o padrão Domain Model e não o ADM.

Vc não viu exatamente porque não trabalhou com o front end. Dê uma olhada no JGodies Validation para ver do que estou falando. Não basta dizer que está inválido, tem que dizer como, onde , porquê e como resolver. Essa informação está normalmente no validador e no help e não no objeto de domínio.

Que seja. O uso de MVC apenas reforça o que eu disse: não é o objeto do domínio que contém a regra daquilo que acontece na tela.

Básicamente a minha dúvida é saber se definindo uma classe com todos os atributos e métodos, junto com anotações especiais eu a posso usar em toda e qualquer camada da aplicação. Exemplo: A camada de validação usa as anotações de valdiação, a camada de persistencia usa as anotações de persistencia, etc etc… apenas a camada de negócio usa os métodos da classe que “fazem alguma coisa”.

Não. Nunca trabalhei com isso. Eu programei com eles, especialmente com VB e fiz alguma coisa - básicamente manutenção de programas já existentes - mas não foi do meu agrado e por isso mudei para Java por isso (entre outras razões). Mas o Java é uma tecnologia e por isso é necessário cria/usar padrões/frameworks para facilitar as coisas. Eu tenho ouvido falar do ADM e concordo com a ideia, mas não me parece que seja aplicável a uma aplicação séria. Por exemplo BPM é um modelos anémico logo à partida e é um modelo muito mais Business-friendly que Domain Model. Domain Model não se dá bem com aplicações destribuidas. É isso que quero saber. Se sim , ou não e em que medida.

louds

O uso de um Domain Model independe da topologia da tua aplicação. Ele simplesmente serve para modelar de maneira mais clara e intuitiva os conceitos do negócio.

Todo sistema vai ter muitos objetos auxiliares e não relacionados ao modelo que fazer o plumbing necessário. O uso de DDM diz respeito a parte do sistema que cuida das regras do negócio e não tem o menor relacionamento com a camadas de infra-estrutura.

O sistema pode sim ser distribuido, precisar DTOs e tudo mais, mantendo um domain model na parte que cabe dele. Outra coisa, em algumas situações é possivel e interessante mapear coisas como validação e workflows como objetos de domínio. DDD diz muito a respeito da comunicação com o cliente, por exemplo, se ele quer discutir sobre “os cenários no qual XXX é pertinente”, o desenvolvedor acaba por modelar isso como um objeto do modelo, apesar de ser só validação.

mutano

Tocando no assunto dos TO, eu sempre tive dúvidas de como fazer a comunicação de um cliente swing com um ejb de fachada, por exemplo, sem o uso de TO. Isso é possível de ser feito? O uso de TOs transforma o meu modelo num Anemic Domain Model?

sergiotaborda

louds:
O uso de um Domain Model independe da topologia da tua aplicação. Ele simplesmente serve para modelar de maneira mais clara e intuitiva os conceitos do negócio.

Todo sistema vai ter muitos objetos auxiliares e não relacionados ao modelo que fazer o plumbing necessário. O uso de DDM diz respeito a parte do sistema que cuida das regras do negócio e não tem o menor relacionamento com a camadas de infra-estrutura.

Ah! era isso que eu queria ler. Essa foi tb a conclusão a que cheguei.
Mas nesse caso como eu faria a associação dos TO com os Objetos de Dominio. Exemplos ? …

pcalcado

Sim, e nesse caso você deve utilizar um DTO (na maioria das vezes), ninguém nunca disse o contrário.

Qual o problema do objeto do framework (Controller, por exemplo) instanciar e enviar apra a Camada de Negocios um objeto de dominio? o que ele nao faz é processar regras de negócio.

Para este tipo de coisa existe o apdrão DTO, leia a descrição no POEAA.

Leia os artigos em:
http://fragmental.com.br/wiki

Sérgio: a View sabe reagir ao Modelo, isso é o feijão-com-arroz do MVC. Se o modelo lança uma DataInvalidaException a view deve saber reagir a isso.

O que acotnece na tela está na Camada de Apresentação, que não é onde residem os objetos de negócio (eles são de domínio mas de um outro domínio, não o de negócios).

Você simplesmente não deveria fazer isso.

De qualquer modo fica muito difícil continuar essa discussão de você não ler sobre:

  • Camadas
  • DTOs
  • Naked Objects

Porque suas dúvidas são respondidas na bibliografia. Recomendo a laitura do POEAA, de Martin Fowler e dos artigos e apresentações do link que passei acima.

pcalcado

sergiotaborda:

Ah! era isso que eu queria ler. Essa foi tb a conclusão a que cheguei.
Mas nesse caso como eu faria a associação dos TO com os Objetos de Dominio. Exemplos ? …

http://www.fragmental.com.br/files/presentations/riojug/Arquitetura_de_Camadas_em_JEE_PDF.zip

sergiotaborda

Sim, e nesse caso você deve utilizar um DTO (na maioria das vezes), ninguém nunca disse o contrário.

Pois isto
diz exactamente o contrário. E essa imagem foi tirada daqui http://fragmental.com.br/wiki/index.php?title=Evitando_VOs_e_BOs
Que é o site que vc recomenda tanto que eu leia.

O que é difícil é vc deixar de me tratar como seu eu tivesse 17 anos e prestar mais atenção na mensagem e menos no mensageiro.


Porque suas dúvidas são respondidas na bibliografia. Recomendo a laitura do POEAA, de Martin Fowler e dos artigos e apresentações do link que passei acima.

A verdade é que não são. Exactamente por eu ter lido sobre esses assuntos e essa “bibliografia” que eu tenho cheguei na conclusão que um sistema destribuido é anémico por natureza. Isto porque ele sempre seque aquele esquema da imagem acima , mesmo quando vc tiver verdadeiro objetos de dominio continua tendo objetos como aqueles que são basiacamente DTO e Service Layer.

Quanto ao PDF é muito bonito mas não tem os exemplo que eu pedi.

mutano

Calma sergio! O pcalcado só está ajudando. Se tu lesse o artigo direito veria que essa figura se refere ao Anemic Domain Model que o artigo mostra como problema e não como solução!

pcalcado

Se você tivesse perdido 15 minutos e lido o artigo veria que isso é um anti-exemplo. O artigo fala exatamente sobre como você deveria evitar este tipo de coisa, eu sei o que está escrito nele porque fui eu quem escreveu e recomendei tanto a leitura porque escrevi este texto e os outros exatamente para não precisar repetir estas coisas em todo santo post no GUJ.

A sua mensagem anterior só mostra que eu me enganei ao tentar conversar como você como alguém que quer aprender e ensinar algo. Você nem sequer leu o artigo (que se chama “Evitando VOs e BOs”). Logo abaixo desta figura ele fala sobre os problemas deste modelo.

O PDF tem o exemplo na parte sobre DTO (que é o mesmo do Fowler, está bem pequeno, é verdade, mas eu poderia te indicar outro material se você tivesse um mínimo de educação e interesse em procurar algo e não apenas expôr suas idéias que contradizem tudo que você diz que leu. Aliás até o texto de onde você tirou esta figura também tem um exemplo gráfico sobre DTO e uma explicação textual.

Bom, eu desisto de conversar com você, com a consciência limpa de ter tentado mesmo após tantas besteiras e tantos ataques em tantas outras trheads (é só ver o histórico do usuário acima).

É mais que óbvio que você quer concluir suas coisas partindo da sua própria opinião e se recusa a procurar mais sobre o assunto. Se alguém quiser conversar sobre este tema sinta-se a vontade, eu apenas não respondo mais ao colega acima nem neste tópico nem em qualquer outro.

sergiotaborda

mutano:
Calma sergio! O pcalcado só está ajudando. Se tu lesse o artigo direito veria que essa figura se refere ao Anemic Domain Model que o artigo mostra como problema e não como solução!

Exactamente. O problema qual seria ? Ter dois tipos de objetos : os TO (VO,DTO, chamem como quiserem) e aquilo que o artigo chama de BusinessObject. Eu sei perfeitamente que isto não é um Domain Model porque um Domain model é a fusão daqueles dois objetos.

Ora , então a logica é: se TO é sinónimo de ADM , retirese o TO e deixe fica só o Objecto de Dominio (OD). O que o pcalcado falou é que pode usar TO que isso não contraria / impede usar OD. Mas o artigo e o prórpio principio do Anemic Domain Model diz exatamente o contrário. TO não existem num Domaim Model verdadeiro, só existem OD.

Mas o pcalcado não partilha desta opinião e falou que sim pode usar TO o que é uma contradição.
Eu partilho a opinião do louds que pode usar os dois e pedi exemplos de como encaixar os dois. MAS se eu usar essa forma, eu estarei automáticamente usando um Anemic Domaim Model. Nem o artigo, nem o Martin , nem ninguém até agora explicou como se usa Domain Model sem TO num ambiente destribuido. A minha opinião é que isso simplesmente não é possivel porque sempre teremos camadas inevitavelmente sempre teremos TO e portanto inevitavelmente caímos no ADM.

R

Olá, estou bem atento a esta thread, pois OO é algo que sempre me interessa… Porém ainda não entendi uma coisa: por exemplo, eu tenho um formulário de cadastro de disciplinas, o usuário entra com os dados da nova disciplina, quando ele clica no botão salvar, ele salvará estes dados em um objeto, será tratado e só então transferido ao domain model? É isto?

Ainda nãi está claro para mim.

Alguém possui exemplos web e/ou desktop para que eu possa entender melhor?

louds

Sérgio, você tem certeza que leu o artigo do Fowler sobre DTOs? Por que lá está super claro como você faz para transformar entre o DTO e os objetos de domínio.

Se o idioma for problema, o tradutor do google deve dar conta, já que ele usa um ingles muito regular.

Inclusive, ele recomenda usar outro pattern do PEAA para resolver isso.

leomc

sergiotaborda:
Nem o artigo, nem o Martin , nem ninguém até agora explicou como se usa Domain Model sem TO num ambiente destribuido. A minha opinião é que isso simplesmente não é possivel porque sempre teremos camadas inevitavelmente sempre teremos TO e portanto inevitavelmente caímos no ADM.

Você leu isso sério?

Nessa sua aplicação ultra complexa aí que talvez pudesse ser feita de forma bem mais simples mas por algum motivo tem que ser distrbuída, você poderia usar DTOs pra levar os dados do swing para o servidor chegando lá(na camada de serviços) você instancia um objeto de domínio e executa metódos de negócios que fazem parte única e exclusivamente dos seus objetos de domínio.
Você tem DTOs, apenas porque quer fazer sua aplicação distribuída mas seus objetos de domínio tem seus atributos e suas operações.

A

sergiotaborda:
Nem o artigo, nem o Martin , nem ninguém até agora explicou como se usa Domain Model sem TO num ambiente destribuido. A minha opinião é que isso simplesmente não é possivel porque sempre teremos camadas inevitavelmente sempre teremos TO e portanto inevitavelmente caímos no ADM.

Concordo na parte que de qualquer jeito vc cai num ADM. Discordo na parte onde vc fala que o Martin não explicou. Ele explicou… :wink:

louds:
Se o idioma for problema, o tradutor do google deve dar conta, já que ele usa um ingles muito regular.

Comentário desnecessário.

sergiotaborda

louds:
Sérgio, você tem certeza que leu o artigo do Fowler sobre DTOs? Por que lá está super claro como você faz para transformar entre o DTO e os objetos de domínio.

Se o idioma for problema, o tradutor do google deve dar conta, já que ele usa um ingles muito regular.

Inclusive, ele recomenda usar outro pattern do PEAA para resolver isso.

Paternalismo à parte (que contnuo achando ofensivos)… e só para vcs terem a certeza que eu li aqui vai o texto relevante

Mas lá não tem nenhum código. Eu pedi exemplos de código que vcs já tenham usado nesta situação. Mas como já entendi que vcs não tem esses exemplos nem vou mais perguntar nada.

Eu acho claro que usar Domain Model pode ser compativel com TO embora os TO violem explicitamente o segundo texto que citei. Duplicando até os dados do dominio que podem ser complexos. É possivel ? sim. É Anemico ? Sim! é este o ponto que eu gostaria de discutir e não o que eu li ou deixei de ler, que idade eu tenho ou se sei inglês. OK !?

sergiotaborda

leomc:

Nessa sua aplicação ultra complexa aí que talvez pudesse ser feita de forma bem mais simples mas por algum motivo tem que ser distrbuída, você poderia usar DTOs pra levar os dados do swing para o servidor chegando lá(na camada de serviços) você instancia um objeto de domínio e executa metódos de negócios que fazem parte única e exclusivamente dos seus objetos de domínio.
Você tem DTOs, apenas porque quer fazer sua aplicação distribuída mas seus objetos de domínio tem seus atributos e suas operações.

Eu dei esse exemplo porque é mais clara a necessidade de DTO, mas pode pensar em ambiente web usando ActionForms. Vai dar no mesmo. Vc usa objetos para conter os dados que não são objetos do dominio. Esses são os objetos anémicos que o Martin fala (anémicos pq não tem comportamentos de negocio)

sergiotaborda

Taz:
sergiotaborda:
Nem o artigo, nem o Martin , nem ninguém até agora explicou como se usa Domain Model sem TO num ambiente destribuido. A minha opinião é que isso simplesmente não é possivel porque sempre teremos camadas inevitavelmente sempre teremos TO e portanto inevitavelmente caímos no ADM.

Concordo na parte que de qualquer jeito vc cai num ADM. Discordo na parte onde vc fala que o Martin não explicou. Ele explicou… :wink:

Ok. Cite essa explicação, ou explique qual é,pq eu não a encontrei.

louds

sergiotaborda:

Mas lá não tem nenhum código. Eu pedi exemplos de código que vcs já tenham usado nesta situação. Mas como já entendi que vcs não tem esses exemplos nem vou mais perguntar nada.

Eu acho claro que usar Domain Model pode ser compativel com TO embora os TO violem explicitamente o segundo texto que citei. Duplicando até os dados do dominio que podem ser complexos. É possivel ? sim. É Anemico ? Sim! é este o ponto que eu gostaria de discutir e não o que eu li ou deixei de ler, que idade eu tenho ou se sei inglês. OK !?

Não é paternalismo, mesmo porque seu significado não cabe, é simplesmente o fato que as respostas estão no texto de maneira clara e você parece que não lê.

Em um sistema distribuido você tem os Assemblers convertendo entre Domain Objects e os DTOs, fora essa conversão, teu modelo continua rico, pois todo comportamento não escapou do lugar que deveriam ficar.

Quanto ao que constitui aquilo que o Martin Fowler chama de Anemic Domain Model, como você mesmo colocou, é uma quimera, um engodo, é ter objetos que parecem/deveriam possuir comportamento rico, porém não passam de simples struts.

Seguindo essa linha, chamar um sistema que usa de DTO de anêmico não tem sentido, afinal, os objetos utilizados para transporte de rede fazem exatamente aquilo que se propoem e parecem. Ninguém vai confundir um DTO com um DO, no caso de ambos existir.

DTOs são um artifício para otimizar o transporte pela rede. Falar que eles invalidam o uso de domain modeling é tão sem nexo quanto dizer que por precisar converter de String para int o conteúdo de um textfield quando transfere o valor da GUI para o domain model, o sistema é anêmico.

Um sistema não existe somente com o domain model, existem muitas outras partes que não necessáriamente possuem um domínio, tão pouco precisem. O fato de ser anêmico, como o Fowler fala, a grosso modo, diz mais a respeito a programadores que escrevem código lixão achando que estão usando DDD e abafando.

Você quer código? Bom está ai seu código de como suar DDD com DTOs:

class ConsultaPorNomePessoaDTO {
  String nome;
}

class Pessoa {
  String nome;
  String sobrenome;

  public boolean possuiParentesco(Pessoa outra) { return sobrenome.equals(outra.sobrenome); }
}

class PessoaAssembler {
    public ConsultaPorNomePessoaDTO conv(Pessoa p) {
ConsultaPorNomePessoaDTO dto = new ConsultaPorNomePessoaDTO();
dto.nome = p.nome + " " + p.sobrenome;
return dto; 
}

public Pessoa conv(ConsultaPorNomePessoaDTO p) {
   return PessoaRepository.recuperaPorNomeCompleto(p.nome);
}
}

interface SistemaXptoFacade {
   List<ConsultaPorNomePessoaDTO> buscaParentes(String nomeCompleto();
}

Veja nesse exemplo que: o DO possui comportamento; o DTO é usado apenas para transferencia de dados pela rede; e o Assembler é utilizado para conversão.

sergiotaborda

louds:

Veja nesse exemplo que: o DO possui comportamento; o DTO é usado apenas para transferencia de dados pela rede; e o Assembler é utilizado para conversão.

Blz. Então agora me diga pq vc não pode simplesmente eliminar o DTO e fazer assim :

class Pessoa implements Serializable{
   String nome;
   String sobrenome;
 
   public boolean possuiParentesco(Pessoa outra) { 
     return  sobrenome.equals(outra.sobrenome); 
  }

  String getNomeCompleto(){
     return p.nome + " " + p.sobrenome;
  }

 
 public static Pessoa busca(String nomeCompleto) {
    return PessoaRepository.recuperaPorNomeCompleto(nomeCompleto);
 }

 }
 
 interface SistemaXptoFacade {
    List<Pessoa> buscaParentes(String nomeCompleto);
 }
Thiago_Senna

Simples! Se for possível evitar o DTO, evite. Se você for obrigado a usá-lo (e isso acontece), use-o.

sergiotaborda

Embora o seu comentário seja tautologico a conclusão que eu queria chegar é : Você sempre pode evitar DTO.

Parece que cabe um resumo da opera…

  1. Orientação Objetos ensina que Objeto é um ente que associa dados com comportamento sobre esses dados e que deve ser criado um modelo de dominio. O modelo de dominio é um conjunto de classes , relacionadas entre si, que possuem estado e comportamento.

  2. Face à necessidade de criar aplicações em várias camadas e popularizado pela fraca especificação EJB 1 e 2 foram introduzidos os conceitos de objeto de transferencia (TO / DTO) e objeto de negocio (Bo/ EJB Statless) . O primeiro contém apenas estado e o segundo apenas comportamento.

  3. Martin Fowler e outros defenderam que isso é um falso modelo de dominio porque desassocia o comportamento do estado violando portanto a permissa numero 1 de Orientação a Objetos. Ele chamou a este pseudo modelo de dominio : Modelo de Dominio Anémico (Anemic Domaim Model)
    e defendeu que o dominio puro deva ser usado.

3.1) Martin Fowler e outros tb reconhecem que o dominio puro não é prático numa aplicação destribuida e portanto é necessário fazer uso de TO/DTO criando assim um modelo híbrido que funciona graças à introdução do papel do Assembler : um objeto que traduz DTO em Objetos de Dominio e vice-versa. Este modelo é semelhante ao usado em EJB até À versoa 2.1 quando Entity Beans são usado como objetos de negocio e têm que ser convertidos em DTO para possibilitar comunicação com as outras camadas/nodos do sistema.

sintese: Identiifa-se um anti-pattern , o anemic domaim model, e propoe-se uma solução igualmente anémica já que ao existrem objectos DTO é possivel que , em qualquer camada , sejam construidos objetos de negocio no estilo dos usados no modelo anémico. Parece então que o modelo anémico é intrinseco a aplicações destribuidas e portanto ele não seria um anti-pattern nesse tipo de aplicações.
Sendo que todas as aplicações sérias são distribuidas (por nodos ou camadas, ou ambos) o modelo anémico é portanto inevitável.
E é até defendido como se viu nas respostas deste tópico.

conclusão: Embora todo o mundo saiba dos males do modelo anémico e alerte para o seu não-uso , todo o mundo, simultaneamente aceita que ele deve ser usado. Isso para mim é um contradição grave , que demonstra a falta de viabilidade em aceitar a ideia que existe tal coisa como um modelo de dominio puro. Esta ideia é suportada na crescente onde de orientação a serviços (outro nome possivel para a figura dos objetos sem estado e só com funcionaldiade) junto com coisa como BPM.
Concluo portanto que , em sisteas sérios, não ha espaço para modelo de domínio puro e que o uso de DTO é inevitável.

Prólogo
Isto é verdade a menos que o próprio objeto de domínio possa fazer o papel de DTO. O que à partida parece simples. Basta fazer o objeto serializável. Por outro lado, um objeto de dominio pode depender de serviços externos , até mesmo de serviços de outras aplicações. Exemplo são a consulta de crédito no Serviço de Proteção ao Crédito, ou uma simples consulta de frete baseado no CEP dado pela empresa transportadora. Embora isto possa ser incluido como uma lógica no modelo de dominio, é na realidade uma lógica trans-dominio (entre dominios) e isso trás problemas práticos que são mais facilmente resoluveis se optarmos por um modelo anémico : objetos de dados + objetos de lógica/serviço/negocio.

Algo a acrescentar ?

sergiotaborda

ficaram algumas perguntas pendentes no meio desta conversa:

:arrow: O uso de TOs transforma o meu modelo num Anemic Domain Model?
:arrow: o usuário entra com os dados da nova disciplina, quando ele clica no botão salvar, ele salvará estes dados em um objeto, será tratado e só então transferido ao domain model? É isto?

Mauricio_Linhares

Não.

sergiotaborda:
:arrow: o usuário entra com os dados da nova disciplina, quando ele clica no botão salvar, ele salvará estes dados em um objeto, será tratado e só então transferido ao domain model? É isto?

Normalmente é assim, a GUI dificilmente já traz tudo pronto e é por isso que existem os controllers. Eles recevem as informações da GUI, transformam em objetos que o Model entende e repassam pro Model fazer o que ele tiver que fazer.

R

Só estou com mais duas dúvidas:

  1. Como é feita a passagem dos dados do TO para o Domain Model? Via uma façade?

  2. Quem que efetua as chamadas ao DAO? O Domain Model? Ou entre o DAO e o Domain Model existe uma camada?

A ideia seria uma arquitetura da seguinte forma:
View -&gt Controller -&gt Façade -&gt Domain Model -&gt DAO

E para a passagem dos valores da view para o controller e para o domain model utiliza-se um TO?

A ideia é esta? entendi direito?

Thiago_Senna

Não concordo com esta afirmação. Quero ver como você vai evitar o DTO em uma tela que exige muita informação de pontos diferentes do domínio sem prejudicar o desempenho da aplicação, caso o seu cliente faça questão de um bom desempenho! :wink:

louds

Sérgio, o seu problema é que você faz questão de entender tudo sempre pela metade. Um sistema distribuido não precisa de DTOs.

Um sistema distribuido é contruido em volta de RPC, MOM ou qualquer outro modelo. Todos estes trocam alguma forma de mensagem entre sí e isso é uma característica extrinsica a serem desenvolvidos com linguagens OO.

Quando escrevemos um sistema distribuido com uma linguagem OO, desejamos que as mensagens trocadas sejam objetos, esta, senão é apenas a única razão para termos troca de objetos entre tiers de um sistema. Isso ainda lembrando que precisamos de uma camada de marshaling, que externaliza o estado dos objetos.

Dito isso, em um sistema escrito com EJB3, por exemplo, podemos mandar as próximas entidades entre tiers do sistema, não existe problema nisso. Inclusive é a forma preferencial de se trabalhar. Quanto ao fato de se utilizar DTOs, todos aqui assumimos erroneamente que você sabia qual era a utilidade desse design pattern, deixe-me explicar então. DTOs são utilizados para otimizar o uso da rede, seja para transferir menos dados, ou reduzir o número de round-trips.

Acho que o problema é que você fica imaginando sobre esses ‘sistemas sérios’ imaginários e não sabe do que está falando. Qual sua experiência com sistemas grandes e distribuidos? Lembre que o pessoal que tentou te ajudar nesse tópico tem larga experiência com sistemas grandes que precisam ser muito escalaveis.

sergiotaborda

Não concordo com esta afirmação. Quero ver como você vai evitar o DTO em uma tela que exige muita informação de pontos diferentes do domínio sem prejudicar o desempenho da aplicação, caso o seu cliente faça questão de um bom desempenho! ;)

O louds já respondeu a isso. Voce usa EJB 3 ou mais concretamente JPA
Vc não precisa de DTO , vc pode usar os próprios entities. Isto vc não podia fazer com EJB 2 e antes. Quer dizer, poder podia, mas não era recomendado.

O JPA trás outr a funcionalidade que é integração dos objetos de negocio com as outras camadas. Já que eles são POJO/Bean normais outros frameworks podem usá-los facilmente. Como o JGoodies, por exemplo.

sergiotaborda

“Todos” aqui assumem demais. Eu tb assumi muitas coisas. Por exemplo, que todos aqui eram educados e que sabiam ler português. Esta conversa de mercador já encheu o saco. Tenham por certo que nunca mais irei iniciar um tópico ou incomodá-los com meus dilemas.
Afinal não sou masoquista.

Boa sorte a “todos”.

O

Todo mundo fala que EJB3 é uma maravilha.
No sentido tecnológico em relação as versões anteriores é verdade.
Mas como vcs tratam no EJB3 o lazy loading , enviando os entities para o client, onde não existe o contexto da JPA ?

pcalcado

Da mesma maneira que sempre se fez com hibernate:

Paulo_Silveira

pcalcado:
Da mesma maneira que sempre se fez com hibernate:

PC, acho que ele quis saber como fazer com o lazy no caso de estar usando JPA com EJB. Ai no cliente do EJB nao tem como fazer “open session in view”, porque nesse caso os objetos SEMPRE estao detached no cliente. entao tem de inicializar antes o que for preciso, ou mudar o fetch mode nas queries.

Eu comentei algo parecido com isso aqui:

louds

Se você estiver com muita boa vontade, tem como permitir sim lazy-loading no cliente. É um trampo enorme, mas funciona. Existem várias estratégias para resolver isso.

Uma você manda a session do hibernate junto no payload de resposta (manda ela desinflada) e reconecta no cliente, o problema disso é que o cliente estará conectando no banco de dados.

Em outra você mantem a session do hibernate escondida em um SFSB e faz lazyloading remoto.

Por fim, a última você edita o stack de eventos do hibernate de forma que quando a session chegar no cliente, ela vai transformar eventos de lazy loading em chamadas remotas.

O maior problema disso é que acaba gerando maior load no servidor e aumenta em MUITO o número de round-trips, possivelmente tornando o sistema perceptivelmente lento.

Paulo_Silveira

Como? Na hora que ele chamar o getter do meu entity que ta desatachado ele nao vai la no SFSB pedir o restinho… O que voce estava falando nao é Java EE compliant, certo? Alias, todas as maneiras que voce citou.

louds:

O maior problema disso é que acaba gerando maior load no servidor e aumenta em MUITO o número de round-trips, possivelmente tornando o sistema perceptivelmente lento.

E isso é EXATAMENTE o que o EJB3 veio resolver, pra que ninguem tenha de ficar fazendo VOs e evitar as zilhares de chamadas remotas

louds

Paulo Silveira:
louds:

Em outra você mantem a session do hibernate escondida em um SFSB e faz lazyloading remoto.

Como? Na hora que ele chamar o getter do meu entity que ta desatachado ele nao vai la no SFSB pedir o restinho… O que voce estava falando nao é Java EE compliant, certo? Alias, todas as maneiras que voce citou.


Se você usar JPA não vai ser compliant, se usar hibernate, não influencia. O truque é você serializar a session no servidor e no cliente substituir ela por uma fachada remota.

Paulo Silveira:

louds:

O maior problema disso é que acaba gerando maior load no servidor e aumenta em MUITO o número de round-trips, possivelmente tornando o sistema perceptivelmente lento.

E isso é EXATAMENTE o que o EJB3 veio resolver, pra que ninguem tenha de ficar fazendo VOs e evitar as zilhares de chamadas remotas

A sim, mas alivia de um lado e aperta do outro. Com lazy loading você é obrigado a materializar tudo que deseja enviar, o esforço é menor que usar DTOs, mas não deixa de ser um porre.

Paulo_Silveira

louds:
Paulo Silveira:
louds:

Em outra você mantem a session do hibernate escondida em um SFSB e faz lazyloading remoto.

Como? Na hora que ele chamar o getter do meu entity que ta desatachado ele nao vai la no SFSB pedir o restinho… O que voce estava falando nao é Java EE compliant, certo? Alias, todas as maneiras que voce citou.


Se você usar JPA não vai ser compliant, se usar hibernate, não influencia. O truque é você serializar a session no servidor e no cliente substituir ela por uma fachada remota.

Ave maria! Muito arrojado pra mim :slight_smile: Mas funciona sim. Eu queria era ver se alguem descobria como fazer isso no JPA sem gambiarras…

rodrigoy

Como sempre digo, cliente desconectado o buraco é mais em baixo…

Não consegui ler o post inteiro, mas vamos tentar ajudar:

Swing + Parte Servidora não Exige DTO

Uma prova disso é o sisteminha Bitshop que desenvolvi na minha série de artigos Design Patterns para um Mundo Real na MundoJava. Tem código fonte aqui:

http://www.aspercom.com.br/bitshop

Algumas vezes tento driblar o Lazy Load fazendo uma AppFaçade Stateful sem mandar a entidade desatachada pro cliente. (ver EmitirPedidoFacade no código). Acho que é isso que o Louds falou.

Não sei se a desculpa da Sun para usar DTO para economizar rede é um negócio 100% verdade. Não fiz nenhum benchmark e não ví nenhum que prove isso.

Um cliente Swing requer um cuidado maior com os objetos desatachados, mas não é impossível de resolver sem DTO. Geralmente eu avalio a possibilidade de colocar um lazy false senão for uma boa avalio fazer uma AppFaçade Statefull, só então recorro ao DTO.

DTO dá nojo. Não existe tamanho único. Se você for fundamentalista e sempre trabalhar com DTO e Assemblies, desenvolver o sistema é um pé no saco, principalmente porque o binding de tela não é trivial…

Falows!?

rodrigoy

(escrevi besteira, já está editado)

brunohansen

Estou chegando meio tardemas…

Shoes só pra confirma uma coisa aqui.
Quando o Controller instancia o Objeto de Dominio ele acaba executando uma pouco de regra de negocio para a instanciação do Objeto de Dominio. Estas regras no caso estão dentro do construtor do Objeto de Dominio, sendo assim podemos até dizer que é o objeto de dominio que executa essas regras.

Concordas?

pcalcado

Oi,

Sim, é o objetod e domínio que executa. Se o fluxo originou-se de um objeto de outra camada não importa, o importante é que quem executou foi o objeto correto.

Hermesnet

Olá pessoal do GUJ,

Nossa, li toda a discussão sobre o assunto e estou impressionado como existem pessoas que pedem opiniões, não as reflete, e pior ainda, não as aceita.

Bom mais isso não vem ao caso.

Pelo que eu entendi, nesta discussão toda e alguns artigos que li, é que o ADM do nosso guru Martin Fowler quis expressar uma preocupação que ele tem com alguns desenvolvedores que estão construindo projetos OO sem ter noção do que estão fazendo, ou por não terem compreendido corretamente os padrões(VO, TO e DTO) e seus objetivos ou simplesmente não entenderam as primícias da OO.

Ao projetar um projeto grande ou pequeno(pois isso é muito relativo do ponto de vista do ego das pessoas) umas das primeiras atividades que nós temos que ter em mente é definir o Domínio do Negócio. E o que o Martim Folwer quis dizer é que estão definindo modelos de domínio de negócio utilizando essa tríplice (VO, TO, DTO) para auxiliar na troca de mensagem dos objetos e ele definiu isso como um ADM.

Alguém por gentileza, poderia me dizer se esta conclusão está equivocada ?

Abraço à todos.

dias.rodolfo

Ola, reparei que o problema aqui em discussao eh o Lazy Loading em clientes EJB3 onde as entidades estao detachadas, vi que as sugestoes do louds acabam todas por chamadas remotas com excecao da conexao aberta no cliente, o que tambem em miudos tambem acaba em conexao remota, mesmo se usarmos SFSB estaremos usando conexao remota, ou seja, de qualquer forma a conexao sera remota, e nao acho isso um problema, afinal a computacao distribuida foi feita para que conexoes remotas sejam feitas, mas o ponto aqui eh o seguinte, como fazer Lazy em entidades detachadas? Existe um framework chamada DataSlim que cria uma estrutura Lazy Loanding em qualquer ambiente inclusive no JPA e que pode ser usada em Entidades Detachadas, porem, como qualquer outra solucao ele fara um conexao remota sempre que um dado Lazy tiver que ser recuperado, porem a conexao pode ser feita para um Stateless, ou seja, nao precisamos ficar criando Stateful (que ao meu ver, sempre foi dito pra se evitar), nem abrindo transacao na camada view, o DataSlim simplesmente conecta com um Stateless que esse sim tem escopo transacional e executa o metodo responsavel por retornar os dados Lazy, ou seja, continuamos com a separacao de responsabilidade entre as camadas. Outro ponto importante quando estamos trabalhando em contextos transacionais como dentro do servidor o dataslim nao interage com o objeto entidade, ou seja, o mecanismo de Lazy pode ser usado apenas quando a entidade eh detachada, quanda a mesma ainda esta " atachada " o que vai prevalecer sera o mecanismo de Lazy do Container (Hibernate ou TopLink ) isso eh bom pois nao precisamos agora escrever clientes que precisem de qualquer alteracao quando formos usar um Framework de Persistencia ou outro.
Bom… A ideia eh mais abrangente mas espero ter dado uma ajuda.
DataSlim: http://code.google.com/p/dataslim

L

Olá pessoal, ainda estou com as seguintes dúvidas:

  1. Como é feita a passagem dos dados do TO para o Domain Model? Via uma façade?

  2. Quem que efetua as chamadas ao DAO? O Domain Model? Ou entre o DAO e o Domain Model existe uma camada?

A ideia seria uma arquitetura da seguinte forma:
View -> Controller -> Façade -> Domain Model -> DAO

E para a passagem dos valores da view para o controller e para o domain model utiliza-se um TO?

A ideia é esta? entendi direito?

Criado 23 de março de 2007
Ultima resposta 3 de abr. de 2008
Respostas 47
Participantes 17