Modelo Anêmico é realmente ruim?

Vc terá uma classe que vou chamar de action com um método onde vc decide que o objeto deve ser persistido ( normalmente em resposta a um gesto do usuário ou evento do sistema). Essa classe tem em seu poder um atributo do tipo do DAO certo para a entidade em causa.
Esta classe não instancia o DAO. Ela recebe uma instancia no seu construtor (inversão de conrole) e apenas usa essa instancia que foi passada.
Quando ela quiser persistir a entidade ela invoca algum método do DAO.

O dao não é um atributo da entidade e muito menos uma propriedade (propriedade significa que ha um get/set para ele).

[quote=sergiotaborda][quote=Frango]
Mas uma dúvida que ainda tenho, como fica a persistência desses objetos? Eu posso ter um DAO como propriedade da entidade ou eu tenho que instanciar o DAO dentro dos meus métodos apenas quando eu precisar usa-los?
[/quote]

Vc terá uma classe que vou chamar de action com um método onde vc decide que o objeto deve ser persistido ( normalmente em resposta a um gesto do usuário ou evento do sistema). Essa classe tem em seu poder um atributo do tipo do DAO certo para a entidade em causa.
Esta classe não instancia o DAO. Ela recebe uma instancia no seu construtor (inversão de conrole) e apenas usa essa instancia que foi passada.
Quando ela quiser persistir a entidade ela invoca algum método do DAO.

O dao não é um atributo da entidade e muito menos uma propriedade (propriedade significa que ha um get/set para ele).
[/quote]

Sergio, vc injetaria a DAO na classe do dominio? Pq se vc fizer atraves do construtor devera colocar sua referencia em algum atributo…nao??

Ou vc passa metodo a metodo?

[quote=rogelgarcia]Andei pesquisando aqui na internet e achei alguns posts sobre o Anemic Domain Model, para ver se eu entendia realmente o que queria dizer…

Esse artigo mostra modelos de código
http://vitamic.wordpress.com/2007/01/04/anemic-domain-model-illustrated/

O que eu defendia, é que não há nada de errado em ter classes com apenas getters e setters… ou seja, do meu ponto de vista esse anemic model (classes só com getters e setters) não é um problema…

O sergio também concorda que pode haver esse tipo de objetos com apenas getters e setters (conforme artigo em seu blog)…

Agora os que não gostam do anemic model, querem colocar as funcionalidades no modelo, por exemplo o método salvar… como até dito no artigo do link que postei…

O que eu considero errado…
[/quote]

Totalmente de acordo com isto.
O conceito de que o salvar deve ser colocado no objeto vem do anti-pattern active record e má interpretação de “comprotamento”

Comportamente é algo que a classe faz, não é algo a que ela se submete.
Quando uma pessoa chuta uma pedra isso é um coportamento, quando alguem dira uma foto dela, isso não é um comportamento.
Persistencia é como tirar fotos. É trabalho do fotografo, não da pessoa que é fotografada.

As pessoa associam erradamente “save” como “comprotamento da classe” e por isso acham que colocar o save na classe iliba a classe de ser anemica.
Estas pessoas cometam um erro. Ao tentar não consturir um modelo “anêmico” acabam construindo um modelo acoplado e pouco coeso.Ou seja, acabam construindo uma porcaria de modelo.

Não ha nenhum problema em ter objetos apenas com get/set (padrão PropertyBag)

O problema que se chama de anemia é uma responsabilidade que seria do objeto está sendo colocada em outro objeto. Esta inversão de papeis ou errada atribuição de responsabilidade é que leva a uma falta de coesão. anemia = falta de coesão.

A coesão não é medida pelo numero de metodos que a classe tem, mas pelo quanto esses métodos dizem respeito a essa classe.

Um erro muito comum é colocar métodos com regras de negocio na entidade. Por exemplo tem um objeto Conta com métodos transferePara(Conta outra), ou objetos Pedido com métodos “finalizar” … Isto é um pesadelo. Na ansia de fugir da anemia (que na realidade as pessoas nem entenderam o que é e acham que se resume a ter apenas get/set - e a culpa disso é da media que vincula essa ideia ) as pessoas acabam criando modelo errados

