| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 28/04/2008 23:51:49
|
MauricioAniche
Entusiasta Java
Membro desde: 20/12/2007 18:33:07
Mensagens: 24
Offline
|
Pessoal,
No meu tópico anterior, discutimos um pouco sobre quem deveria ser responsável por persistir a informação no banco. No livro do Nilsson, ele sugere algo do tipo:
ISession session = SessaoDoHibernate();
RepositorioDeClientes repositorio = new RepositorioDeClientes(session);
repositorio.adiciona(x);
reposiorio.deleta(y);
session.BeginTransaction().Commit();
A implementacao de adiciona() no caso seria
_session.Save(x);
ou
vocês repassam esse session pra um DAO e este sim executa o Save()? Pq aí eu não vejo muita vantagem em ter diversos DAOs, já que o repositorio acaba recebendo o ISession do NHibernate!
Ou vocês utilizam a estratégia do Service, igual o Sérgio explicou no post anterior?
[]'s
Mauricio
|
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 00:51:57
|
Alessandro Lazarotti
Virtual Machine Man
![[Avatar]](/images/avatar/2aaaddf27344ee54058548dc081c6541.jpg)
Membro desde: 21/01/2004 14:12:54
Mensagens: 719
Offline
|
DAO traz a abstração de em qual banco voce vai persistir, neste caso representado pela Session do hibernate (que pra ser honesto é um pouco diferente que um DAO, talvez um "DomainStore" versão "DataMapper" rs, mas admita por momento que ele seja seu DAO)... Na verdade, não é necessário "vários DAOs" (em relação a representação e não a infra), o que se precisa é de vários repositórios.
This message was edited 2 times. Last update was at 29/04/2008 01:10:56
|
... Lezinho
------------------------
twitter: @lazarotti
http://alessandrolazarotti.wordpress.com/
http://jbossbrasil.org/
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 00:54:21
|
Alessandro Lazarotti
Virtual Machine Man
![[Avatar]](/images/avatar/2aaaddf27344ee54058548dc081c6541.jpg)
Membro desde: 21/01/2004 14:12:54
Mensagens: 719
Offline
|
PS: o código fica melhor com o DAO injetado (do que simplesmente uma IoC manual pelo consrtrutor), pelo menos as dependencias não ficam evidentes no domínio.
|
... Lezinho
------------------------
twitter: @lazarotti
http://alessandrolazarotti.wordpress.com/
http://jbossbrasil.org/
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 09:46:58
|
MauricioAniche
Entusiasta Java
Membro desde: 20/12/2007 18:33:07
Mensagens: 24
Offline
|
Alessandro,
O problema é que o ISession tem que ser injetado pelo construtor mesmo, pois eu posso ter diferentes Units of Work em diferentes repositórios. A idéia é de injetar o ISession (Unit Of Work) e depois deixar o UnitOfWork persistir todos os dados.
Minha dúvida é se vocês usam o próprio ISession do HHibernate como Unit of Work, ou vocês abstraem e criam seu próprio Unit of Work e implementam um NHibernateUnitOfWork...
Ou vocês no fundo, usam outra estratégia para persistir os dados, como Services, igual o Sérgio explicou! Essa estratégia do Unit of Work me agradou bastante, o código fica bem bacana!
Consegui me explicar?
[]'s
Mauricio
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 10:02:50
|
Alessandro Lazarotti
Virtual Machine Man
![[Avatar]](/images/avatar/2aaaddf27344ee54058548dc081c6541.jpg)
Membro desde: 21/01/2004 14:12:54
Mensagens: 719
Offline
|
O problema é que o ISession tem que ser injetado pelo construtor mesmo, pois eu posso ter diferentes Units of Work em diferentes repositórios. A idéia é de injetar o ISession (Unit Of Work) e depois deixar o UnitOfWork persistir todos os dados.
Mas qual é a diferença de você injetar na mão ou um framework fazer a inversão pra você?
Minha dúvida é se vocês usam o próprio ISession do HHibernate como Unit of Work, ou vocês abstraem e criam seu próprio Unit of Work e implementam um NHibernateUnitOfWork...
Eu prefiro um abstractDao do que usar diretamente a implementação do Hibernate, por exemplo. No implementar eu tenho liberdade de fugir do JPA e usar features do Hibernate ou preferir seguir a risca a especificação do JavaPersistence, essa é "uma" das vantagem de abstrair. Claro que para ter um efeito melhor, as queries tbm deveriam ser abstraídas por QueryObjects... embora de um trampo maior, suas dependencias ficam menores. Mas apenas abstrair os gerenciadores, já podem ser interessantes, olhando para o repository e não vendo nenhum EntityManager por exemplo.
OBS: Os repositórios neste modelo não seriam simples "delegadores", eles conteriam as regras para a consulta. Tbm deixo claro que essa é UMA possível implementação, para cada caso pode ocorrer uma engenharia diferente para a resolução do problema motivado pelo padrão.
|
... Lezinho
------------------------
twitter: @lazarotti
http://alessandrolazarotti.wordpress.com/
http://jbossbrasil.org/
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 10:41:31
|
MauricioAniche
Entusiasta Java
Membro desde: 20/12/2007 18:33:07
Mensagens: 24
Offline
|
Alessandro,
Nunca implementei realmente um framework de IoC, então me corrija se eu estiver errado: Com a injeção sendo feita de forma automática, eu não tenho a instância do objeto que foi injetado, a não ser que eu pegue através de um getUnitOfWork() ou algo assim, correto? E caso eu queira a mesma instância em 2 repositórios diferentes, como eu faria?
E como esse UnitOfWork é responsável pela minha persistência, como eu o chamaria? Através de um get() no repositório?
Como você resolve isso?
[]'s
Mauricio
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 10:53:11
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline
|
MauricioAniche wrote:
ISession session = SessaoDoHibernate();
RepositorioDeClientes repositorio = new RepositorioDeClientes(session);
repositorio.adiciona(x);
reposiorio.deleta(y);
session.BeginTransaction().Commit();
Isto é tipicamente o codigo dentro de um UnitOfWork.
O Session não é um UnitOfWork é um DAO. ( Na realiaade é uma parte do DomainStore que é o Hibernate... mas ok)
A tecnologia de persistencia ( aka a API de persistencia) tem que ser chamada do DAO. Caso contrário vc tem um vinculo forte (acoplamento) com essa API. Esse vinculo não é necessáriamente ruim. Vc tem que escolher se quer usar a API directamente e se ferrar depois, ou usar o DAO e não se ferrar depois. Mas se o sistema so for funcionar por 1 mes tlv esse "depois" nunca chegue e portanto a escolha é menos relevante.
A ideia é: lei de murphy : vc vai se ferrar de qualquer jeito: use DAO.
Faça UnitOfWork ser um objeto explicito com transação controladada fora dele. É mais fácil.
Pense no UnitOfWork como um Command cuja execução é especial: é dentro de uma transação e num ambiente que controla concurrencia.
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 11:21:04
|
MauricioAniche
Entusiasta Java
Membro desde: 20/12/2007 18:33:07
Mensagens: 24
Offline
|
Sérgio,
É nisso que eu queria chegar... Você injeta um IUnitOfWork no repositório. A minha dúvida é como é essa interface...
Algo do tipo resolveria, concorda?
Os Unit of Works de vocês tem algo a mais do que isso?
E aí tanto o Repositorio quanto o Unit of Work fica acoplado ao DAO? Por exemplo..
É por aí?
[]'s
Mauricio
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 13:01:28
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline
|
MauricioAniche wrote:Sérgio, É nisso que eu queria chegar... Você injeta um IUnitOfWork no repositório. A minha dúvida é como é essa interface... Algo do tipo resolveria, concorda? Os Unit of Works de vocês tem algo a mais do que isso?
Esse é o padrão UnitOfWork tal como definido pelo Fowler. Na prática não encontro essa forma do padrão util. Eu perfiro um versão um pouco diferente (que chamo de WorkUnit para não confundir). A ideia é que existe um objetivo do tipo comando (o WorkUnit) cuja execução é controlada através de um contexto. Ele pode usar esse contexto para fazer lock de recurso para controlar concorrencia ( pois a do banco não é suficiente já que pode nem existir um banco...). O contexto usa um DAO especial. Este dao recebe todos as ações mas não as executa, apenas as coloca numa lista. Só quando acontece o commit é que o DAO joga os comandos para um DAO real. Aqui é extremamente importante que o Repositorio possa ser injetado com o DAO. O repositorio é obtido através de um Registry que olha um threadLocal pelo DAO que está valendo. O WrokContext manipula esse threadlocal para que o Repositorio seja injetado com o DAO "dummy" . Dentro do codigo do workunit que é o que o programador escreve não ha diferença nenhuma já que ele está proibido de usar o DAO , tem que usar o respositório sempre que mexe com regras de negocio. No fim tudo é revertido para a forma original. Vc perguntou como eu fazia... O meu WorkDAO seria o equivalente ao UnitOfWork do Fowler.
E aí tanto o Repositorio quanto o Unit of Work fica acoplado ao DAO? Por exemplo..
Repare que o UnitOfWork é um buffer do DAO , ou seja, as acções são iguais aos do DAO mas elas não acontecem realmente até que ha o commit final. Ele é um DAO com um método commit(). Nessa estrutura realmente o Repositorio tem que ser injetado com o DAO certo, especialmente em operação que manipulam os dados dentro de uma transação. E o UnitOfWork tem que ser injetado com o DAO real Não faz sentido o Repositorio ter um UnitOfWork porque o UnitOfWork é opcional. Num select vc não usa UoW. A ideia seria mais ou menos assim : Nota: a annotaçao @Inject é só para dizer que deve ser injetado. Não é uma especificação de como a injeção deve acontecer. Básicamente significa "obtenha isto de alguma forma"
This message was edited 2 times. Last update was at 29/04/2008 13:03:33
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 13:40:15
|
MauricioAniche
Entusiasta Java
Membro desde: 20/12/2007 18:33:07
Mensagens: 24
Offline
|
Oi Sérgio,
Nesse seu último exemplo, você passando UoWDAO pro repositório, essa interface deve conter também os métodos do DAO, de listagem, e tudo mais, concorda?
Estou com um projeto aqui chamado SmartCA, não me lembro da onde eu baixei, mas é um exemplo de DDD em .NET. Olha a abordagem dele, e me diga o que você acha.
Conseguiu entender? Essa implementação também é bastante interessante, não?
[]'s
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 15:13:38
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline
|
MauricioAniche wrote:Oi Sérgio,
Nesse seu último exemplo, você passando UoWDAO pro repositório, essa interface deve conter também os métodos do DAO, de listagem, e tudo mais, concorda?
sim esqueci de dizer que UoWDAO implementa DAO
Estou com um projeto aqui chamado SmartCA, não me lembro da onde eu baixei, mas é um exemplo de DDD em .NET. Olha a abordagem dele, e me diga o que você acha.
É isso ai. Só achei estranho esta parte :
Se o unitOfWork é nulo o repositorio não faz nada ? .. meio estranho.
Por outro lado, quem chama o método Commit ? Não é o repositorio , certo ?
Logo o repositorio não precisa saber que existe um UoW , apenas o DAO. E o DAO é obrigatorio existir ou dá exception.
É que nesse exemplo em .NET não ha DAO e o UoW faz o papel tanto de UnitOfWork como de DAO.
Eu só acho que é melhor separar as resposabilidades. Caso contrário eu poderia escrever este codigo sem sentido
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 16:44:04
|
MauricioAniche
Entusiasta Java
Membro desde: 20/12/2007 18:33:07
Mensagens: 24
Offline
|
Sérgio,
Essa discussão tá ficando interessante e me ajudando demais!
Só não entendi uma coisa, você falou que tem que separar as responsabilidades, mas você disse que UoWDAO implementa DAO, ou seja, UoW é um Unit of Work e também é um DAO? Você passa o DAO real (que foi injetado) para o UoW.. Não fica meio estranho você ter o DAO na camada de aplicação?
Não é tão casual assim separar as responsabilidades desses dois, né?!
[]'s
Mauricio
This message was edited 1 time. Last update was at 29/04/2008 16:45:03
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 17:11:03
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3433
Offline
|
MauricioAniche wrote:Sérgio,
Essa discussão tá ficando interessante e me ajudando demais!
Só não entendi uma coisa, você falou que tem que separar as responsabilidades, mas você disse que UoWDAO implementa DAO, ou seja, UoW é um Unit of Work e também é um DAO?
ah! mas um DAO não é um UnitOfWork. Essa é a separação. Um Unit of Work tem mais responsabilidades. Ele tem que implementar commit(); É essa responsabilidade que o DAO não tem, nem deve ter.
Você passa o DAO real (que foi injetado) para o UoW.. Não fica meio estranho você ter o DAO na camada de aplicação?
Eu não o "tenho". E ele não está em lado nenhum. Eu apenas preciso de o injetar.
Repare que o uso do UoW como um DAO é um simplicifador. Vc é livre de criar o UoW com a interface que quiser. Contudo, em algum ponto, o DAO real será chamado. Então porque não dentro do commit() ?
Não é tão casual assim separar as responsabilidades desses dois, né?!
Não entendi o que quer dizer com esta frase. Separação de responsabilidade é o dia-a-dia. É o que separa sistemas bem feitos de gambiarras...
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 17:36:46
|
MauricioAniche
Entusiasta Java
Membro desde: 20/12/2007 18:33:07
Mensagens: 24
Offline
|
Sérgio,
Sim, essa é a idéia, nada de gambiarras...
Então vamos ver se eu entendi... O Unit Of Work vai receber um DAO, meu Repositorio vai receber meu UoW. Meu UoW então vai ter que disponibilizar toda a funcionalidade do DAO para o repositorio... Imagine o seguinte caso... Tenho 2 repositorios... Clientes e Pedidos...
Repare que eles tem em comum apenas os métodos de persistência, mas na listagem cada um tem o seu. Vc sugere meu IUnitOfWork ter métodos do tipo FindBy(QueryObject qo), FindByPk(), e coisas do tipo ?
[]'s
Mauricio
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 29/04/2008 17:47:42
|
MauricioAniche
Entusiasta Java
Membro desde: 20/12/2007 18:33:07
Mensagens: 24
Offline
|
Sérgio,
Que é a idéia do NWorkSpace, do Nilsson, correto?
http://www.jaoo.dk/jaoo2006/articles/nworkspace.jsp
[]'s
Mauricio
|
|
|
 |
|
|