| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 12:30:59
|
Fabio Kung
JavaEvangelist
Membro desde: 08/03/2004 08:24:47
Mensagens: 445
Localização: São Paulo
Offline
|
sergiotaborda wrote:O que interessa é que vc SEMPRE vai poder usar o modelo na sua forma pura sem recurrer a truques ou a métodos "globais" como repositorio.getAlunosDa(turma).
Usar este tipo de codigo é fazer modelos orientados a banco de dados e não modelos OO.
Eu nunca defendi isso. Apenas enumerei as opções. Minha opção sempre foi por fazer turma.getAlunos() e turma.getAlunosComNotaMenorQue(double).
Além disso, o seu jeito de fazer que me cheira procedural e não OO. Isso que você chama de usar o modelo na sua forma mais pura?
Para descobrir os alunos com nota maior que 8 não é necessário um repositório inteligente. Apenas um serviço que faça esse processo. E funciona +- assim:
Esse é um exemplo claro de que o mecanismo de persistência que você usa impacta sim, onde é ou não viável usar um repositório. Para qualquer sistema que não seja um pet-project é proibitivo fazer o que você fez.
Se eu sei que tenho um banco de dados, não há porque ignorar isso e trazer *todos* os objetos para a memória para filtrar alguns e pegar só o que eu quero. Você não convence ninguém a eliminar a principal vantagem dos bancos de dados relacionais, que é fazer consultas.
Ignorar o mecanismo de persistência é nivelar por baixo.
E aceitar o fato de que o banco de dados existe, não significa fazer sistemas orientados a banco de dados. Significa mesmo, apenas aceitar que ele existe e aproveitar aquilo que ele tem a te oferecer. Continuo podendo fazer DDD e sistemas OO.
sergiotaborda wrote:Se a escolha do ORM inpacta o seu modelo então para que serve o DAO ? Afinal que isolamento é esse ? Isolamento poroso ? Se o ORM impacta o modelo o seu sistema é fortemente acoplado. Pior ainda, só funciona dessa maneira. Então para quê complicar com DAO e repositorios ? Arranque isso fora , deixe o ORM puro e pronto. Vai ganhar um monte em simplicidade e poupar um monte de camadas inuteis no seu sistema.
DAOs não servem para isolar nada. Na prática isso nunca foi verdade. DAOs servem sim para centralizar o acesso aos dados e dividir a responsabilidade no seu sistema.
|
Procurando por oportunidades de emprego?
OndeTrabalhar.com
OndeTrabalhar.com Java?
http://blog.caelum.com.br
Fabio Kung
|
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 12:37:39
|
fabim
GUJ Master
![[Avatar]](/images/avatar/d4e3e8180a65648886ff348c7a6bbff5.jpg)
Membro desde: 14/12/2006 19:30:03
Mensagens: 1268
Localização: Vitoria - Espirito Santo
Offline
|
Fabio Kung wrote:DAOs servem sim para centralizar o acesso aos dados e dividir a responsabilidade no seu sistema.
Daos servem pra dividir responsabilidade de q? Mas DAO's nao são apenas Data-Mappers? Que deveriam ser plugáveis?
|
ειπεν αυτη ο ιησους εγω ειμι η αναστασις και η ζωη ο πιστευων εις εμε καν αποθανη ζησεται
Sun Certified Web Component Developer
Sun Certified Java Programmer
Sun Certified Java Associate
Sun Certified Business Component Developer - Em Andamento
Bacharelando em Sistemas de Informacao
 |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 12:51:59
