Modelo Anêmico é realmente ruim?

113 respostas
N

Estava pesquisando sobre modelo anêmico e todos falam que não se deve separar a parte de propriedades e funcionalidades do objeto.
Que criar objetos VOs e BOs é necessário somente em alguns casos.

Aonde trabalho a arquitetura da aplicação é toda feita entre VOs e BOs e tudo funciona muito bem e me parece bem organizado.

Agora a pergunta, se utilizar do modelo anêmico é realmente ruim? Utilizar um modelo rico é realmente mais vantajoso?

(Eu não estou afirmando que nem um e nem o outro é certo, estou perguntando a opinião de vocês sobre o que acham o mais correto)

Abraços

113 Respostas

Y

Frango:
Estava pesquisando sobre modelo anêmico e todos falam que não se deve separar a parte de propriedades e funcionalidades do objeto.
Que criar objetos VOs e BOs é necessário somente em alguns casos.

Aonde trabalho a arquitetura da aplicação é toda feita entre VOs e BOs e tudo funciona muito bem e me parece bem organizado.

Agora a pergunta, se utilizar do modelo anêmico é realmente ruim? Utilizar um modelo rico é realmente mais vantajoso?

(Eu não estou afirmando que nem um e nem o outro é certo, estou perguntando a opinião de vocês sobre o que acham o mais correto)

Abraços

Da mesma forma, nos tempos de Clipper nao havia orientacao a objetos e havia muitos bons softwares.

Um modelo anemico será necessariamente um fracasso? Nao, ele pode ser organizado e mesmo simples. Mas ele jamais terá a seguranca de um modelo de dominio bem feito, com os objetos respeitando suas responsabilidades e encapsulando o que nao deve ser mostrado ao mundo externo, so para citar um dos motivos de eu nao gostar dele. Ha outros.

Alem da diferença entre o seu conceito de organização e o meu conceito de organização. O seu conceito será formado pela comparação a outros codigos que voce já viu e considera organizado, que são diferentes dos códigos que eu já vi e considero organizado.

Resumindo minha opiniao, um modelo anemico pode até ter uma certa organização, facilidade de compreensao e de manutencao, mas sem duvida teria mais ainda tudo isso se nao fosse anemico.

A

Frango, esse modelo acadêmico eu entendo de certa forma como uma visão “conceitual” do domínio. Por exemplo: podemos usar isso em diagramas de classe para dizer quais são as operações daquele objeto e não necessariamente que a implementação do objeto terá tudo programado lá dentro.

A

como eu já tinha certo conhecimento disso, mas nao lembrava como aprendi… resolvi dar uma pesquisada no assunto de Modelagem de dados, onde encontrei:

Modelo Conceitual:
Representação dos conceitos e características observados no ambiente;
Ignorar particularidades de implementação.

P

Vc conseque imprimir todos os fontes em 4 paginas A4 com fonte legal, legivel ?

Se sim o seu modelo é tão simples que qualquer forma que vc codifique-o, da mais procedural a mais OO, vai cumprir o seu papel. Porem se o seu modelo crescer (e geralmente cresce) a forma como vc estrutura os seu codigo se mostra mais ou menos eficiente para desenvolver, manter, testar, etc. Um modelo anêmico te traz este tipo de dificuldade.

Outra coisa é que ter um modelo mais proximo da realidade, com os mesmos termos e nomenclatura, aproxima a linguagem do desenvolvedor com a do ‘analista de negocios’/clientes em geral.

O que o cliente entende: Usar um BO para alterar o VO e persistir usando o DAO no ORACLE ou “o cliente compra uma roupa”?

V

Para mim o modelo anêmico é uma forma disfarçada de estruturar o sistema em módulos, igualzinho se fazia na programação procedural. O enfoque sai dos objetos e volta para os dados, ou “value objects”.

Qual a diferença de um value object para um Struct? E de um BO para um módulo?

N

peczenyj, o sistema no qual me refiro é um sistema relativamente grande, com vários módulos e bem complexo.

Uma coisa que é bastante defendida é que o modelo anêmico dificulta a manutenção.
Mas a manutenção não fica mais fácil quando você já sabe onde está sendo processada a lógica, ou onde estão os dados?

Eu estou bem confuso quanto a essas coisas, não tenho uma opinião formada, do tipo: modelo anêmico é melhor ou modelo rico é melhor.

Não vejo a diferença na vantagem de utilizar um ou outro, e é por isso mesmo que eu abri o tópico, para ver se esclareço a idéia sobre isso afim de criar uma opinião.

R

Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

N

rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

E as funcionalidades dessa entidade, aonde vão?

R

Voce fala funcionalidades para salvar e carregar os dados por exemplo?

Em um DAO

N

rogelgarcia:
Voce fala funcionalidades para salvar e carregar os dados por exemplo?

Em um DAO

Não, eu digo de funcionalidades de regra de negócio

P

@rogelgarcia

No caso do Endereço, vc tem um EndereçoBO que valida o CEP? Vc tem um EndereçoBO.getInstance() ? Se tem então não é tão simples assim.

@Frango

A manutenção fica mais facil se o que eu preciso saber esta diante de mim. Preciso abrir 2 (ou mais) arquivos para adicionar uma funcionalidade?

Veja este exemplo simples.

