Separando a lógica de negócios da lógica de banco de dados com transações

11

arquitetura

Temos três camadas em nossa aplicação. Camada de serviço para fornecer uma API externa. Camada BO para nossa lógica de negócios e uma camada DAO para nossa conexão com o banco de dados.

Digamos que toda vez que atualizamos um arquivo, também queremos alterar algo na pasta, por exemplo 'data da última modificação'. Isso precisa ser feito em uma transação. Ou é bem-sucedido e o Arquivo e a Pasta são editados. Ou há uma falha e a transação é revertida para que ambos os objetos estejam no estado anterior.

A ação "Editar uma pasta quando um arquivo é editado" é uma lógica puramente comercial. Então isso significa que ele pertence à camada BO. No entanto, usamos o Objectify em nosso banco de dados, portanto, para iniciar uma transação, precisamos chamar ofy (). Transact (...). Se chamarmos essa função na camada BO, isso interromperá nosso design, pois haverá chamadas específicas do banco de dados (Objectify) em nossa camada Business.

Qual seria uma solução limpa para esse problema?

Serge Hendrickx
fonte
Não é possível FileBOligar FolderBO.edit(newDate)devido ao problema da transação?
Visto
java não tem um equivalente de c # TransactionScope?
Ewan
Em Java, o escopo da transação depende da estrutura que você usa. Em JEE que poderia ser gerenciado pelo servidor de aplicações, mas normalmente é definida e gerida de forma declarativa vía Frameworks como Spring (anotações Via, XML, ...)
LAIV
Preocupe-se menos em tentar tornar diferentes "camadas" do seu aplicativo funcionalmente independentes / ignorantes um do outro. Aceite a ideia de que seu código foi criado para a arquitetura que ele suporta e, em vez disso, concentre-se em tornar esse código bem composto em relação a si mesmo.
Ant P

Respostas:

5

Como você corta suas transações é realmente uma lógica de negócios. Portanto, deixe sua camada DAO fornecer uma API independente da estrutura de banco de dados para o transactmétodo que você mencionou (e provavelmente para coisas como commite rollback). Então você pode usá-lo a partir da sua camada BO sem torná-lo dependente do banco de dados ou da estrutura db.

Doc Brown
fonte
4

Parece que o Objectify foi desenvolvido para transações atômicas (transações do Google Application Engine ). Exigirá que você desenvolva sua própria abstração do Gerenciamento de Transações .

Nesse caso. a abstração continua Como delegar o gerenciamento de transações nas camadas superiores?

A abordagem da @DocBrown me parece a solução mais rápida e limpa para implementar na arquitetura fornecida ( arquitetura em camadas ).

Devido à falta de muitas informações sobre o aplicativo e seu contexto, a solução do Doc também me parece a mais segura.

No entanto, sugiro dar uma olhada no padrão de design do UnitOfWork para a camada de negócios . Eu acho que combina com o gerenciamento de transações proposto pela Objectify .

Resumidamente, o padrão visa encapsular regras de negócios em Transações de Negócios (unidades de trabalho). O padrão permite a herança entre B.Ts e, até agora, também vejo Objectify . Ele ainda suporta composição. Portanto, por composição ou herança, a abordagem permite B.Ts complexos .

Aplicado à arquitetura fornecida, ficaria assim:

FileService -> FileBO : new EditFileTransaction().execute()
                           |-> ofy().transact(...)
                           |--> FileDAO.actionA()
                           |--> FolderDAO.actionA()
                           |-> [ofy().commit(...)|ofy().rollback()]
Laiv
fonte