Separar la lógica de negocios de la lógica de base de datos con transacciones

11

arquitectura

Tenemos tres capas en nuestra aplicación. Capa de servicio para proporcionar una API externa. Capa BO para nuestra lógica de negocios, y una capa DAO para nuestra conexión de base de datos.

Digamos que cada vez que actualizamos un archivo, también queremos cambiar algo en la carpeta, por ejemplo, 'última fecha de modificación'. Esto debe hacerse en una transacción. O tiene éxito y se editan tanto el Archivo como la Carpeta. O hay un error y la transacción se revierte, por lo que ambos objetos están en el estado anterior.

La acción "Editar una carpeta cuando se edita un archivo" es puramente lógica de negocios. Entonces esto significaría que pertenece a la capa BO. Sin embargo, utilizamos Objectify para nuestra base de datos, por lo que para iniciar una transacción necesitamos llamar a ofy (). Transact (...). Si llamamos a esta función en la capa BO, esto rompe nuestro diseño, ya que habrá llamadas específicas de la base de datos (Objectify) en nuestra capa Business.

¿Cuál sería una solución limpia para este problema?

Serge Hendrickx
fuente
¿No puede FileBOllamar FolderBO.edit(newDate)por el problema de la transacción?
Visto el
¿Java no tiene un equivalente de c # TransactionScope?
Ewan
En Java, el alcance de la transacción depende del marco que utilice. En JEE podría ser administrado por el servidor de aplicaciones, pero generalmente se define y administra de manera declarativa a través de Frameworks como Spring (vía anotaciones, xml, ...)
Laiv
Preocúpese menos por tratar de hacer que las diferentes "capas" de su aplicación sean funcionalmente independientes / ignorantes entre sí. Abrace la idea de que su código está construido para la arquitectura que admite y, en cambio, concéntrese en hacer que ese código esté bien compuesto con respecto a sí mismo.
Ant P

Respuestas:

5

Cómo cortar sus transacciones es, de hecho, lógica de negocios. Por lo tanto, deje que su capa DAO proporcione una API db framework independiente para el transactmétodo que mencionó (y probablemente para cosas como commity rollback). Luego puede usarlo desde su capa BO sin hacerlo dependiente de su base de datos o de su marco db.

Doc Brown
fuente
4

Parece que Objectify está diseñado para transacciones de tipo atómico (Transacciones de Google Application Engine ). Le exigirá que desarrolle su propia abstracción de la Gestión de transacciones .

En este caso. la abstracción continúa ¿Cómo delego la gestión de transacciones a las capas superiores?

El enfoque @DocBrown me parece la solución más rápida y limpia para implementar en la arquitectura dada ( arquitectura en capas ).

Debido a que extrañamos demasiada información sobre la aplicación y su contexto, la solución de Doc también me parece la más segura.

Sin embargo, sugeriría echar un vistazo al patrón de diseño UnitOfWork para la capa empresarial . Creo que encaja con la gestión de transacciones propuesta por Objectify .

Brevemente resumido, el patrón tiene como objetivo encapsular las reglas comerciales en Transacciones comerciales (unidades de trabajo). El patrón permite la herencia entre B.Ts y hasta ahora veo, Objectify también. Incluso es compatible con la composición. Así que, o por la composición o herencia, el enfoque permite complejas B.Ts .

Aplicado a la arquitectura dada, se vería así:

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