|
Fabio Kung
JavaEvangelist
Membro desde: 08/03/2004 08:24:47
Mensagens: 445
Localização: São Paulo
Offline
|
Edufa wrote:Seria esse um caminho ou seria exagero?
Edufa, perfeito o seu auto-questionamento.
A sua proposta é uma das melhores formas de se abstrair ao máximo os mecanismos de persistência, com Repositorios e Specifications.
Eu só discordo um pouco de deixar a responsabilidade de montar as Specifications pelo sistema todo. Eu as centralizaria no repositório mesmo e não exporia o método List<Aluno> getAlunos(Specification specification) para quem usa o repositório.
A questão que eu sempre faço a mim mesmo é: vale mesmo a pena colocar mais uma camada em cima do hibernate? Como o Laércio já postou, frases do próprio Evans:
Eric Evans wrote:"In general, don't fight your frameworks. Seek ways to keep the fundamentals of domain-driven design and let go of the specifics when the framework is antagonistic. Look for affinities between the concepts of domain-driven design and the concepts in the framework."
Abstrair totalmente a persistência tem um custo muito alto e você vai ter que replicar muita coisa do que já está feito na API de Criteria, por exemplo. Aliás, Criteria é um bom exemplo do padrão Specification.
Além disso vai ter que fazer implementações de Specification diferentes para cada mecanismo diferente de persistência que tiver, ou então diferentes conversores (Specification -> HQL, Specification -> SQL, Specification -> XPath, Specification -> Criteria, ...), que nada mais são do que verdadeiros compiladores.
Vale a pena? Quantas vezes alguém precisou trocar completamente o mecanismo de persistência?
Eu diria que não vale a pena.
Além disso, fatalmente você cai em algum caso que não dá para generalizar a operação específica de alguma das estratégias e aí você deixa ela de fora do seu conjunto de Specifications. Se conseguíssemos mesmo generalizar todo e qualquer mecanismo de persistência, não haveria necessidade de várias abordagens para consulta (relacional, oo, olap, document-based, ...).
|
Procurando por oportunidades de emprego?
OndeTrabalhar.com
OndeTrabalhar.com Java?
http://blog.caelum.com.br
Fabio Kung
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 13:01:07
|
Fabio Kung
JavaEvangelist
Membro desde: 08/03/2004 08:24:47
Mensagens: 445
Localização: São Paulo
Offline
|
fabiocsi wrote:
Fabio Kung wrote:DAOs servem sim para centralizar o acesso aos dados e dividir a responsabilidade no seu sistema.
Daos servem pra dividir responsabilidade de q? Mas DAO's nao são apenas Data-Mappers? Que deveriam ser plugáveis?
Daos centralizam o código de acesso a dados para que você não fique fazendo select/hql/criteria/buscaemxml/... pelo seu sistema inteiro. E sim, eles são DataMappers.
|
Procurando por oportunidades de emprego?
OndeTrabalhar.com
OndeTrabalhar.com Java?
http://blog.caelum.com.br
Fabio Kung
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 13:04:24
|
Thiago Senna
GUJ Master
![[Avatar]](/images/avatar/78719f11fa2df9917de3110133506521.jpg)
Membro desde: 11/02/2005 08:08:02
Mensagens: 1595
Offline
|
sergiotaborda wrote:
Sair criando reposiories genéricos para tudo quanto é entidade para mim vai dar em merda. Repositores com método add ou remove só justifica se ele é o topo da hieraquia de relacionamentos.
@#$@#$ ele É o topo da hirarquia!
Ok Sérgio, de qualquer maneira, não escrevi tudo aquilo com intenção de dizer que você disse o contrário. Mas eu reforcei essa colocação por que em um exemplo anterior você colocou um código onte o repositório de turma estava também mantendo o repositório de aluno.
sergiotaborda wrote:
O codigo de repositorio de turmas é mais ou menos assim:
Acho muito trabalhoso meus repositorios conter este tipo de lógica. Além de modelar o domínio também vou ter que pensar em como o meu repositório vai manter o domínio? Faz mais sentido o TurmaRepositorio saber que todos os alunos do sistemas estão espalhados pelas instâncias das turmas. Pronto! Para que manter um AlunoRepository?
sergiotaborda wrote:O grafo de turma ainda tem que ser validado, tem que passar por serviços e só no fim, se tudo estiver ok, que o aluno novo será adicionado à lista de alunos.
Perfeito! Se eu entendi, então a validação pode ocorrer no método TurmaRepository.add, correto? A validação do aluno pode ocorrer na coleção, quando for feito turma.getAlunos.add/turma.addAluno.
O problema desta minha abordagem mesmo é ficar sobrescrevendo as collections. Isso pode acabar ficando trabalhoso, mas posso criar um grupo de collections que facilitem minha vida.
Afinal, qual é o problema das minhas collections também possuirem regras de negócio e saberem delegar ações para uma estratégia de persistência? ao meu ver, isso parece um recurso muito poderoso -> a minha infraestrutura pode injetar no meu domain collections conhecidas apenas por ele (a infra) sem que o domain tome conhecimento disso.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 13:05:04
|
fabim
GUJ Master
![[Avatar]](/images/avatar/d4e3e8180a65648886ff348c7a6bbff5.jpg)
Membro desde: 14/12/2006 19:30:03
Mensagens: 1268
Localização: Vitoria - Espirito Santo
Offline
|
Fabio Kung wrote:
Daos centralizam o código de acesso a dados para que você não fique fazendo select/hql/criteria/buscaemxml/... pelo seu sistema inteiro. E sim, eles são DataMappers.
E não conhecem objetos de dominio certo?
Um DAO nao pode, por exemplo, retornar um List<Alunos>... senao como ele seria plugável?
This message was edited 1 time. Last update was at 07/03/2008 13:06:05
|
ειπεν αυτη ο ιησους εγω ειμι η αναστασις και η ζωη ο πιστευων εις εμε καν αποθανη ζησεται
Sun Certified Web Component Developer
Sun Certified Java Programmer
Sun Certified Java Associate
Sun Certified Business Component Developer - Em Andamento
Bacharelando em Sistemas de Informacao
 |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 13:12:39
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline
|
Fabio Kung wrote:
sergiotaborda wrote:O que interessa é que vc SEMPRE vai poder usar o modelo na sua forma pura sem recurrer a truques ou a métodos "globais" como repositorio.getAlunosDa(turma).
Usar este tipo de codigo é fazer modelos orientados a banco de dados e não modelos OO.
Eu nunca defendi isso. Apenas enumerei as opções. Minha opção sempre foi por fazer turma.getAlunos() e turma.getAlunosComNotaMenorQue(double).
Além disso, o seu jeito de fazer que me cheira procedural e não OO. Isso que você chama de usar o modelo na sua forma mais pura?
Para mim, modelo não é banco de dados. modelo são classes interagindo.
Se vc conhece uma forma mais pura, diga. Somos todos ouvidos.
(...)
Esse é um exemplo claro de que o mecanismo de persistência que você usa impacta sim, onde é ou não viável usar um repositório. Para qualquer sistema que não seja um pet-project é proibitivo fazer o que você fez.
Na prática vc tem razão. É poibitivo por motivos de arquitetura e limitação tecnologica. Mas não porque o modelo está mal desenhado ou existe algum problema com o conceito de repositorio.
O ponto era destingir a função do repositorio da função de um serviço. Eu poderia implementar de outro modo usando o padrão QueryObject. Mas eu só faria isso por motivos de limitação. Em tese o codigo acima não tem qualquer problema e reflete exactamente o que é necessário ser feito. E isso é a fiolosofia do DDD.
Pegue o exemplo de uma estratégia de persistencia em memoria como já foi exemplificado aqui.
Pense que ha um prevayler ou algo ali que não é um banco de dados. A $%#$% dos objetos está em memoria. O ponto é que vc não sabe. Não lhe interessa. Não é responsabilidade do dominio saber isso. Mesmo assim vc precisa do QueryObject porque fazer for a todo o momento não é prático. Contudo, o QueryObject para o caso da estratégia em memoria vai acabar sendo isso mesmo. E agora vc vai dizer que isso é irreal.
Não, não é irreal. Se vc tiver um ambiente distribuido onde precisa de cache local fazer essas pesquisas não é tão simples assim e vc não pode chamar o banco porque vc nem tem permissão de se conectar com ele!
Na prática vc usa o QueryObject e faz o seu DAO mapear esse objeto para uma forma interna de procura. No caso de objetos em memoria vc usa o for com um if , para o caso do XML usa XPath, para bancos usa SQL e assim vai. Mas quando vc cria o serviço de DOMINIO vc não pode estar pensando no SQL. Esse é o ponto.
Enquanto vc não enxergar o banco como "um mecanismo entre os possiveis" e não como deus, vc nunca vai sair do mesmo ponto.
Se eu sei que tenho um banco de dados, não há porque ignorar isso e trazer *todos* os objetos para a memória para filtrar alguns e pegar só o que eu quero. Você não convence ninguém a eliminar a principal vantagem dos bancos de dados relacionais, que é fazer consultas.
Ignorar o mecanismo de persistência é nivelar por baixo.
O que eu fiz foi ignorar o mecanismo de consultas como vc disse no primeiro paragrafo e não o de persistencia.
Eu estava apenas tentando diferenciar a responsabildiade do repositorio da de um serviço. mas tudo bem. não entenderam ? dane-se.
Na prática vc implementa o padrão QueryObjet junto com Intrepreter (isto é o que os Criteria do hibernate são). E isso é que é funcional. contudo, quem monta a query ?? A @#$@#$ do serviço e não o repositorio.
Era só isso que eu estava dizendo.
E aceitar o fato de que o banco de dados existe, não significa fazer sistemas orientados a banco de dados. Significa mesmo, apenas aceitar que ele existe e aproveitar aquilo que ele tem a te oferecer. Continuo podendo fazer DDD e sistemas OO.
(...)
DAOs não servem para isolar nada. (..)
Se vc sabe tão bem assim que tem um banco de dados esqueça repositorios. Não são para vc. A sério.
Repositorios são para pessoas que não querem saber se têm bancos de dados ( OO = encapsulamento = não quero saber).
Se os DAOs não servem para isolar nada para quê usá-los ? Use o hibernate directamente e seja feliz.
E não me diga que é daqueles que cria um DAO para cada entidade e depois chama o hibernate lá dentro.
Nem me diga que cria um Façade para o Hibernate. Estas coisas sim, não servem para nada.
Existe uma tempo em que estamos modelando. Falando em abstrato. Discutindo conceitos.
E existe um tempo em que estamos falando de codigo, implementação. Discutindo opções práticas.
Não pode misturar as duas coisas. Só serve para se confundir.
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 13:13:15
|
Edufa
JavaEvangelist
![[Avatar]](/images/avatar/5747a0021eb349e9c8d3667cf1a5e9ec.jpg)
Membro desde: 18/04/2006 10:20:03
Mensagens: 315
Localização: Curitiba, PR
Offline
|
Fabio Kung wrote:
Eu só discordo um pouco de deixar a responsabilidade de montar as Specifications pelo sistema todo. Eu as centralizaria no repositório mesmo e não exporia o método List<Aluno> getAlunos(Specification specification) para quem usa o repositório.
Concordo, eu acabei me influenciando por um projeto onde eu tive de montar filtros plugáveis, o usuário montava a consulta usando um monte de parametros e possibilidades, e salvava-as para serem reutilizadas.
Resumidamente ele montava as Criteria e agrupava em Specifications.
Nesse caso eu teria de externar a criteria e as specification, que na época não chamei por estes nomes pois não tinha esse conhecimento. Deu trabalho e ficou feio, mas bem flexivel para o usuário final. rs.
Seria uma abordagem com bastante poder em termos de consultas, mas algo bem específico.
Fabio Kung wrote:
A questão que eu sempre faço a mim mesmo é: vale mesmo a pena colocar mais uma camada em cima do hibernate? Como o Laércio já postou, frases do próprio Evans:
Eric Evans wrote:"In general, don't fight your frameworks. Seek ways to keep the fundamentals of domain-driven design and let go of the specifics when the framework is antagonistic. Look for affinities between the concepts of domain-driven design and the concepts in the framework."
Abstrair totalmente a persistência tem um custo muito alto e você vai ter que replicar muita coisa do que já está feito na API de Criteria, por exemplo. Aliás, Criteria é um bom exemplo do padrão Specification.
Concordo totalmente. Acredito q como não existe solução simples recai-se num purismo de querer eliminar o Criteria do hibernate no repositório
Fabio Kung wrote:
Além disso vai ter que fazer implementações de Specification diferentes para cada mecanismo diferente de persistência que tiver, ou então diferentes conversores (Specification -> HQL, Specification -> SQL, Specification -> XPath, Specification -> Criteria, ...), que nada mais são do que verdadeiros compiladores.
Sim apesar de ver algumas apis q fazem isso, nenhuma delas é completa seria ótimo se tivesse algo como a Criteria do hibernate, só que de mais alto nivel q inclusive pudesse ser usada em collections. Deixando essa parte bem mais transparente.
Fabio Kung wrote:
Vale a pena? Quantas vezes alguém precisou trocar completamente o mecanismo de persistência?
Eu diria que não vale a pena.
Além disso, fatalmente você cai em algum caso que não dá para generalizar a operação específica de alguma das estratégias e aí você deixa ela de fora do seu conjunto de Specifications. Se conseguíssemos mesmo generalizar todo e qualquer mecanismo de persistência, não haveria necessidade de várias abordagens para consulta (relacional, oo, olap, document-based, ...).
Acho interessante ver o lado purista, para depois ver o lado prático, comparar os dois e ver quais as melhores práticas que podem ser usadas. Se dá para montar algo genérico, mas ficar um monstro, legal, é interessnate ver o custo de certas escolhas. Até mesmo para poder defender onde e quando deve-se ser mais rigoroso.
Como apontei lá em cima eu tive de fazer uso de uma solução que ficaria muito mais elegante usando Specification e Criteria, desconhecer o caminho mais purista atrapalha, bem como aceita-lo sem questionamento.
|
Edufa
Curitiba, PR
--
"O estado sou eu". - Luís XIV
"O estado somos nós."- Lênin
"O estado somos eu." - Lula
--
O mundo é deles mas a amazônia é nossa
O petróleo é nosso, mas o gás é deles.
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 13:18:31
|
Fabio Kung
JavaEvangelist
Membro desde: 08/03/2004 08:24:47
Mensagens: 445
Localização: São Paulo
Offline
|
perfeito edufa. Nesse seu caso eu também optaria por expor algum tipo de Specification.
|
Procurando por oportunidades de emprego?
OndeTrabalhar.com
OndeTrabalhar.com Java?
http://blog.caelum.com.br
Fabio Kung
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 13:20:46
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline
|
Thiago Senna wrote:
Acho muito trabalhoso meus repositorios conter este tipo de lógica. Além de modelar o domínio também vou ter que pensar em como o meu repositório vai manter o domínio? Faz mais sentido o TurmaRepositorio saber que todos os alunos do sistemas estão espalhados pelas instâncias das turmas. Pronto! Para que manter um AlunoRepository?
Era só um exemplo!!! Na realidade o repositorio não vai chamar o repositorio de aluno porque o aluno já foi incluido antes. Era apenas um exemplo que tentava mostrar que a logica de um repositorio não é apenas delegar. ao DAO. O objetivo do respositorio é poder escrever acções sobre a coleção total de objetos de forma dependente do dominio. Se vc não precisa disso, vc nem precisa de repositorios.
sergiotaborda wrote:O grafo de turma ainda tem que ser validado, tem que passar por serviços e só no fim, se tudo estiver ok, que o aluno novo será adicionado à lista de alunos.
Perfeito! Se eu entendi, então a validação pode ocorrer no método TurmaRepository.add, correto?
Não.
Não vou explicar de novo a diferença entre consistencia e validação. A validação ocorre em objetos de vaidação especialmente construidos para isso.
O problema desta minha abordagem mesmo é ficar sobrescrevendo as collections. Isso pode acabar ficando trabalhoso, mas posso criar um grupo de collections que facilitem minha vida.
Afinal, qual é o problema das minhas collections também possuirem regras de negócio e saberem delegar ações para uma estratégia de persistência? ao meu ver, isso parece um recurso muito poderoso -> a minha infraestrutura pode injetar no meu domain collections conhecidas apenas por ele (a infra) sem que o domain tome conhecimento disso.
Cara, tente implementar isso. Use um dominio sério e complexo.
Rápidamente vc vai descobrir os pros e contras dessa sua ideia.
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 13:21:42
|
Fabio Kung
JavaEvangelist
Membro desde: 08/03/2004 08:24:47
Mensagens: 445
Localização: São Paulo
Offline
|
sergiotaborda wrote:
Fabio Kung wrote:
(...)
Esse é um exemplo claro de que o mecanismo de persistência que você usa impacta sim, onde é ou não viável usar um repositório. Para qualquer sistema que não seja um pet-project é proibitivo fazer o que você fez.
Na prática vc tem razão. É poibitivo por motivos de arquitetura e limitação tecnologica. Mas não porque o modelo está mal desenhado ou existe algum problema com o conceito de repositorio.
Ótimo Sérgio. Concordo plenamente com você aqui.
Só acho que não concordamos no que eu andei dizendo em resposta a outras pessoas, que eu acho que o custo é alto demais para se pagar e você não acha. Mas tudo bem, temos opiniões diferentes e ponto. A discussão foi válida.
Discussão encerrada?
|
Procurando por oportunidades de emprego?
OndeTrabalhar.com
OndeTrabalhar.com Java?
http://blog.caelum.com.br
Fabio Kung
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 14:25:08
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline
|
fabiocsi wrote:
Fabio Kung wrote:
Daos centralizam o código de acesso a dados para que você não fique fazendo select/hql/criteria/buscaemxml/... pelo seu sistema inteiro. E sim, eles são DataMappers.
E não conhecem objetos de dominio certo?
Um DAO nao pode, por exemplo, retornar um List<Alunos>... senao como ele seria plugável?
Exactamente. Não só isso como eles seriam dependentes do modelo não sendo reaproveitáveis.
O DAO tem que abstrair a API de persistencia, mas também tem que ser reutilizável em diferentes dominios.
Na prática se o objeto seguir certas convenções ( como ter um construtor publico sem parametros) vc pode usar Generics e Reflection para aceitar e devolver qualquer objeto. É um truque. Na realidade ele trabalha como Object.
Qualquer Object.
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 07/03/2008 14:43:53
|
Thiago Senna
GUJ Master
![[Avatar]](/images/avatar/78719f11fa2df9917de3110133506521.jpg)
Membro desde: 11/02/2005 08:08:02
Mensagens: 1595
Offline
|
sergiotaborda wrote: Cara, tente implementar isso. Use um dominio sério e complexo.
Rápidamente vc vai descobrir os pros e contras dessa sua ideia.
Comecei a implementar algumas coisinhas. To começando com um modelo mais simples e vou adicionar complexidade aos poucos. Se eu for fiel a este 'pet project' e der uma enroscada (ou estiver fácil demais) eu volto aqui pra vocês colocarem lenha na fogueira.
|
|
|
 |
|
|