Hibernate e Domain-Driven Design  XML
Índice dos Fóruns » Arquitetura de Sistemas
Autor Mensagem
lelis718
What is classpath?
[Avatar]

Membro desde: 13/06/2007 22:21:53
Mensagens: 9
Offline

Bom pessoal, depois de ler a famosa discussão
http://guj.com.br/posts/list/60/60916.java
sobre Repositorio x DAO ficou uma coisa martelando em minha cabeça.

Afinal de contas.

Qual é a melhor forma de se utilizar o hibernate em um DDD?

Se o correto é evitar VOs e BOs
é normal eu exibir, em uma camada de apresentação algo como por exemplo





E para persistir os dados?
No momento em que eu vou cadastrar um cliente em uma determinada "tela faz tudo" em ajax que nela vou salvando os dados dos contatos e seus respectivos endereços. É normal se aproveitar do cascateamento do hibernate para isso e ter por exemplo um método



que salvaria todos os meus dados de cliente, também dos seus contatos e respectivos enderecos?

Qual é a forma que vocês fariam?
andre_salvati
GUJ Ranger

Membro desde: 02/06/2005 16:28:38
Mensagens: 939
Offline

lelis718 wrote:

Qual é a forma que vocês fariam?


Hoje eu uso Hibernate dentro do JBoss e faço da forma que vc falou. Só que o que vc faz com o "Repositorio", eu faço com o DAO.

Ajude na criação do StackOverflow em português!!!

http://area51.stackexchange.com/proposals/23539/software-development-in-portuguese?referrer=tI8Uon7RDszY236h5e0UuA2


http://www.empresadigital.inf.br
http://twitter.com/afsalvati
lelis718
What is classpath?
[Avatar]

Membro desde: 13/06/2007 22:21:53
Mensagens: 9
Offline

Taz wrote:
Hoje eu uso Hibernate dentro do JBoss e faço da forma que vc falou. Só que o que vc faz com o "Repositorio", eu faço com o DAO.


Certo. Mas dessa forma eu estou expondo meu domain model (negócios) na camada de apresentação. Isto é correto?

E se por alguma força maior do destino eu ser obrigado a não utilizar o hibernate... eu serei obrigado a criar um monte de repositórios com alguns métodos que fariam o que o hibernate faz.

Logo eu teria em um certo:


E , dentro da classe cliente, eu teria uma instancia de um EnderecoRepositorio (ou EnderecoDao) para eu retornar os dados.
Este EnderecoRepositorio teria o método

EnderecoRepositorio.obterEnderecoCliente(Cliente cliente).

E assim com as demais relações que eu tiver no meu modelo de domínio.
Ae então... voltando ao exemplo anterior:

lelis718 wrote:
No momento em que eu vou cadastrar um cliente em uma determinada "tela faz tudo" em ajax que nela vou salvando os dados dos contatos e seus respectivos endereços. É normal se aproveitar do cascateamento do hibernate para isso e ter por exemplo um método





Eu teria de implementar um cascateamento manual.

Vendo dessa forma vcs não acham que um Domain Model acaba de uma certa forma "exigindo" uma ferramenta de persistência?

(Sempre trabalhei com DDD e na maioria das vezes utilizei o hibernate ou similares e quando não utilizei tive bastante problemas desse tipo para resolver. Fico imaginando agora como seria a melhor forma de resolver sem ele ehehehe).


sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline

A melhor forma é aquela que funciona se vc alterar alguma coisa. Como vc disse se usar o hibernate directamente, e um dia vc deixar de poder usar o hibernate vc tem um problema. Mas se vc usar um objecto intermediário que encapsula o acesso ao repositorio se por detrás dos panos ele usar hibernate ou jpa ou jdbc não interessa ao resto da aplicação. O repositorio tem o proposito:

1) resolver o problema de localização. É pelo repositorio que os objetos do dominio encontram as entidades.
2) resolver o mapeamento de agregados*.
2.1) de isolar o dominio da persistência. Se o software requerer persistencia, ela será encapsulada dentro do repositorio. Mas um repositorio não é um DAO. A persistencia final será da responsabilidade de um DAO


*Agregado é um padrão para criar entidades em que os objetos que lhe são especificos são apenas maniuplados por ela. O repositório tem acesso privilegiado a isso para poder mapeá-los durante a persistência.

