Acho que você está confundindo o propósito do pattern Repository em DDD. Um Repository simula uma coleção de objetos em memória. Ele sabe retornar objetos baseado em algum critério de busca, persistir um objeto recém criado e atualizar objetos existentes. Métodos como sacar(), depositar() não pertencem a um Repositório e sim à própria Entidade. Para um exemplo de uma interface de Repository: http://dddsample.sourceforge.net/xref/se/citerus/dddsample/domain/model/cargo/CargoRepository.html
A transação como sempre deve ser controlada na camada de Serviço e não no Repository.
[quote=esmiralha]Acho que você está confundindo o propósito do pattern Repository em DDD. Um Repository simula uma coleção de objetos em memória. Ele sabe retornar objetos baseado em algum critério de busca, persistir um objeto recém criado e atualizar objetos existentes. Métodos como sacar(), depositar() não pertencem a um Repositório e sim à própria Entidade. Para um exemplo de uma interface de Repository: http://dddsample.sourceforge.net/xref/se/citerus/dddsample/domain/model/cargo/CargoRepository.html
A transação como sempre deve ser controlada na camada de Serviço e não no Repository.[/quote]
Acho que vc não entendeu a aplicação do pattern nesse caso:
Meu modelo NUNCA vai conhecer o DAO, o DAO vai implementar meu Repository, mas como não conheço o dao, e as ações de persistencia ficarão a cargo do repository, preciso ter as transações em algum lugar, aí que entra minha pergunta.
Eu, quando nao uso spring, ponho as transacoes nos services, que sao quem orquestra toda a operacao. No seu caso eu nao usaria a conta para fazer a transferencia e sim uma outra entidade ou um service mesmo, o qual seria o responsavel pelo saque numa conta e deposito na outra.
Pessoalmente acho que uma conta nao deveria ter a responsabilidade de fazer o deposito/transferencia em outra.
[quote=YvGa]Eu, quando nao uso spring, ponho as transacoes nos services, que sao quem orquestra toda a operacao. No seu caso eu nao usaria a conta para fazer a transferencia e sim uma outra entidade ou um service mesmo, o qual seria o responsavel pelo saque numa conta e deposito na outra.
Pessoalmente acho que uma conta nao deveria ter a responsabilidade de fazer o deposito/transferencia em outra.[/quote]
Mas na minha arquitetura, não tenho service, é só assim:
Se não me engano é nesses casos que você usa uma UnitOfWork. Cria ela no inicio da HttpRequest, injeta nos seus repositorios e comita no final requisição.
Se não me engano é nesses casos que você usa uma UnitOfWork. Cria ela no inicio da HttpRequest, injeta nos seus repositorios e comita no final requisição.[/quote]
Bem isso, mas no caso de um repositório ser uma interface, eu injetaria como? :roll:
Ele abre uma transaction no inico da request e comita no final dela.
Sendo assim, durante a requisição, quando seus DAO fizeram INSERT/UPDATE, você vai ter uma transação rodando.
Desculpe-me por não ter mais detalhes, faz tempo que não programo em Java.
Ele abre uma transaction no inico da request e comita no final dela.
Sendo assim, durante a requisição, quando seus DAO fizeram INSERT/UPDATE, você vai ter uma transação rodando.
Desculpe-me por não ter mais detalhes, faz tempo que não programo em Java.[/quote]
evite transações e implemente transações compensatórias.
vera que o design pode ficar mais simples.
nesse caso: vc quer transferir de A para B.
vc “saca” de A
vc transfere para B
deu problema? vc extorna para A, depois de X minutos – como acontece na prática com um DOC ou TED.
não consegue extornar por problema no banco? vc tem um belo problema.
se o Saca e Transfere forem eventos, a coisa fica bem interessante.
ai perceba o seguinte: imagine que vc sacou 2x 200 reais ao mesmo tempo e vc tem 201 reais na conta. simultaneo mesmo. provavelmente vc vai atender aos dois requests e, quando ficar negativo e o cara náo puder ficar negativo mete uma multa nele.
mas ai vc não quer que isso aconteça. vc vai ter que implementar algum recurso de “lock” para evitar problemas de simultaneidade. Por exemplo, vc pode gerar um Token de autorização por conexao sendo que o Token que vale é sempre um, que seria salvo em uma estrutura de dados xpto. na hora de responder ao saque vc pode ver se o Token é valido e como só pode haver um… no fim tudo é uma questão de “quem quer rir tem que fazer rir”.
[quote=peczenyj]evite transações e implemente transações compensatórias.
vera que o design pode ficar mais simples.
nesse caso: vc quer transferir de A para B.
vc “saca” de A
vc transfere para B
deu problema? vc extorna para A, depois de X minutos – como acontece na prática com um DOC ou TED.
não consegue extornar por problema no banco? vc tem um belo problema.
se o Saca e Transfere forem eventos, a coisa fica bem interessante.
ai perceba o seguinte: imagine que vc sacou 2x 200 reais ao mesmo tempo e vc tem 201 reais na conta. simultaneo mesmo. provavelmente vc vai atender aos dois requests e, quando ficar negativo e o cara náo puder ficar negativo mete uma multa nele.
mas ai vc não quer que isso aconteça. vc vai ter que implementar algum recurso de “lock” para evitar problemas de simultaneidade. Por exemplo, vc pode gerar um Token de autorização por conexao sendo que o Token que vale é sempre um, que seria salvo em uma estrutura de dados xpto. na hora de responder ao saque vc pode ver se o Token é valido e como só pode haver um… no fim tudo é uma questão de “quem quer rir tem que fazer rir”.[/quote]
Entendo e respeito seu ponto de vista, mas… acho que eu só partiria para uma abordagem desse tipo se houvesse uma ótima razão e para mim um design mais simples por si só não seria uma razão boa o bastante, pois a simplicidade está nos olhos do observador (e aos meu olhos eu ainda não tenho certeza que manter checkpoints e undos seria um design realmente mais simples). TPM alto e particionamento seriam boas razões para desprezar o controle transacional oferecido pelo banco e implementar outro na unha.
Também nunca entendi como Event Sourcing se diferencia da simples implementação do pattern Command na camada de Domínio. Preciso ler mais sobre o assunto.
Ainda não consegui resolver essa questão, e estou começando outro projeto que já vi que vou ter o mesmo problema, então quem puder dar uma dica, agradeceria
Pois meu gerenciador de entidades vai ser injetado por um container de DI, mas eu preciso ter a instância dele para controlar minhas transações, esse é meu problema.
Se você gerenciar suas transações nos Repositórios, como vai gerenciar uma transação que envolva mais de um Repositório? Eu acho que transações devem ser gerenciadas por serviços, usando anotações.
[quote=esmiralha]Se você gerenciar suas transações nos Repositórios, como vai gerenciar uma transação que envolva mais de um Repositório? Eu acho que transações devem ser gerenciadas por serviços, usando anotações.
Até onde entendi do tópico, tambem acho isso.
[/quote]
[quote=j0nny]Mas na minha arquitetura, não tenho service, é só assim:
Controller - Entidades - Repositorios [/quote]
Penso que deveria haver serviços ou algo similar neste ponto.