ValidadorPessoaFisica vp = ValidadorPessoaFisica.getInstance(); if(vp.validaPessoaFisica(aluno)){ // salva no banco } else { // mostra erro }

Imagine que agora PessoaFisica alem de sexo masculino e feminino tem “não informado” para ser mais politicamente correto. Alem de alterar a classe em si eu preciso alterar TODOS os pontos onde ela tem alguma Logica. Isso significa que eu preciso

  1. Acreditar na documentação
  2. Esperar que testes unitarios sejam uteis
  3. Procurar com o eclipse (ou outra IDE) todos os lugares onde usam um objeto PessoaFisica
  4. Rezar para não ter ninguem que use Reflection
  5. Descobrir que um relatorio semestral deu pau na cara do gerente senior

Se tudo fica contido em uma classe, tem testes, esta bem feito, minimamente documentado, eu minimizo as dores de cabeça.

E, se a logica pode estar em 1 classe separada, ela pode estar em mais de uma classe. Isso quando vc não tem 2 ou mais classes que representem a mesma coisa sob pontos de vista diferentes mas em pacotes diferentes.

Edit: recentemente descobri que tinha um filtro em uma serie de requests que atualizavam outros sistemas. E atualizavam em um momento inadequado. Precisei fazer magia negra com grep, sed e awk para encontrar todos os 4 pontos em 3 projetos diferentes que faziam isso. Se o modelo fosse forte, eu poderia altualizar estes outros sistemas com algo do tipo Observer.

V

rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Por outro lado, como ficaria o BO da classe endereço? Seria praticamente vazio, no máximo fazendo delegação para o VO (ou uma cópia do VO, dependendo da estratégia que você use). Qualquer um desses três casos (classe final vazia, delegação pura e simples ou cópia de classe) é um sintoma de má modelagem.

N

peczenyj:
@rogelgarcia
@Frango

A manutenção fica mais facil se o que eu preciso saber esta diante de mim. Preciso abrir 2 (ou mais) arquivos para adicionar uma funcionalidade?

Veja este exemplo simples.

ValidadorPessoaFisica vp = ValidadorPessoaFisica.getInstance(); if(vp.validaPessoaFisica(aluno)){ // salva no banco } else { // mostra erro }

Imagine que agora PessoaFisica alem de sexo masculino e feminino tem “não informado” para ser mais politicamente correto. Alem de alterar a classe em si eu preciso alterar TODOS os pontos onde ela tem alguma Logica. Isso significa que eu preciso

  1. Acreditar na documentação
  2. Esperar que testes unitarios sejam uteis
  3. Procurar com o eclipse (ou outra IDE) todos os lugares onde usam um objeto PessoaFisica
  4. Rezar para não ter ninguem que use Reflection
  5. Descobrir que um relatorio semestral deu pau na cara do gerente senior

Se tudo fica contido em uma classe, tem testes, esta bem feito, minimamente documentado, eu minimizo as dores de cabeça.

E, se a logica pode estar em 1 classe separada, ela pode estar em mais de uma classe. Isso quando vc não tem 2 ou mais classes que representem a mesma coisa sob pontos de vista diferentes mas em pacotes diferentes.

Edit: recentemente descobri que tinha um filtro em uma serie de requests que atualizavam outros sistemas. E atualizavam em um momento inadequado. Precisei fazer magia negra com grep, sed e awk para encontrar todos os 4 pontos em 3 projetos diferentes que faziam isso. Se o modelo fosse forte, eu poderia altualizar estes outros sistemas com algo do tipo Observer.

Seguindo o seu exemplo,
Se fosse no modelo anêmico seria algo do tipo:

PessoaFisicaBO bo = new PessoaFisicaBO();
if(bo.validaPessoaFisica(pessoa)) {
//salva
}
else {
//erro
}

No modelo rico, eu teria uma classe que faz a lógica de validar pessoa física?
Não seria a mesma coisa que ter uma classe BO?

R

ViniGodoy:
rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Por outro lado, como ficaria o BO da classe endereço? Seria praticamente vazio, no máximo fazendo delegação para o VO (ou uma cópia do VO, dependendo da estratégia que você use). Qualquer um desses três casos (classe final vazia, delegação pura e simples ou cópia de classe) é um sintoma de má modelagem.

VO seria o próprio Endereco
o BO teria métodos para manipulacao do Endereco, mas nao seria delegacao…

M

Não, vc não teria. A própia pessoa fisica faria isso.

R

A validacao eu nao costumo colocar nem no VO nem no BO… uso uma arquitetura separada de validacao… que valida os objetos onde seja necessário…

Mas o VO (Endereco) continua anemico nesse caso…

eu nao tenho um método

endereco.isValid()
R

Vamos pegar o PessoaFisica por exemplo… num modelo Rico… como ficariam as funcionalidades para salvar e carregar os dados?

A

rogelgarcia:
ViniGodoy:
rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Por outro lado, como ficaria o BO da classe endereço? Seria praticamente vazio, no máximo fazendo delegação para o VO (ou uma cópia do VO, dependendo da estratégia que você use). Qualquer um desses três casos (classe final vazia, delegação pura e simples ou cópia de classe) é um sintoma de má modelagem.

VO seria o próprio Endereco
o BO teria métodos para manipulacao do Endereco, mas nao seria delegacao…

Uma entidade deve conter apenas as coisas que a compoem… qualquer validação ou algo do genero deve ser feita em classe específica, pode ser uma BO. O design pattern BO acessa as daos ou outros metodos da BO ou ainda outra camada da aplicação que esteja em, digamos… “uma camada a frente”, porém jamais retornando… a ideia eh simples

View -> Controller -> Facade/BO -> BO -> DAO -> VO

qualquer coisa do genero

VO -> DAO
DAO -> BO
VO -> BO
Facade -> Controller
DAO -> Facade

não pode ocorrer

uma camada só pode chamar sua camada subsequente

P

onde fica a persistencia?

Depende do padrão que vc adotar. Vc pode usar activeRecord e o objeto sabe se salvar (e como recuperar) como é comum em Rails. Ou pode usar Repositorios (DDD). O lance é que persistência tem pouco haver com negocio e sim com uma particularidade do seu sistema: eu preciso usar um banco de dados ou outra coisa pois os objetos não podem ficar em memoria (que é um recurso finito) pra sempre.

@dohko

Um objeto não deveria ser capaz de criticar e validar o seu estado interno? Pq eu preciso de uma classe externa?

Não seria mais Simples ter Objetos que se relacionam como Objetos?

N

peczenyj:
onde fica a persistencia?

Depende do padrão que vc adotar. Vc pode usar activeRecord e o objeto sabe se salvar (e como recuperar) como é comum em Rails. Ou pode usar Repositorios (DDD). O lance é que persistência tem pouco haver com negocio e sim com uma particularidade do seu sistema: eu preciso usar um banco de dados ou outra coisa pois os objetos não podem ficar em memoria (que é um recurso finito) pra sempre.

@dohko Um objeto não deveria ser capaz de criticar e validar o seu estado interno? Pq eu preciso de uma classe externa?

Poderia explicar melhor aquele exemplo que você deu sobra validação de pessoa fisica?

Como seria no modelo anemico e rico e qual as vantagens?

A

peczenyj:
onde fica a persistencia?

Depende do padrão que vc adotar. Vc pode usar activeRecord e o objeto sabe se salvar (e como recuperar) como é comum em Rails. Ou pode usar Repositorios (DDD). O lance é que persistência tem pouco haver com negocio e sim com uma particularidade do seu sistema: eu preciso usar um banco de dados ou outra coisa pois os objetos não podem ficar em memoria (que é um recurso finito) pra sempre.

@dohko

Um objeto não deveria ser capaz de criticar e validar o seu estado interno? Pq eu preciso de uma classe externa?

Não seria mais Simples ter Objetos que se relacionam como Objetos?

No meu caso eu resolvo isso com uma classe que estende a entidade… pode ser PessoaFisicaEntity ou PessoaFisiscaVO extendendo PessoaFisica (classe que apenas contem o que a compoe)… Ai sim, nesta classe a um nivel abaixo teria esses métodos… O problema é que eu nao considero uma boa pratica, a nao ser que vc tenha controle e nao deixe que metodos bizarros comecem a aparecer na sua VO, como por exemplo um metodo que define que cor sera uma coluna na view… ex: getCorNome() { return “azul” }… e ai começa a coisa maluca… por isso eu preferiria usar classes que auxiliam na validacao

B

O modelo anêmico não é um fracasso. Aliás a maioria dos sistemas por aí continua sendo feitos desta forma, entram em produção, e milhões de pessoas os usam sem problemas.

Problema é que ele duplica muitas regras, validações, deixa a lógica mais longa, menos legível, e mais complicada de reusá-la.

N

Bruno Laturner:
O modelo anêmico não é um fracasso. Aliás a maioria dos sistemas por aí continua sendo feitos desta forma, entram em produção, e milhões de pessoas os usam sem problemas.

Problema é que ele duplica muitas regras, validações, deixa a lógica mais longa, menos legível, e mais complicada de reusá-la.

Eu não vejo ele duplicando regras, porque se eu tenho cada VO com seu respectivo BO. Quando eu quero usar a regra do “Carro” por exemplo, eu vou e chamo a CarroBO. Eu não vou reescrever a lógica sendo que ela já existe no BO.

F

Na minha opnião vocẽ pode usar o modelo anêmico o tanto que você quiser em qualquer linguagem, só não chame isso de OO.

P

Se as regras de negocio da entidade Carro ficam só na classe CarroBO, qual a justificativa para manter longe da classe Carro (eliminando a classe VO)?

N

No caso, eu acho mais organizado a entidade em uma classe, as regras de negócio em outra classe e o acesso ao banco em outra.
Mas não que isso seja o correto, eu estou falando o que eu acho mais organizado.

A diferença do rico para o anêmico não é somente colocar a regra de negócio no objeto ao invés de colocar em uma classe separada?

Mas qual vantagem eu vou ter nisso?

A

Realmente nao eh OO… chama aplicar design patterns

M

Pra aplicar um pattern vc precisa de uma motivação. Qual a sua motivação pra estar separando comportamento e dados?

Vc está numa aplicação distribuida usando ejb 2? Se não, eu não vejo motivo para isso.

Alias, qual a sua base de patterns? o livro do Fowler, o de Patterns J2EE da Sun, ou outro? pq pelo que eu estou notando, os seus VOs não são na verdade VOs, seriam apenas DTOs, me corrija se eu estiver engano por favor.

N

mario.fts:
Pra aplicar um pattern vc precisa de uma motivação. Qual a sua motivação pra estar separando comportamento e dados?

Vc está numa aplicação distribuida usando ejb 2? Se não, eu não vejo motivo para isso.

Alias, qual a sua base de patterns? o livro do Fowler, o de Patterns J2EE da Sun, ou outro? pq pelo que eu estou notando, os seus VOs não são na verdade VOs, seriam apenas DTOs, me corrija se eu estiver engano por favor.

Eu li essa mesma justificativa em outro lugar, qual a motivação de separar a entidade da regra? ainda mais se não está em uma aplicação distribuida.

Então seria apenas uma questão de preferência em separar a entidade da lógica. É por isso a pergunta do título do tópico: Modelo Anêmico é realmente ruim? Ele realmente influencia negativamente?

A

mario.fts:
Pra aplicar um pattern vc precisa de uma motivação. Qual a sua motivação pra estar separando comportamento e dados?

Vc está numa aplicação distribuida usando ejb 2? Se não, eu não vejo motivo para isso.

Alias, qual a sua base de patterns? o livro do Fowler, o de Patterns J2EE da Sun, ou outro? pq pelo que eu estou notando, os seus VOs não são na verdade VOs, seriam apenas DTOs, me corrija se eu estiver engano por favor.

A unica pessoa que diferencia VO de DTO é o Fowler. Infelizmente ainda nao tive a oportunidade de ler sua bibliografia, porém já está “escalonado” (rs). Me baseio em GOF e SUN.

[] ´s

A

Só de pensar métodos misturados em atributos que representam uma entidade do mundo real ou abstrata, já me da enjoo. Agora considere dao nesses métodos… Vou mais além… Injeção de dependência em cada método, ou você vai querer ter atributos com as DAOs…ou melhor ainda… vc irá instanciar a DAO em cada método desse???. agora imagine q vc ta usando o hibernate… todos eles com o modificador transiente!

M

Sim, agora estou entendendo melhor suas considerações. É bom conhecer a base de conhecimentos antes de fazer afirmações. :wink:

vc já leu este link? http://www.fragmental.com.br/wiki/index.php?title=Evitando_VOs_e_BOs

Os motivos que ele cita são muito bem explicados, acho que vale dar uma lida, resume bem as opiniões de quem defende que não se use modelos anêmicos.

P

Nossa… ninguem leu Domain Driven Design não?

Ou Naked Objects (:evil:)?

www.ime.usp.br/~jef/NOportugues.pdf

E os Fantoches ?

http://fragmental.com.br/wiki/index.php?title=Fantoches

Y

Enjoo por que? As coisas nao ficam mais organizadas juntas? Voce tem os atributos da sua classe e os metodos que interagem com eles, e somente esses metodos, no mesmo lugar.

Daos sim, prefiro que fiquem separados, mas as regras especificas do dominio devem ficar juntas.

Imagine a situacao classica do objeto ContaCorrente, com VO BO voce pode alterar o saldo atual dele de qualquer lugar, nada te garante que essa alteracao seja feita apenas pelo BO, ja que no VO voce tem todos os atributos expostos para que o BO possa usar.

Mas qual o sentido em se alterar o saldo de uma conta corrente a nao ser por uma transacao? Com um metodo que atualize o saldo, voce garante que nenhum outro metodo ira atualiza-lo sem que haja uma transacao, por exemplo, porque o atributo saldo nao sera exposto a ninguem pra fazer isso. Ele sera alterado apenas pela propria classe ContaCorrente e se voce preferir apenas por um e metodo dessa classe.

A

peczenyj:
Nossa… ninguem leu Domain Driven Design não?

Ou Naked Objects (:evil:)?

www.ime.usp.br/~jef/NOportugues.pdf

Confesso q nao li… acho que ando desatualizado :stuck_out_tongue:

A

Enjoo por que? As coisas nao ficam mais organizadas juntas? Voce tem os atributos da sua classe e os metodos que interagem com eles, e somente esses metodos, no mesmo lugar.

Daos sim, prefiro que fiquem separados, mas as regras especificas do dominio devem ficar juntas.

Imagine a situacao classica do objeto ContaCorrente, com VO BO voce pode alterar o saldo atual dele de qualquer lugar, nada te garante que essa alteracao seja feita apenas pelo BO, ja que no VO voce tem todos os atributos expostos para que o BO possa usar.

Mas qual o sentido em se alterar o saldo de uma conta corrente a nao ser por uma transacao? Com um metodo que atualize o saldo, voce garante que nenhum outro metodo ira atualiza-lo sem que haja uma transacao, por exemplo, porque o atributo saldo nao sera exposto a ninguem pra fazer isso. Ele sera alterado apenas pela propria classe ContaCorrente e se voce preferir apenas por um e metodo dessa classe.

Considerando que o objeto só depende dele mesmo para fazer isso, acredito que sim!

N

No modelo rico eu posso chamar um método de persistência (DAO) de dentro de um método de lógica (BO) ?

P

Humm… isto pode te dar uma luz

http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto/

Y

dohko:

Considerando que o objeto só depende dele mesmo para fazer isso, acredito que sim!

Mas se nao depende somente dele há algo errado na modelagem das classes. Um modelo rico não é simplesmento um modelo nao VO/BO, ele vai muito alem.

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.)

Responsabilidade dos objetos é um tema muito complexo e geralmente negligenciado por quem estuda OO. É o principio mais importante e é o que normalmente faz a diferença no código, mas é um conceito com um nominho da simples.

P

Sem falar em Aspectos. A discussão não tem fim, porém qualquer forma de programar mais OO e menos Procedural é interessante pois da base para as proximas ações.

B

Sim, continua a mesma coisa que no modelo anêmico. A regra de negócios sabe chamar a persistência, e a persistência sabe como extrair os dados deste objeto para gravar em algum lugar.

Na verdade mais se resume a falar “Me persista”, e um gerenciador se vira para fazer isto.

A

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!

B

É muito conveniente criar domains enxutos, que simplesmente transitam entre o banco e a tela. Isso porque ORMs como o hibernate recomendam DAO, e nada mais natural do que o DAO implementar os comportamentos que eram pra estar nesses objetos, consequentemente sem inteligencia imbutida.

O que é feio mesmo é criar várias camadas de beans burrões com esses.

Pra quem acha que isso é totalmente errado, só olhar os exemplos do Hibernate pra discutir lá com o Gavin King :twisted:

R

Basicamente, seguimos 3 regras (definidas no GOF) para boas práticas de OO:

1 - Favorecer composição ao invés de herança
2 - Programar para interfaces e não para implementações
3 - Alta coesão e baixo acoplamento

Num modelo rico, onde o objeto sabe como se salva e como se carrega, você terá código de persistencia dentro dele (o active record do rails eu considero mais válido pois, voce nao codifica isso na classe, o framework é que implementa pra voce)
Se voce tem que validar o objeto, provavelmente vc fará algo do tipo ValidatorUtils.validateEmail(pessoa.getEmail())

Isso vai ferir o item 3 das boas práticas de programação. Muitas lógicas misturadas na mesma classe, causando baixa coesão.

Se voce pensar na interface de PessoaFisica, o que é uma pessoa física? O que ela tem? O que ela pode fazer? Faz parte da pessoa física se salvar? Você se salva? Se carrega?
Se voce faz um programa chamando pessoaFisica.save(), voce começa a programar para a implementação, pois a interface que define uma pessoa física, não tem isso de salvar…

Ferindo o principio 2.

É mais ou menos como se um bolo fosse representado pela classe Bolo e nessa classe tivesse um método chamado assar. Quando voce compra um bolo, tem um botão que ele se assa sozinho? Não, voce precisa de um forno…

P

Só o fato de diminuirmos o Ruído Semântico da camada de negócios com um modelo mais rico dá frutos sensacionais.

R

Mas eu acho válido por exemplo um método getIdade() na pessoa física…

N

peczenyj:
Humm… isto pode te dar uma luz

http://blog.caelum.com.br/2007/06/09/repository-seu-modelo-mais-orientado-a-objeto/

Valeu pelo link.

Eu ainda sou meio leigo nesse conceito de repositórios.

Utilizo somente DAOs.

Para programar OO eu necessariamente preciso utilizar repositórios?

Tem algum link legal sobre repositórios?

Valeu

M

http://blog.fragmental.com.br/2007/03/01/voce-pergunta-001-daos-e-repositorios/
http://blog.fragmental.com.br/2008/05/22/domain-driven-design-e-simples/
http://blog.fragmental.com.br/2010/01/18/domain-driven-bolovo-passando-conhecimento-e-etc/
http://www.guj.com.br/posts/list/134767.java

faz uma busca por repositórios aqui no guj, vão vir milhões de links. kkkkk

S

Frango:

Então seria apenas uma questão de preferência em separar a entidade da lógica. É por isso a pergunta do título do tópico: Modelo Anêmico é realmente ruim? Ele realmente influencia negativamente?

Sim. Leia a matéria da javamagazine deste mes sobre coesão e acoplamento. O problema do modelo anémico é falta de coesão e excesso de acoplamento.

Não se trata de colocar todas as funções numa classe só, trata-se de separar corretamente o que é de cada classe. Isso é SoC, e quando mal feito leva a problemas de coesão e acoplamento

B

Repositório é somente uma abstração de onde guardar e obter objetos, normalmente os DAOs são as classes concretas que implementam os repositórios.

Mas se for começar a pesquisar sobre isto, leia primeiro o livro do Eric Evans, Domain Driven Design. Ele que dá a base de tudo.

R

sergiotaborda:

Sim. Leia a matéria da javamagazine deste mes sobre coesão e acoplamento. O problema do modelo anémico é falta de coesão e excesso de acoplamento.

Não se trata de colocar todas as funções numa classe só, trata-se de separar corretamente o que é de cada classe. Isso é SoC, e quando mal feito leva a problemas de coesão e acoplamento

Eu já acho o contrario… como postei anteriormente…

Mas vou dar uma lida nessa revista… qual é o número?

M

rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Essa não é a definição de modelo anêmico. Modelo anemico é quando, havendo algum comportamento, ele é colocado em um objeto diferente daquele que possui os dados. O que vai contra aos principios da OO que é agrupar os dois no mesmo objeto.

S

rogelgarcia:
sergiotaborda:

Sim. Leia a matéria da javamagazine deste mes sobre coesão e acoplamento. O problema do modelo anémico é falta de coesão e excesso de acoplamento.

Não se trata de colocar todas as funções numa classe só, trata-se de separar corretamente o que é de cada classe. Isso é SoC, e quando mal feito leva a problemas de coesão e acoplamento

Eu já acho o contrario… como postei anteriormente…

Mas vou dar uma lida nessa revista… qual é o número?

Se não me engano é a 77.

Existe uma diferença entre o método getIdade(Date) em pessoa e o método save() em pessoa. ActiveRecord é anémico.
É da responsabilidade da pessoa saber a sua idade, mas não é responsabilidade da pessoa ter codigo de “save” que é um conceito de TI que nada tem que ver com pessoas.

Eu comentei sobre modelo anêmico faz algum tempo no meu blog antigo.

A

mochuara:
rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Essa não é a definição de modelo anêmico. Modelo anemico é quando, havendo algum comportamento, ele é colocado em um objeto diferente daquele que possui os dados. O que vai contra aos principios da OO que é agrupar os dois no mesmo objeto.


Faço das suas as minhas palavras.
Aliás, acho que colocar o validaCep() em uma outra classe é errado… Não errado, mas eu não gostaria de fazer dessa maneira. É a mesma coisa que colocar calcularIdade() de um objeto do tipo Pessoa dentro de uma outra classe… Vira aquela coisa de gets e sets pra tudo quanto é lado (lembrem-se dos artigos de que getters e setters ‘are evil’). Mas isso é só a opinião de um gordo que nem sabe digitar direito né :stuck_out_tongue:

Ah, lembrei de uma coisa. Eu estava lendo um artigo sobre um framework que tinha saído na época (final de 2008, começo de 2009, alguma coisa assim). Lá, até mesmo os CRUDs estavam sendo codificados em classes Pessoas, Clientes e afins. O que vocês acham disso? Acaba com toda aquela coisa de DAO e Repository, o que as vezes não é legal.

R

mochuara:
rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Essa não é a definição de modelo anêmico. Modelo anemico é quando, havendo algum comportamento, ele é colocado em um objeto diferente daquele que possui os dados. O que vai contra aos principios da OO que é agrupar os dois no mesmo objeto.

Eu considerei que havia o comportamento de salvar por exemplo … que nao deve ser colocado na classe

M

rogelgarcia:
mochuara:
rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Essa não é a definição de modelo anêmico. Modelo anemico é quando, havendo algum comportamento, ele é colocado em um objeto diferente daquele que possui os dados. O que vai contra aos principios da OO que é agrupar os dois no mesmo objeto.

Eu considerei que havia o comportamento de salvar por exemplo … que nao deve ser colocado na classe

Continua não tendo nada a ver com modelo anêmico. O modelo é anêmico quando, deliberadamente ou por força de uma arquitetura pré-definida, se resolve separar aquilo que outrora deveria estar agrupado em unico objeto.

N

sergiotaborda:
Frango:

Então seria apenas uma questão de preferência em separar a entidade da lógica. É por isso a pergunta do título do tópico: Modelo Anêmico é realmente ruim? Ele realmente influencia negativamente?

Sim. Leia a matéria da javamagazine deste mes sobre coesão e acoplamento. O problema do modelo anémico é falta de coesão e excesso de acoplamento.

Não se trata de colocar todas as funções numa classe só, trata-se de separar corretamente o que é de cada classe. Isso é SoC, e quando mal feito leva a problemas de coesão e acoplamento

Confesso que desde o começo da Thread esperava uma resposta sua. hahaha

Li o seu post e estou começando a entender melhor e a acreditar que o modelo rico é melhor por diminuir o acoplamento e aumentar a coesão.

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?

abraços

R

Acho que tá havendo um mal entendido aqui…

No post do sergiotaborda é dito que os objetos fantoche… como a classe Endereco que citei… sao apenas isso fantoche… e que isso é o correto… porque a responsabilidade delas é apenas ser um conjunto de dados

Aí os defensores do modelo rico… dizem que as classes nao podem ser só fantoches… que devemos evitar o modelo anemico…

E o sergiotaborda como outros são contra o modelo anemico…

O que voces chamam de modelo anemico???

R

mochuara:
rogelgarcia:
mochuara:
rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Essa não é a definição de modelo anêmico. Modelo anemico é quando, havendo algum comportamento, ele é colocado em um objeto diferente daquele que possui os dados. O que vai contra aos principios da OO que é agrupar os dois no mesmo objeto.

Eu considerei que havia o comportamento de salvar por exemplo … que nao deve ser colocado na classe

Continua não tendo nada a ver com modelo anêmico. O modelo é anêmico quando, deliberadamente ou por força de uma arquitetura pré-definida, se resolve separar aquilo que outrora deveria estar agrupado em unico objeto.

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

N

rogelgarcia:
Acho que tá havendo um mal entendido aqui…

No post do sergiotaborda é dito que os objetos fantoche… como a classe Endereco que citei… sao apenas isso fantoche… e que isso é o correto… porque a responsabilidade delas é apenas ser repositorio de dados

Aí os defensores do modelo rico… dizem que as classes nao podem ser só fantoches… que devemos evitar o modelo anemico…

E o sergiotaborda como outros são contra o modelo anemico…

O que voces chamam de modelo anemico???

Acho que você não entendeu direito.

O modelo anêmico é quando você separa a lógica e as propriedades de uma entidade em classes diferentes.
Porque? Porque o conceito de objeto é propriedades + funcionalidades, sendo assim separar isso em duas classes vai contra o conceito de orientação a objeto.

O que o sergio defende é de que se o objeto não tem nenhuma funcionalidade (regra de negócio), você não precisa inserir alguma só para dizer que tem.

E se um objeto só tem o proposito de armazenar dados que assim seja, isso não torna o modelo anêmico.

Entendeu?

M

O que é VO?

R

Sim… entendi isso… e é o que eu defendo tb…

Só que o que eu tinha como conceito de modelo anemico… é objetos com apenas getters e setters…
Os objetos com getters e setters… são os objetos que o sergio defente…

R

VO Value Object… é a entidade por exemplo… a classe Endereco

M

Frango:

O que o sergio defende é de que se o objeto não tem nenhuma funcionalidade (regra de negócio), você não precisa inserir alguma só para dizer que tem.

E se um objeto só tem o proposito de armazenar dados que assim seja, isso não torna o modelo anêmico.

Entendeu?

Independente de ser modelo anemico ou nao, se um objeto não tem funcionalidade (ou seja, não troca mensagens com outros objetos), qual motivo da sua existencia? Pra mim isso não é um bom sinal de design OO.

R

mochuara:
Frango:

O que o sergio defende é de que se o objeto não tem nenhuma funcionalidade (regra de negócio), você não precisa inserir alguma só para dizer que tem.

E se um objeto só tem o proposito de armazenar dados que assim seja, isso não torna o modelo anêmico.

Entendeu?

Independente de ser modelo anemico ou nao, se um objeto não tem funcionalidade (ou seja, não troca mensagens com outros objetos), qual motivo da sua existencia? Pra mim isso não é um bom sinal de design OO.

Ele existe para guardar dados…
na classe Endereco… rua cep bairro … etc

R

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…

Temos então duas definições…

Anemic Model, é uma classe que deveria possuir funcionalidades (como getIdade() em PessoaFisica) mas essas funcionalidades estão em outra classe… OK Concordo que nesse caso o Anemic Model é ruim…

Tem gente que defende que o método salvar deve ficar no Modelo, alegando que é Anemic Model se o salvar ficar em outra classe… Não concordo… e por isso disse que anemic model não é ruim…

Então, uma classe com apenas getters e setters, é anemic model? Como por exemplo a classe Endereco, que nao tem que fazer mais nada, a não ser guardar as informacoes do endereço…

E os que defendem que o método salvar deve estar no modelo? Chamam modelos sem esse método de anemic model?

R

Considerando que há essa divergência entre os Anemic Models… eu acho que existem “níveis de anemia” e o que cada um considera anêmico varia nesses niveis…

(vou simplificar o código para ficar mais fácil entender… nao vou colocar os getters e setters tb nao)

Anemia 0 - Absolutamente nenhuma funcionalidade no Modelo…

class PessoaFisica {
      String nome;
      Date dataNascimento;
}

class PessoaFisicaBO {
      int getIdade(Pessoa p){...}
      boolean declarouIR(Pessoa p){
              ...
             // web service para acessar o site da receita federal
      }

}

class PessoaFisicaDAO {
    void save(PessoaFisica p){...}
}

class PessoaFisicaAction {
     void processCrud(request) {...}
}

Anemia 1 - Funcionalidades apenas pertinentes ao modelo (onde o modelo resolve por si só o problema)

class PessoaFisica {
      String nome;
      Date dataNascimento;
      int getIdade(){...} // MÉTODO NO MODELO
}

class PessoaFisicaBO {
      
      boolean declarouIR(Pessoa p){
              ...
             // web service para acessar o site da receita federal
      }
}

class PessoaFisicaDAO {
    void save(PessoaFisica p){...}
}

class PessoaFisicaAction {
     void processCrud(request) {...}
}

Anemia 2 - Funcionalidades apenas pertinentes ao modelo independente se precisa de outras informacoes, ou objetos…

class PessoaFisica {
      String nome;
      Date dataNascimento;
      int getIdade(){...}
      boolean declarouIR(){ // MÉTODO NO MODELO
              ...
             // web service para acessar o site da receita federal
      }
}

class PessoaFisicaBO {
      

}

class PessoaFisicaDAO {
    void save(PessoaFisica p){...}
}

class PessoaFisicaAction {
     void processCrud(request) {...}
}

Anemia 3 - Funcionalidades pertinentes ao modelo mas independente de sua responsabilidade

class PessoaFisica {
      String nome;
      Date dataNascimento;
      int getIdade(){...}
      boolean declarouIR(){
              ...
             // web service para acessar o site da receita federal
      }
      void save(){...}// MÉTODO NO MODELO
}

class PessoaFisicaBO {
      

}

class PessoaFisicaDAO {
    
}

class PessoaFisicaAction {
     void processCrud(request) {...}
}

Anemia 4 - Funcionalidades pertinentes ao modelo mas independente de sua responsabilidade (nível extremo, igual ao do framework do carinha)

class PessoaFisica {
      String nome;
      Date dataNascimento;
      int getIdade(){...}
      boolean declarouIR(){
              ...
             // web service para acessar o site da receita federal
      }
      void save(){...}
      void processCrud(request) {...}// MÉTODO NO MODELO
}

class PessoaFisicaBO {
      

}

class PessoaFisicaDAO {
    
}

class PessoaFisicaAction {
     
}

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…

A

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…

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? Pq tipo assim… eu tenho um projeto que estou desenvolvendo a algum tempo onde eu separei o dominio em um jar separado… esse jar pertence exclusivamente a minha empresa… nela eu tenho os mais variados tipos de classes, desde pessoa até coisas especificas de outros projetos… o que as diferencia é apenas o pacote… por exemplo… tenho com.teste.domain.Pessoa -> com.teste.model.PessoaFisica -> com.teste.cliente1.model.Cliente… como seria isso no modelo rico??

Outra coisa… se eu quiser mudar a camada de persistencia no modelo ‘rico’, simplesmente alterando o jar app_hibernate para app_jdbc da minha aplicação é possível???

Outra… se eu quiser re-utilizar meu jar de domain e meu jar de persistence ou model em outra aplicação é possível???

F

@dohko

Sinceramente, eu não tenho o sonho de reaproveitar componentes de domínio. Ai você pensa: “mas o dominio do aplicativo A se parece com o do aplicativo B”, talvez seja o caso de refatorar ambos aplicativos para A, B e C, com C contendo as partes comuns. Você pode até generalizar/abstrair os modelos do domínio, o resultado vai ser ou alguma coisa pouco útil ou um trambolho complexo com interfaces gigantes e não relacionadas ao dominio. Em todo caso vale a pena testar, a minha experiência diz que fazer isso não é bom, é mais prático reescrever.

Adicionando: dá uma olhada nesse link http://en.wikipedia.org/wiki/Subject-oriented_programming

Pergunta: com.teste.domain.Pessoa -> com.teste.model.PessoaFisica -> com.teste.cliente1.model.Cliente o que é isso? Herança? Esses “teste” no nome da classe são testes (ex. unitário) ou é só um exemplo de nome?

Como seria no modelo rico?
O que eu falei até aqui não diz respeito a modelo rico ou modelo anêmico, tanto faz.

Outra coisa… se eu quiser mudar a camada de persistencia no modelo ‘rico’, simplesmente alterando o jar app_hibernate para app_jdbc da minha aplicação é possível???

Sim, tanto no modelo rico quanto no modelo anêmico é possível utilizar abstrações e “camuflar” o que tem por baixo.

Pelo visto você anda tendo um bom reaproveitamento com os modelos anêmicos / semi-anêmicos / não anêmicos (ou outro). No que de fato consiste esse reaproveitamento? Importar um jar , subir um schema (de banco) e realizar uma série de testes automáticos?

M

rogelgarcia:
Considerando que há essa divergência entre os Anemic Models… eu acho que existem “níveis de anemia” e o que cada um considera anêmico varia nesses niveis…

(vou simplificar o código para ficar mais fácil entender… nao vou colocar os getters e setters tb nao)

Anemia 0 - Absolutamente nenhuma funcionalidade no Modelo…

class PessoaFisica {
      String nome;
      Date dataNascimento;
}

class PessoaFisicaBO {
      int getIdade(Pessoa p){...}
      boolean declarouIR(Pessoa p){
              ...
             // web service para acessar o site da receita federal
      }

}

class PessoaFisicaDAO {
    void save(PessoaFisica p){...}
}

class PessoaFisicaAction {
     void processCrud(request) {...}
}

Anemia 1 - Funcionalidades apenas pertinentes ao modelo (onde o modelo resolve por si só o problema)

class PessoaFisica {
      String nome;
      Date dataNascimento;
      int getIdade(){...} // MÉTODO NO MODELO
}

class PessoaFisicaBO {
      
      boolean declarouIR(Pessoa p){
              ...
             // web service para acessar o site da receita federal
      }
}

class PessoaFisicaDAO {
    void save(PessoaFisica p){...}
}

class PessoaFisicaAction {
     void processCrud(request) {...}
}

Anemia 2 - Funcionalidades apenas pertinentes ao modelo independente se precisa de outras informacoes, ou objetos…

class PessoaFisica {
      String nome;
      Date dataNascimento;
      int getIdade(){...}
      boolean declarouIR(){ // MÉTODO NO MODELO
              ...
             // web service para acessar o site da receita federal
      }
}

class PessoaFisicaBO {
      

}

class PessoaFisicaDAO {
    void save(PessoaFisica p){...}
}

class PessoaFisicaAction {
     void processCrud(request) {...}
}

Anemia 3 - Funcionalidades pertinentes ao modelo mas independente de sua responsabilidade

class PessoaFisica {
      String nome;
      Date dataNascimento;
      int getIdade(){...}
      boolean declarouIR(){
              ...
             // web service para acessar o site da receita federal
      }
      void save(){...}// MÉTODO NO MODELO
}

class PessoaFisicaBO {
      

}

class PessoaFisicaDAO {
    
}

class PessoaFisicaAction {
     void processCrud(request) {...}
}

Anemia 4 - Funcionalidades pertinentes ao modelo mas independente de sua responsabilidade (nível extremo, igual ao do framework do carinha)

class PessoaFisica {
      String nome;
      Date dataNascimento;
      int getIdade(){...}
      boolean declarouIR(){
              ...
             // web service para acessar o site da receita federal
      }
      void save(){...}
      void processCrud(request) {...}// MÉTODO NO MODELO
}

class PessoaFisicaBO {
      

}

class PessoaFisicaDAO {
    
}

class PessoaFisicaAction {
     
}

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…

É por causa desse tipo de discussão inutil que estou de saco cheio de desenvolver em Java. Esse tipo de coisa simplesmente não existe em outras linguagens, e por isso elas são geralmente chamadas de mais produtivas.

R

É… dá pra ver que vc tá nervoso mesmo… heheheheh

Mas essa discussão é independente da linguagem…

M

rogelgarcia:
É… dá pra ver que vc tá nervoso mesmo… heheheheh

Que nada, esse lance de anemia 0, anemia 1, anemia 2, foi até engraçado! :lol:

R

Eu ia colocar um com vitamina B12 pra ver se melhorava… ehhehe

M

http://guj.com.br/posts/list/30/203206.java#1029177

F

rogelgarcia:
Considerando que há essa divergência entre os Anemic Models… eu acho que existem “níveis de anemia” e o que cada um considera anêmico varia nesses niveis…

(vou simplificar o código para ficar mais fácil entender… nao vou colocar os getters e setters tb nao)

Rogel, concordo com vc em partes, mas pra mim se a classe é somente uma estrutura de campos, ela deve ser imutavel, ou seja, vc não altera o estado dela, TODOS os campos vem no construtor, e vc possui somente getters para recuperar o valor.

A

faq:
@dohko

Adicionando: dá uma olhada nesse link http://en.wikipedia.org/wiki/Subject-oriented_programming

Pergunta: com.teste.domain.Pessoa -> com.teste.model.PessoaFisica -> com.teste.cliente1.model.Cliente o que é isso? Herança? Esses “teste” no nome da classe são testes (ex. unitário) ou é só um exemplo de nome?

so o nome, com.minhaemprsa.domain.Pessoa -> com.minhaempresa.model.PessoaFisica -> com.minhaempresa.meucliente.model.Cliente

Na verdade a questão não é só reaproveitar, alem de manter um certo padrao em todas as bases, estou tentando criar uma dependencia do modelo do cliente com o meu


Pelo visto você anda tendo um bom reaproveitamento com os modelos anêmicos / semi-anêmicos / não anêmicos (ou outro). No que de fato consiste esse reaproveitamento? Importar um jar , subir um schema (de banco) e realizar uma série de testes automáticos?

Um exemplo seria se eu quisesse usar o meu model, domain e persistence em uma aplicacao desktop… seria apenas importar os jars

N

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?

Alguém pode exemplificar como fica a persistência em um modelo rico?

A

rogelgarcia:
(definidas no GOF) para boas práticas de OO:

2 - Programar para interfaces e não para implementações

Se voce pensar na interface de PessoaFisica, o que é uma pessoa física? O que ela tem? O que ela pode fazer? Faz parte da pessoa física se salvar? Você se salva? Se carrega?

Se voce faz um programa chamando pessoaFisica.save(), voce começa a programar para a implementação, pois a interface que define uma pessoa física, não tem isso de salvar…

E mais… na verdade não é só o GOF quem diz isso… basta pensar no principio da abstração…

em um artigo que estou trabalhando, fiz a seguinte citação:

S

Andre Brito:
mochuara:
rogelgarcia:
Para mim, o modelo anemico é completamente válido…

Exemplo, suponhamos uma classe Endereco.

Nessa classe temos os atributos, rua, cep, bairro, etc.

A classe Endereco nada mais é do que um tipo de dados complexo. Ou seja, não tem que fazer nada mesmo, a nao ser, guardar as informacoes.

Essa não é a definição de modelo anêmico. Modelo anemico é quando, havendo algum comportamento, ele é colocado em um objeto diferente daquele que possui os dados. O que vai contra aos principios da OO que é agrupar os dois no mesmo objeto.


Faço das suas as minhas palavras.
Aliás, acho que colocar o validaCep() em uma outra classe é errado… Não errado, mas eu não gostaria de fazer dessa maneira. É a mesma coisa que colocar calcularIdade() de um objeto do tipo Pessoa dentro de uma outra classe… Vira aquela coisa de gets e sets pra tudo quanto é lado (lembrem-se dos artigos de que getters e setters ‘are evil’).

getters and setter are not evil, people just dont’t understand them…

S

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).