O jogo é mais ou menos assim

Uma ação de procura é requisitada ao Repositorio
O Repositorio traduz essa pesquisa em entiddes do dominio.
O repositorio usa um DAO para obter os dados das entidade. Estes dados podem ser dados em várias tabelas ou não.
O repositorio mapeia os dados obtidos do DAO para o objeto da entidade. Por exemplo, endereço é um objeto dentro de cliente, mas na tabela ele é um cojunto de campos no mesmo registro que os outros campos de cliente. O repositorio faz esse trabalho de separar quais dados são de quais objetos.
O repositorio retorna a entidade (ou conjunto de) pretendido.

Repare que o local "fisico" onde os dados estão é responsabilidade do DAO saber e não do Repositorio.
VC poderia ter um HibernateDAO ou um XMLDAO ou um HashMapDAO ou qq outra coisa. O repositorio não se interessa por esses detalhes. Por outro lado o DAO não sabe o que são aquele conjunto de campos que ele recebe. Ele é um "burro de carga" entre o local fisico onde os dados estão persistidos e o repositorio. Apenas isso.

Claro que o Repositorio e o DAO podem ser fundidos, mas isso, quanto a mim, não é flexivel.

Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
lelis718
What is classpath?
[Avatar]

Membro desde: 13/06/2007 22:21:53
Mensagens: 9
Offline


sergiotaborda wrote:
1) resolver o problema de localização. É pelo repositorio que os objetos do dominio encontram as entidades.
2) resolver o mapeamento de agregados*.
2.1) de isolar o dominio da persistência. Se o software requerer persistencia, ela será encapsulada dentro do repositorio. Mas um repositorio não é um DAO. A persistencia final será da responsabilidade de um DAO



Então pensando dessa forma como seria o melhor isolamento da camada de persistência?

seria algo como



Ae se eu utilizo o hibernate, eu retorno direto a lista de endereços.. se não eu não retorno.

Seria mais ou menos assim?



andre_salvati
GUJ Ranger

Membro desde: 02/06/2005 16:28:38
Mensagens: 939
Offline

lelis718 wrote:

Seria mais ou menos assim?



Eu prefiro separar os acessos ao repositório/DAO em FACADEs (Session Beans). Na realidade, o que vc está propondo é diferente (Active Record).

Ajude na criação do StackOverflow em português!!!

http://area51.stackexchange.com/proposals/23539/software-development-in-portuguese?referrer=tI8Uon7RDszY236h5e0UuA2


http://www.empresadigital.inf.br
http://twitter.com/afsalvati
lelis718
What is classpath?
[Avatar]

Membro desde: 13/06/2007 22:21:53
Mensagens: 9
Offline

Taz wrote:

Eu prefiro separar os acessos ao repositório/DAO em FACADEs (Session Beans). Na realidade, o que vc está propondo é diferente (Active Record).


Teria como postar um exemplo?
andre_salvati
GUJ Ranger

Membro desde: 02/06/2005 16:28:38
Mensagens: 939
Offline

Assim...



Gostaria de colocar a validação nos próprios Pojos, mas não foi possível devido a um problema com o Hibernate Validator.

Ajude na criação do StackOverflow em português!!!

http://area51.stackexchange.com/proposals/23539/software-development-in-portuguese?referrer=tI8Uon7RDszY236h5e0UuA2


http://www.empresadigital.inf.br
http://twitter.com/afsalvati
sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline

lelis718 wrote:

Então pensando dessa forma como seria o melhor isolamento da camada de persistência?

seria algo como





Seria mais como


Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
lelis718
What is classpath?
[Avatar]

Membro desde: 13/06/2007 22:21:53
Mensagens: 9
Offline

Sérgio agora você complicou minha cabeça.


Estamos vendo em isolar a camada de persistência...

Desta sua forma está isolado...
Mas ae não consigo enxergar a utilização do hibernate...

Seguindo este processo. com dao.getDadosCliente(id) retornando um map ou a outra coisa...
no hibernate utilizaríamos o dao.getDadosCliente(id) retornando o próprio cliente?

Mas ae a interface muda. como seria fazer um repositório híbrido?


sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline

lelis718 wrote:Sérgio agora você complicou minha cabeça.


