Juntar repository e collections é possível?  XML
Índice dos Fóruns » Arquitetura de Sistemas
Autor Mensagem
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
[WWW] [MSN] [ICQ]
fabim
GUJ Master
[Avatar]

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


[MSN]
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
[WWW] [MSN] [ICQ]
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
[WWW] [MSN] [ICQ]
Thiago Senna
GUJ Master
[Avatar]

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.

[Email]
fabim
GUJ Master
[Avatar]

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


[MSN]
sergiotaborda
GUJ Expert
[Avatar]

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
[WWW]
Edufa
JavaEvangelist
[Avatar]

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.
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
[WWW] [MSN] [ICQ]
sergiotaborda
GUJ Expert
[Avatar]

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
[WWW]
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
[WWW] [MSN] [ICQ]
sergiotaborda
GUJ Expert
[Avatar]

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
[WWW]
Thiago Senna
GUJ Master
[Avatar]

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.
[Email]
 
Índice dos Fóruns » Arquitetura de Sistemas
Ir para:   
Powered by JForum 2.1.8 © JForum Team