Anemic Domain Model e sistemas sérios

[quote=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.
[/quote]

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 !?

[quote=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.[/quote]

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)

[quote=Taz][quote=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.
[/quote]

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:
[/quote]

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

[quote=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 !?[/quote]

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.

[quote=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.[/quote]

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);
 }

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

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 ?

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?

Não.

[quote=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?
[/quote]

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.

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?

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:

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.

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! ;)[/quote]

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.

“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”.

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 ?

Da mesma maneira que sempre se fez com hibernate:

[quote=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:

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.

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.

[quote=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.[/quote]

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

[quote=Paulo Silveira][quote=louds]
Em outra você mantem a session do hibernate escondida em um SFSB e faz lazyloading remoto.
[/quote]

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.
[/quote]
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.

[quote=Paulo Silveira]

[quote=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.[/quote]

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

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.