A

sergiotaborda:
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?

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).

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?

S

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…

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

S

dohko:
sergiotaborda:
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?

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).

Sergio, vc injetaria a DAO na classe do dominio?

não.


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

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

  }

}
S

dohko:
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…

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?

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)

A

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

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

A
sergiotaborda:
dohko:
sergiotaborda:
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?

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).

Sergio, vc injetaria a DAO na classe do dominio?

não.

Pq se vc fizer atraves do construtor devera colocar sua referencia em algum atributo...nao?? Ou vc passa metodo a metodo?

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

  }

}

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

G

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

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.

R

Tem gente que usa o VO como entidade…

Eu quis dizer foi entity mesmo…

G

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

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

R

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…

G

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…

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.

Y

dohko:
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.)

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!

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.

R

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.

Beleza cara… voce venceu…

S

g4j:
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…

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.

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.

G

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.

N

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?

M

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.

M

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

N

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?

P

Acho que existe muita confusão sobre persistência de objetos.

Na boa, salvem no banco na melhor hora possivel, no lugar aonde fizer mais sentido.

Por exemplo, salvar muitas vezes envolve transações (com direito a rollback, commit, etc). As regras de negocio estão atreladas à persistencia? Acho que deve ser visto cada caso com critica, nem sempre precisamos (ou podemos) ser 100% OO.