Na escala de WTF/segundo um modelo onde existe apenas propertybags e objetos que as manipulam é muito mais aceitável que um modelo onde existe objetos com muitos métodos , cheios de regras de negocio que visivelmente foram enxertadas à força neles.

Pegando o exemplo do Endereço. Depois que o cara montou os atributos, e colocou o método “save” que delega para um DAO, ele ainda cria um método “encotnrar por CEP” como estático de Endereço. Este tipo de modelo é uma porcaria e as pessoas não devem usá-lo. Nunca!

como sempre, seguir as boas práticas OO é mais importante. E a primeira é : Separação de Responsabilidade.
às vezes eu acho que as pessoas , ou não sabem o que é separação, ou não sabem o que é responsabilidade… ou os dois.

Modelo anêmico não aquele que tem apenas propertyBags, e sim aquele em que as responsabilidades estão mal distribuidas.
O termo foi abusado pro muita gente demasiado literalmente levando à ideia de que objetos apenas com get/set são ruins.
Isso é uma falácia imensa criada por pessoas que não entendem OO.

Não ha nenhum problema em ter acessores e modificadores ( get/set) nas classes desde que isso seja correto do ponto de vista do modelo. Por exemplo, ter um getIdade/setIdade é errado, não porque é get/set mas sim porque idade é algo dinamico. Tem um getIdade(Date) é rrado porque acessores não tem parametros. O correto é ter um método chamado idadeEm(Date):int porque não é uma propriedade, é um valor calculado com base nas propriedades e numa data.