Estamos vendo em isolar a camada de persistência...

Desta sua forma está isolado...
Mas ae não consigo enxergar a utilização do hibernate...

Seguindo este processo. com dao.getDadosCliente(id) retornando um map ou a outra coisa...
no hibernate utilizaríamos o dao.getDadosCliente(id) retornando o próprio cliente?

Mas ae a interface muda. como seria fazer um repositório híbrido?



Quem quiz usar o hibernate com DDD foi vc , não eu

O Hibernate é mais do que um simples ORM e mais do que um DAO, ele é um novo conceito
É um mecanismo de abstração de persistência em banco de dados. Esse mecanismo é muito semelhante ao JPA (aliás é historicamente ao contrário, mas ok)
Esse mecanismo do hibernate é mapeamento entre objectos e banco (ORM) + um mecanismo de controlo de ciclo de vida (em semelhança com os entity beans do EJB) mas só funciona com bancos de dados. A sua sintaxe e mecanismo são directamente relacionados ao SQL e à noção de tabela e campo.

Politica à parte, e no essencial das coisas, existe muito campo de manobra em DDD. Nem os seus criadores concordam na implementação do repositorio. A implementação de um repositorio pode ser tão directa como o uso directo de JDBC (que aliás se percebe que pode ser usado dentro das classes elas mesmas) ou tão indireta com o uso de um DAO que não assume mecanismos de persistencia (ou seja, não parte do principio que existirá um banco de dados, mas apenas um mecanismo de persistência abstracto)
Existem opiniões divergentes quanto a se um repositorio é um dao e vice-versa. Quanto a mim não é a mesma coisa. Um dos pilares da programação OO é a separação de responsabilidade. Ela traz mais classes e complica mais o código, mas simplifica a manutenção e a alteração. Veja, entidade não é um dado, registro não é uma entidade. É por isto que precisamos de mapeamento, mas ele só não chega.

A figura do repositorio em DDD é criada , como já disse, com o objetivo principal de permitir que entidades sejam encontradas por outros objetos do dominio e não com o objetivo de persistência. Repare que nenhuns outros tipos de objetos são obtidos com repositórios. No hibernate se vc tem cliente-->Endereço vc pode pgar todos os clientes (com ou sem o endereço) ou todos os endereços (sem os clientes) já que vc está abstractamente lendo duas tabelas diferentes. Em DDD vc não pode ler os endereços em separados dos clientes , a mesmos que os endereços sejam eles próprios entidade ( como chave) per se. São duas visões bem diferentes.
Por outro lado, veja que DDD é extremamente OO apenas na definição das partes do modelo. Ou seja, DDD é uma filosofia de modelagem, não de implementação. Tanto é que podemos ver exemplos de implementações usando JDBC diretamente( e ao mesmo tempo com a sugestão de usar ORM) mas até de uma forma pouco centralizada - que estariamos à espera de encontrar num programa que usa DAO.

Enfim, vc quer mesmo implementar um repositorio e usar DDD ? Esqueça persistência. DDD é tudo sobre modelar e nada sobre persistência. Em DDD nem tudo é uma entidade (nem tudo tem um ID), mas mesmo assim pode estar numa tabela. Isto é bem diferente da filosofia do JPA/Hibernate.

Provavelmente se usar DDD e depois de ter seus objetos de dominio vc for usar Hibernate/JPA irá acabar com essas classes cheias de annotations. Ora, é neste ponto que não é claro se colocar informações de persistência no dominio é violação de principios ou não é. Alguns dizem que não ( porque as annotations são meta programação) e outros dizem que sim ( porque elas estão vinculadas À classe, para as alterar é preciso alterar a classe). Eu acho que sim, pelo simples delas dependerem do DAO. Imagine que eu tenho um DAO puro JDBC
mas tá dando um trabalho cao para manter. Ai eu decido usar JPA/Hibernate. Mas com isso sou forçado a implementar annotations nos meus objetos de dominio só porque o JPA funciona assim. (sim, eu sei que pode escrever tudo no xml, esse não é o ponto). Se a implementação JPA deu pau e tiver momentaneamente que voltar para o DAO JDBC de que me servem todas aquelas anotações ? De nada. Isso mostra o vinculo que existe entre e o DAO e as anotações ( usadas fora do DAO mas que satisfazem apenas um DAO em particular).