N

peczenyj:
Acho que existe muita confusão sobre persistência de objetos.

Na boa, salvem no banco na melhor hora possivel, no lugar aonde fizer mais sentido.

Por exemplo, salvar muitas vezes envolve transações (com direito a rollback, commit, etc). As regras de negocio estão atreladas à persistencia? Acho que deve ser visto cada caso com critica, nem sempre precisamos (ou podemos) ser 100% OO.

Mas seguindo este modelo OO, como seria a melhor solução para isso?

Eu entendi os outros conceitos, mas ainda me sinto perdido com relação a persistência.

A

O modelo rico me parece muito “bonito de se ver”, mas dificil de se implementar… É como o comunismo… belo de se ler mas dificil de ver funcionar

M

Bom, eu vou falar como EU costumo fazer. não sei se é o certo, e nem sei se exite um certo e um errado nessa história.

Eu teria meu dominio da seguinte maneira mais ou menos. não exatamente com esses nomes, vou usar eles apenas para deixar o conceito mais claro

Conta
Transferencia
ContaRepositório
TransferenciaRepositorio

Vc reparou que os repositório fazem parte do dominio? como assim? eles não são parte da camada de persistencia?

Não. Eles também fazem parte do dominio. e objetos de dominio podem conversar entre si livremente para implementar regras de negócio.

