[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 ?
- Criar uma classe utilitária que recebe o objeto e calcula a sua idade (Idades.idadeDe(Pessoa, Date) , Idade.idadeDeCasa(Casa, Date , etc…)
- Manter um método idadeEm(Date):int em cada um copiando o codigo e alterando conf0orme as propriedades de cada objeto
- 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”.