Agora, Se eu tiver 3 classes que precisam de calcular idade o que devo fazer ?

  1. Criar uma classe utilitária que recebe o objeto e calcula a sua idade (Idades.idadeDe(Pessoa, Date) , Idade.idadeDeCasa(Casa, Date , etc…)
  2. Manter um método idadeEm(Date):int em cada um copiando o codigo e alterando conf0orme as propriedades de cada objeto
  3. Manter um método idadeEm(Date):int em cada um , mas invocando um método de pacote de um classe utilitária que recebe duas data e calcula a ideia ?

A terceira. O modelo é correto, e a implementação é DRY (Don’t repeat yourself).
A primeira é anêmica, e a segunda não é DRY.

O modelo anêmico é ruim, mas pior é o modelo “tudo junto na mesma classe”.

[quote=dohko][quote=sergiotaborda][quote=Frango]
Mas uma dúvida que ainda tenho, como fica a persistência desses objetos? Eu posso ter um DAO como propriedade da entidade ou eu tenho que instanciar o DAO dentro dos meus métodos apenas quando eu precisar usa-los?
[/quote]

Vc terá uma classe que vou chamar de action com um método onde vc decide que o objeto deve ser persistido ( normalmente em resposta a um gesto do usuário ou evento do sistema). Essa classe tem em seu poder um atributo do tipo do DAO certo para a entidade em causa.
Esta classe não instancia o DAO. Ela recebe uma instancia no seu construtor (inversão de conrole) e apenas usa essa instancia que foi passada.
Quando ela quiser persistir a entidade ela invoca algum método do DAO.

O dao não é um atributo da entidade e muito menos uma propriedade (propriedade significa que ha um get/set para ele).
[/quote]

Sergio, vc injetaria a DAO na classe do dominio?

[/quote]

não.

[quote]
Pq se vc fizer atraves do construtor devera colocar sua referencia em algum atributo…nao??
Ou vc passa metodo a metodo?[/quote]

O que eu falei é que vc tem três classes , action, o DAO e a entidade e vc usa assim



public class Action {

  private final DAO dao;

 public Action  (DAO dao){
    this.dao = dao;
 }
 
 public void fazAlgumaCoisaQueOusuarioMandou(){
      
    Entidade instancia = new Entidade();
 
   // faz alguma coisa com instancia e por fim salva

    dao.save(instancia);

  }

}

[quote=dohko][quote=rogelgarcia]

Alguns vão dizer que o anemic model é o que é exemplificado em 0, 1, 2, 3 ou 4…

Varia de acordo com a interpretação… o que eu considerava que seria anemic model … seria o exemplo 0 ou 1…

No caso eu recomendaria fazer como no exemplo 1… Eu considero como anemic model (de acordo com o que eu já ouvi falar) … mas não acho ruim… considero ser a melhor opção…

Vemos que o excesso de zelo para se evitar o anemic model, pode piorar o modelo, trazendo para ele responsabilidades que não são pertinentes…[/quote]

eu tenho a mesma visão do roel

Uma dúvida que tenho… eh assim, no modelo ‘rico’, se eu quisesse re-utulizar meu domain model em outra aplicacao seria possivel?
[/quote]

Se vc quer aproveitar o dominio é bom que seja rico mesmo. Não é apenas possivel como é desejável (embora complexo e àrduo).
Vc vai ouvir as pessoas dizerem que entidades não se aproveitam, mas isso é apenas um problema de miopia e não uma realidade.

O que não se aproveita são regras de negocio. então se um cliente deseja que um Pedido se comporte de forma diferente do que um Pedido normal,
vc não pode considerar que isso é parte do dominio genérico.

como vc mostrou que já diivide por cliente as respetivas implementações, eu acho que isso é muito válido.

O modelo ser rico ou não, não tem anda que ver com persistencia. (rico não significa que as entidades têm um maldito save)

[quote=sergiotaborda][

Agora, Se eu tiver 3 classes que precisam de calcular idade o que devo fazer ?

  1. Criar uma classe utilitária que recebe o objeto e calcula a sua idade (Idades.idadeDe(Pessoa, Date) , Idade.idadeDeCasa(Casa, Date , etc…)
  2. Manter um método idadeEm(Date):int em cada um copiando o codigo e alterando conf0orme as propriedades de cada objeto
  3. Manter um método idadeEm(Date):int em cada um , mas invocando um método de pacote de um classe utilitária que recebe duas data e calcula a ideia ?

A terceira. O modelo é correto, e a implementação é DRY (Don’t repeat yourself).
A primeira é anêmica, e a segunda não é DRY.

O modelo anêmico é ruim, mas pior é o modelo “tudo junto na mesma classe”.

[/quote]

Mas Sergio, no modelo correto onde estaria o metodo de pacote? na Classe Idades, certo? e como vc recuperaria isso? Injetaria?

[quote=sergiotaborda][quote=dohko][quote=sergiotaborda][quote=Frango]
Mas uma dúvida que ainda tenho, como fica a persistência desses objetos? Eu posso ter um DAO como propriedade da entidade ou eu tenho que instanciar o DAO dentro dos meus métodos apenas quando eu precisar usa-los?
[/quote]

Vc terá uma classe que vou chamar de action com um método onde vc decide que o objeto deve ser persistido ( normalmente em resposta a um gesto do usuário ou evento do sistema). Essa classe tem em seu poder um atributo do tipo do DAO certo para a entidade em causa.
Esta classe não instancia o DAO. Ela recebe uma instancia no seu construtor (inversão de conrole) e apenas usa essa instancia que foi passada.
Quando ela quiser persistir a entidade ela invoca algum método do DAO.

O dao não é um atributo da entidade e muito menos uma propriedade (propriedade significa que ha um get/set para ele).
[/quote]

Sergio, vc injetaria a DAO na classe do dominio?

[/quote]

não.

[quote]
Pq se vc fizer atraves do construtor devera colocar sua referencia em algum atributo…nao??
Ou vc passa metodo a metodo?[/quote]

O que eu falei é que vc tem três classes , action, o DAO e a entidade e vc usa assim

[code]

public class Action {

private final DAO dao;

public Action (DAO dao){
this.dao = dao;
}

public void fazAlgumaCoisaQueOusuarioMandou(){

Entidade instancia = new Entidade();

// faz alguma coisa com instancia e por fim salva

dao.save(instancia);

}

}
[/code][/quote]

Quando vi isso, logo lembrei do Vraptor… tinha visto isso nele e ia até questionar o pessoal pq a controller tava chamando a dao diretamente… Alguém pode confirmar??

[quote=rogelgarcia]

Pois entao… tem gente que entende que o salvar deve estar no VO … se eu digo que o salvar nao deve ficar no VO… esses que consideram o contrario… chamam o meu modelo de anemico[/quote]

Cara VO não tem nada a ver com persistência! Tem certeza que sabe MESMO o que é VO? Acho que vc está confundindo VO com Entity.

Tem gente que usa o VO como entidade…

Eu quis dizer foi entity mesmo…

Ótima pergunta! (pergunta sarcástica certo?)

Leiam por favor: http://martinfowler.com/bliki/ValueObject.html

Nesse seu mesmo link tem dizendo

“Early J2EE literature used the term value object to describe a different notion, what I call a Data Transfer Object.”

Foi o que eu quis dizer…

[quote=rogelgarcia]Nesse seu mesmo link tem dizendo

“Early J2EE literature used the term value object to describe a different notion, what I call a Data Transfer Object.”

Foi o que eu quis dizer…

[/quote]

VO é uma espécie de DTO que mantém seu estado. O que isto tem a ver com Entity? Uma classe que reflete um registro de uma tabela do banco de dados por exemplo, tem mais a ver com Entity.

[quote=dohko][quote=YvGa]
Eu tenho notado ultimamente que há uma grande preocupacao em estudar design patterns, DDD, TDD e uma serie de coisas sem antes estudar o basico do basico de orientacao a objeto. (Nao eh uma critica ao dohko nao, tenho visto muito mesmo isso.)
[/quote]

Cara, o que vc tá falando? Que eu não sei orientação a objetos??

“Básico do Básico”

Cara… para que possamos ter uma livre discussão, te convido a apresentar a todos os membros do GUJ o básico do básico em orientação a objetos, e ainda… Me convença com embasamento teórico de que usar o seu modelo é melhor que usar o meu![/quote]

Como eu mesmo disse no meu post, nao foi um comentario especificamente direcionado a voce, mas foi colocado sobre o que eu tenho visto em geral.

Nao estou dizendo que voce nao sabe orientacao a objetos. E muito menos que eu sou o cara, e que sei tudo, estou apenas discordando da tua maneira de fazer as coisas.

Quando falo sobre o basico do basico, falo sobre coesao e acoplamento, sobre responsabilidades dos objetos, sobre encapsulamento, etc, os conceitos basicos OO, que visivelmente o modelo BO/VO desrespeita. É muito comum os programadores adorarem design patterns, livros da moda e deixarem de lado esses conceitos basicos. Nao sei se é o seu caso.

Sobre usar convencer alguem que meu modelo eh melhor ou nao, eu dei um exemplo do meu la atras e expliquei os porques de usa-los, voce pode usar o mesmo exemplo e dizer porque o seu seria melhor. Mas desde já adianto que a minha intencao nao é comparar meu conhecimento ao seu, ou se eu sei mais que voce ou nao. Mas como esse é um forum de referencia para a comunidade seria ótimo o pessoal ter base para comparar as opiniões e ter exemplos pra se basear.

[quote=g4j]

VO é uma espécie de DTO que mantém seu estado. O que isto tem a ver com Entity? Uma classe que reflete um registro de uma tabela do banco de dados por exemplo, tem mais a ver com Entity. [/quote]

Beleza cara… voce venceu…

[quote=g4j][quote=rogelgarcia]Nesse seu mesmo link tem dizendo

“Early J2EE literature used the term value object to describe a different notion, what I call a Data Transfer Object.”

Foi o que eu quis dizer…

[/quote]

VO é uma espécie de DTO que mantém seu estado. O que isto tem a ver com Entity? Uma classe que reflete um registro de uma tabela do banco de dados por exemplo, tem mais a ver com Entity. [/quote]

Vc deu a refrencia certa mas embaralhou tudo.

VO do Fowler não tem nada a ver com DTO ou entity.

um registro do banco é um registro do banco, não é DTO nem entity.

Entidade é uma classe , normalmente persistivel, que contem N propriedades. A sua estrutura é muito semlhante ao do registro no banco correspondente. O que caracteriza uma entidade é que ela tem identidade. VO do fowler não têm identidade.

Exemplos de VO do fowler são Color e Date, por exemplo

DTO não é entidade. Nem VO.
Um List pode ser um DTO. O objetivo do DTO é transportar dados da forma mais eficiente possivel em termos de espaço e tempo.

não se utiliza mais a nomenclatura J2EE para VO que se confunde com DTO.

Onde eu escrevi isso?

Não afirmei nada parecido. O que quiz dizer é que uma tupla de uma tabela de um banco de dados tem uma identidade (pk). Um Entity ou Entidade pode se “assemelhar” com isso, ou não?

Exatamente o que eu quiz dizer!

Perfeito. Ainda não entendi onde embaralhei cara.

Pesquisando um pouco mais sobre o assunto, li a mundo java edição 17 que possui um artigo do Philip Calçado, e esse artigo me clareou muito as idéias. Recomendo que quem estiver com dúvida leia!

O modelo rico então é feito de Objetos, DAOs e “Serviços”.
Estes Serviços não se assemelhão aos BOs do modelo anêmico?

Um BO não seria um serviço que além de organizar o fluxo de chamadas também contem os métodos de regra de negócio?

O Serviço no caso implementa regras de negócio que não fazem parte de nenhum objeto do dominio.

Vou usar um exemplo, o de conta corrente. não é um bom exemplo, vou explicar pq mais a frente, mas didaticamente acho que é válido.

A conta corrente tem o método saca (double valor) e deposita(double valor). Esses métodos estão no objeto conta pq é faz sentido para o dominio, vc depoisita e saca dinheiro da conta, não da contaService ou da ContaBO entende?

Agora, no caso da transferencia, como faz? onde vc chama o método tranferencia, na conta que recebe ou na conta que envia o dinheiro? é de responsabilidade da conta transferir dinheiro para outra conta?

Vc poderia (Mas NÃO deveria) criar um serviço de transferencia, que recebe as duas contas e a quantia a ser transferida. algo como transferencia (conta a, conta b, double valor).

no caso, a transferencia faria algo assim:


public class TransferenciaService{

public transferencia (Conta aDebitar, Conta aCreditar, double valor){
     aDebitar.saque(valor);
     aCreditar.deposito(valor);
}
}

A transferencia apenas orquestra as chamadas aos métodos da conta, implementando uma nova regra de negócios. No caso vc teria que transacionar, e etc e tal, mas a idéia é mais ou menos essa.

Agora, pq no caso vc não deveria fazer um TransferenciaService? pq Transferencia é um conceito importante para o dominio (bancário no caso) e faz sentido ter um objeto Transferencia, que executaria o mesmo método que eu escrevi acima. Ai, vc não precisaria de um Service.

Eu não sou muito bom com explicações, mas creio que da pra ter uma idéia do conceito.

O importante a perceber no exemplo que eu dei é que os métodos de negócio continuam na conta, e foram reaproveitados no Service.

Entendi.

Mas tenho outra dúvida, seguindo o seu exemplo.

Eu criei um objeto Transferência. Após executar o método transferência eu tenho que salvar o estado da conta que enviou e da conta que recebeu. Como ficaria isso em código? Teria um serviço que chamaria o método transferir(Conta a, Conta b, BigDecimal valor) da classe Transferência e depois salvaria os objetos Conta? Ou eu devo chamar esse método de dentro da minha classe controladora, por exemplo uma Action do Struts? Eu não posso chamar o método Conta.salvar() de dentro da classe Transferência certo?