O que eu tentei explicar é a diferença entre a responsabilidade de um Repositório em comparação com a de um DAO, que quanto a mim, não são a mesma. Os DAO que a gente vê por ai ( sobre tudo aquelas genericos que usam Hibernate/JPA por detrás dos panos) são na realidade um hibrido (ou seria mutante?). Eles fazem ambos os trabalhos. Mas em qual camada pertence um objeto que sabe sobre o dominio e sobre os dados persistidos ?
Para forçar a separação é preciso ter os dois.

O Repositorio encapsula todas as regras de relações entre objetos do dominio, em especial de entidades com seus VO , enquanto o DAO encapsula o acesso aos mecanismo de persistência.
Usar hibernate como um mecanismo de persistência dentro de um DAO é sim um sobre-trabalho, mas isso porque a tecnologia do hibernate não está nem ai para os repositorios e os DAO. o hibernate é um mediador completo entre o objeto da entidade e o banco e vice-versa que despresa o DAO.

É uma colisão de filosofias e concerteza complica a cabeça de muita gente.



Seguindo este processo. com dao.getDadosCliente(id) retornando um map ou a outra coisa...
no hibernate utilizaríamos o dao.getDadosCliente(id) retornando o próprio cliente?


Provavelmente vc retorna um objeto ClienteMemento, ou alguma coisa assim, que será mapeado para Cliente propriamente dito. Para discutir isto em profundidade tem que estar presente o conceito de Aggregado (Aggregation) para que seja clara a distinção entre entidade e conjunto de campos. Pois só assim faz sentido ter um repositorio (coleção de entidades) e um dao (acesso a conjuntos de campos)

Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
andre_salvati
GUJ Ranger

Membro desde: 02/06/2005 16:28:38
Mensagens: 939
Offline

sergiotaborda wrote:

O que eu tentei explicar é a diferença entre a responsabilidade de um Repositório em comparação com a de um DAO, que quanto a mim, não são a mesma. Os DAO que a gente vê por ai ( sobre tudo aquelas genericos que usam Hibernate/JPA por detrás dos panos) são na realidade um hibrido (ou seria mutante?). Eles fazem ambos os trabalhos. Mas em qual camada pertence um objeto que sabe sobre o dominio e sobre os dados persistidos ?
Para forçar a separação é preciso ter os dois.


Sérgio,

estaria vc dizendo que não é possível implementar DDD com Hibernate!?

Acredito que DDD ("uma filosofia de modelagem", como vc mesmo disse) pode utilizar Hibernate (uma decisão de implementação).

sergiotaborda wrote:
No hibernate se vc tem cliente-->Endereço vc pode pgar todos os clientes (com ou sem o endereço) ou todos os endereços (sem os clientes) já que vc está abstractamente lendo duas tabelas diferentes. Em DDD vc não pode ler os endereços em separados dos clientes , a mesmos que os endereços sejam eles próprios entidade (como chave) per se.


Realmente, no Hibernate vc pode fazer isso, mas não precisa. Vc poderia criar um DAO apenas para Cliente que retornasse também os Endereços, ignorando assim a existência de um DAO para Endereço. É uma questão de garantir que a implementação esteja adequada à sua "filosofia de modelagem".

This message was edited 2 times. Last update was at 30/08/2007 09:34:01


Ajude na criação do StackOverflow em português!!!

http://area51.stackexchange.com/proposals/23539/software-development-in-portuguese?referrer=tI8Uon7RDszY236h5e0UuA2


http://www.empresadigital.inf.br
http://twitter.com/afsalvati
sergiotaborda
GUJ Expert
[Avatar]

Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline

Taz wrote:
sergiotaborda wrote:

O que eu tentei explicar é a diferença entre a responsabilidade de um Repositório em comparação com a de um DAO, que quanto a mim, não são a mesma. Os DAO que a gente vê por ai ( sobre tudo aquelas genericos que usam Hibernate/JPA por detrás dos panos) são na realidade um hibrido (ou seria mutante?). Eles fazem ambos os trabalhos. Mas em qual camada pertence um objeto que sabe sobre o dominio e sobre os dados persistidos ?
Para forçar a separação é preciso ter os dois.


Sérgio,

estaria vc dizendo que não é possível implementar DDD com Hibernate!?