a classe transferencia poderia receber uma referencia ao repositório de contas, e ao final da operação, inserir estas contas no repositório para que sejam persistidas.

algo como

public class Transferencia{

ContrasRepositoriio contasRepo;

//A transferencia tem uma dependencia do repositório de contas, 
// aqui vc usar seu motor de injeção de dependencias favorito, guice, pico, spring, sei 
public Transferencia(ContasRepositorio repo){
this.contasRepo = repo;
}

//Este método deve ser transacionado,
public transferirDinheiro(Conta aCreditar, Conta aDebitar, BigDecimal valor){
aDebitar.saque(valor);
aCreditar.depoisto(valor);

//E agora? agora vamos persistir as duas contas para "efetivar" a transferência.
this.contasRepo.save(aCreditar);
this.contasRepo.save(aDebitar);
}

}

Este código no mundo real naõ faria apenas essas operações, a transferencia teria atributos para guardar quais as contas, qual o valor, horario e etc.
A ta, entendi. mas e a transferencia? Vc não precisaria persistir ela pra que ela possa aparecer no extrato, por exemplo?

Sim, mas persistir a transferencia é de obrigação de quem a criou. lá após a chamada a transferir(), a transferencia será persistida.

Agora quem cria a transferencia? sei lá. Pode ser uma fachada ou um ServicoFinanceiro, que disponibiliza todas as operações como saque, deposito, transferencia, desde que garantam a atomicidade da operação.

N

Entendi.

O repositório seria uma abstração do DAO, certo?

Então no caso ali eu poderia ter um ContaDAO ao invés de ContaRepositório?

Valeu pela explicação

M

Acho que é um problema mais de adaptar-se que de dificuldade de implementação. O que foi discutido até agora, pra mim, é claro como a agua, porque eu aprendi assim, e tenho enormes dificuldades e acho inumeros problemas usando modelos BOLOVO. É a situação inversa da sua. Acho que é mais constume mesmo.

Só lembrando, mais um link interessante sobre o assunto. um ebook com o basico do basico sobre DDD

http://www.infoq.com/minibooks/domain-driven-design-quickly

M

Frango:
Entendi.

O repositório seria uma abstração do DAO, certo?

Então no caso ali eu poderia ter um ContaDAO ao invés de ContaRepositório?

Valeu pela explicação

Então, sim. É que eu considero repositórios e daos coisas distintas.

no meu dao, eu teria métodos como save, listById, ListForCriteria e coisas assim, 100% voltados a persistencia.

no repositório, eu teria uma instancia do dao dentro dele, criaria as queries necessárias pro meu dominio e delegaria para o dao a execução no banco. apesar de aumentar o acoplamento no caso, eu criaria as critérias/hqls dentro do repositorio e só usava o dao pra executar no banco. Se vc tiver usando Spring com HibernateTemplate, nem de dao vc precisaria, já delegava do repositório direto pro HibernateTemplate. Lógico que aumenta o acoplamento com o spring, mas eu gosto de fazer assim. se for com JPA, delegava pro entitymanager e já era.