não. Não estou dizendo isso. O que estou dizendo é : se separar Repositorio de DAO e Entidade (DDD) de Entidade (de persistência) e tentar usar Hibernate para o DAO de persitencia, vc vai ter problemas de repetição (usando coisas como ClientMemento ou) ou problemas de acoplamento ( usando annotations)
Se não usar o DAO (com ou sem hibernate) e programar o acesso aos dados (com ou sem hibernate) directamente no repositorio vc está misturando responsabilidades. Se um dia precisar mudar o mecanismo de persistencia vai dar trabalho.

Imagine-se um programa cuja persistência é em xml. O programa cresce e agora é preciso usar banco de dados.
Como vc não isolou a persistencia num DAO e fez tudo no repositorio, agora vc tem que programar todos os repositorios de novo. Mas se vc tivesse usado um DAO e uma implementação XMLDAO agora era só implementar um DataBaseDAO e trocar pelo outro.



Criando sua própria API de Validação



Blog do MiddleHeaven
[WWW]
lelis718
What is classpath?
[Avatar]

Membro desde: 13/06/2007 22:21:53
Mensagens: 9
Offline

sergiotaborda wrote:

Imagine-se um programa cuja persistência é em xml. O programa cresce e agora é preciso usar banco de dados.
Como vc não isolou a persistencia num DAO e fez tudo no repositorio, agora vc tem que programar todos os repositorios de novo. Mas se vc tivesse usado um DAO e uma implementação XMLDAO agora era só implementar um DataBaseDAO e trocar pelo outro.




Sim então..
é esse o ponto em que eu iria chegar.

Então não existe um modelo para implementar um DAO utilizando o Hibernate?

Nos meus projetos eu utilizo o DAO e faço implementações sobre o hibernate em cima de um "HibernateDAO" onde faço todo trabalho de sessões do hibernate nesta Dao e retorno, diretamente da DAO, objeto necessário por exemplo o método

Cliente cliente = dao.obterCliente(id);


E então eu tenho alguns problemas em cima do Domain Model onde caio naqueles resultados que postei :



onde sou realmente obrigado a implementar como vc mesmo diz um ActiveRecord.

Agora seria esta a melhor forma de implementação de um domain model com o hibernate? com o padrão de ActiveRecord ?
E então numa situação onde sou obrigado a retirar o hibernate o meu objeto passa a solicitar as informações para os Repositórios..
O que você acha disso?


Edufa
JavaEvangelist
[Avatar]

Membro desde: 18/04/2006 10:20:03
Mensagens: 315
Localização: Curitiba, PR
Offline

Vamos lá, estou estudando isso e deixe-me ver se sei responder ou ajudar alguma coisa, pq tb to tendo alguma dificuldade de entender esses conceitos, nem tanto de entender mas de ver a coisa toda se encaixando.

O Dao sabe como persistir e recuperar um objeto (não importa onde). O repositório atua no meio de campo entre os objetos de domínio e os dao. OU seja o repositório sabe quais daos instanciar e usar para salvar e/ou recuperar um determinado objeto.

Dessa forma os conceitos são diferentes, o dao tem de se preocupar com banco de dados, xml, arquivo texto, etc, ele carrega mastiga e o repositório gerencia os objetos de domínio e suas agregações. Olhando pelo outro lado, objetos de domínio deveriam trabalhar apenas com o repositório e não precisam saber ou imaginar o q é dao.

No repositório então vc teria um método List<Usuario> getUsuarioComNotaBaixaSemComentario(); (por que sua lógica de negócios exige que vc marque todos os usuários sem comentários e com notas baixas), e dentro do método vc chama o dao, monta a query.

Acho que um dos problemas principais de entender essa abordagem é a dificuldade de ver exemplos práticos disso implementados, enquanto uso de dao com hibernate vc acha montes de exemplos códigos, sugestões, com ddd, vc não acha tanto código e mais a parte teórica. O motivo disso, eu vejo que normalmente usa-se ddd em sistemas maiores e mais complexos, sendo assim difícil de ter um sisteminha de locadora ou biblioteca ou cdteca com essas idéias. Não sei quanto aos outros, mas eu gosto de pegar código e comparar com o q eu faço.

Quem sabe mais favor indicar os erros, rs

---

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