N

mario.fts:
Frango:
Entendi.

O repositório seria uma abstração do DAO, certo?

Então no caso ali eu poderia ter um ContaDAO ao invés de ContaRepositório?

Valeu pela explicação

Então, sim. É que eu considero repositórios e daos coisas distintas.

no meu dao, eu teria métodos como save, listById, ListForCriteria e coisas assim, 100% voltados a persistencia.

no repositório, eu teria uma instancia do dao dentro dele, criaria as queries necessárias pro meu dominio e delegaria para o dao a execução no banco. apesar de aumentar o acoplamento no caso, eu criaria as critérias/hqls dentro do repositorio e só usava o dao pra executar no banco. Se vc tiver usando Spring com HibernateTemplate, nem de dao vc precisaria, já delegava do repositório direto pro HibernateTemplate. Lógico que aumenta o acoplamento com o spring, mas eu gosto de fazer assim. se for com JPA, delegava pro entitymanager e já era.

Mesmo assim eu não entendi o porque de usar o Repositório a usar diretamente o DAO…

P

http://gc.blog.br/2009/01/17/sindrome-de-dao/

Acho que esta é a diferença.

S

mario.fts:
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?

Este é exemplo tipico de um sistema acoplado pouco coeso. Na realidade vc não saca nem deposita dinheiro da conta. Vc executa um movimento na conta. Vc tem uma entidade MovimentoConta que tem informação de onde, quando,quanto e porquê o saldo está sendo alterado. O saldo é a soma de todos os movimentos. A conta não tem uma propriedade saldo. ela tem um calculo de saldo.

Exactamente ao contrário. Vc deveria sim ter um objeto Transferencia e um ServiçoDeTrasnferencia
A trasnferencia é um conjunto de MovimentosConta não necessáriamente 2.

Quando faz um DOC e paga uma taxa existem dois movimentos na sua conta, o do dinherio transferido e o da taxa.

num modelo de banco real, vc precisa dessas entidade todas e faria lago como

public class TransferenciaService{

public transferencia (Conta aDebitar, Conta aCreditar, double valor){

      MovimentoConta debita = new MovimentoConta (aDebitar, valor, Movimento.DEBITA);
      MovimentoConta debitaTaxa = new MovimentoConta (aDebitar, taxa, Movimento.DEBITA);
      MovimentoConta credita = new MovimentoConta (aCreditar, valor, Movimento.CREDITA);

      Transferencia trans = new Transferencia(aDebitar,aCreditar, agora());

     trans.add(credita);
     trans.add(debita );
     trans.add(debitaTaxa );

     // persiste tudo 

     daoTrasnferencia.salva(transf);
     daoMov.salva(credita);
     daoMov.salva(debita );
     daoMov.salva(debitaTaxa );

}
}

Vc precisa dos dois. A Transferencia é o “o quê” o Serviço é o decisor de “como”
Eliminar o serviço em detrimento de um objeto de entidade com a capacidade de executar regras de negocio é errado. Não é boa separação de responsabilidade.

Um método importante de trasfeerencia que pertence realmente na trasnferencia é reverse(). Este método cria e devolde uma transferencia ao contrário que estorna a transferencia inicial. O mesmo para o movimentoConta. Este tipo de método é que não pode ser colocar em outro objeto.

B

:shock:

public transferir (Conta de, Conta para, double valor){ new Transferencia(valor).debitar(de).creditar(para); transferenciaDao.salva(transferencia); }

M

sergiotaborda:
mario.fts:
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?

Este é exemplo tipico de um sistema acoplado pouco coeso. Na realidade vc não saca nem deposita dinheiro da conta. Vc executa um movimento na conta. Vc tem uma entidade MovimentoConta que tem informação de onde, quando,quanto e porquê o saldo está sendo alterado. O saldo é a soma de todos os movimentos. A conta não tem uma propriedade saldo. ela tem um calculo de saldo.

Concordo com suas observações, na minha modelagem não daria pra imprimir um extrato por exemplo, devido a essa falta da entidade movimento.

Mas eu sei disso. Eu criei o modelo assim pq não era meu foco explicar como funciona o modelo financeiro, e sim se ele deveria criar um serviço, e onde entra a persistencia nisso tudo. Tudo muito ludico, mas a intenção foi essa mesmo. Mas acho que foi o suficiente pro entendimento do problema proposto.

Um ponto interessante é a sua observação que ele deveria criar um serviçotransferencia e um objeto transferencia. Não tinha pensado assim diretamente, mas cheguei a citar isso no meu texto, na parte que falo do facade e do servicoFinanceiro.

S

mario.fts:
sergiotaborda:
mario.fts:
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?

Este é exemplo tipico de um sistema acoplado pouco coeso. Na realidade vc não saca nem deposita dinheiro da conta. Vc executa um movimento na conta. Vc tem uma entidade MovimentoConta que tem informação de onde, quando,quanto e porquê o saldo está sendo alterado. O saldo é a soma de todos os movimentos. A conta não tem uma propriedade saldo. ela tem um calculo de saldo.

Concordo com suas observações, na minha modelagem não daria pra imprimir um extrato por exemplo, devido a essa falta da entidade movimento.

Mas eu sei disso. Eu criei o modelo assim pq não era meu foco explicar como funciona o modelo financeiro, e sim se ele deveria criar um serviço, e onde entra a persistencia nisso tudo. Tudo muito ludico, mas a intenção foi essa mesmo. Mas acho que foi o suficiente pro entendimento do problema proposto.

Talvez seja isto que está faltando :compreender que a modelagem das classes de dominio depende do dominio.Não se trata de fazer escolhas tecnologias e sim de modelar corretamente. é pela modelagem correta que chegamos a um modelo coeso, desacoplado e não anémico.

As pessoas criam modelo anêmico ou pouco coesos porque:

  1. não entendem o dominio ( analise de requisitos/dominio)
  2. não sabem refletir o dominio em objetos (analise orientada a objetos)
  3. não sabem como devem ser as interações entre objetos ( ponto de vista teorico de OO, padrões, melhores práticas, etc…)
S

bobmoe:
sergiotaborda:

public class TransferenciaService{

public transferencia (Conta aDebitar, Conta aCreditar, double valor){

      MovimentoConta debita = new MovimentoConta (aDebitar, valor, Movimento.DEBITA);
      MovimentoConta debitaTaxa = new MovimentoConta (aDebitar, taxa, Movimento.DEBITA);
      MovimentoConta credita = new MovimentoConta (aCreditar, valor, Movimento.CREDITA);

      Transferencia trans = new Transferencia(aDebitar,aCreditar, agora());

     trans.add(credita);
     trans.add(debita );
     trans.add(debitaTaxa );

     // persiste tudo 

     daoTrasnferencia.salva(transf);
     daoMov.salva(credita);
     daoMov.salva(debita );
     daoMov.salva(debitaTaxa );

}
}


:shock:

public transferir (Conta de, Conta para, double valor){ new Transferencia(valor).debitar(de).creditar(para); transferenciaDao.salva(transferencia); }

O seu codigo mostra que existe uma entidade MovimentoConta ?
então como vc acha que o seu código é exemplo do que eu disse ?

Não se trata de fluencia aqui e sim de entender o dominio e porquê o objeto transferencia é necessário: para agrupar Movimentos.

Criado 7 de abril de 2010
Ultima resposta 13 de abr. de 2010
Respostas 113
Participantes 16