Capa de servicio de aplicación que llama a funciones de base de datos. Mala arquitectura?

11

Guión:

  • Pila: Java, Spring, Hibernate.
  • Modelo: Aplicación Cliente-Servidor.
  • Patrón: Modelo-Vista-Controlador (MVC).

Las clases de capa de servicio tienen tres comportamientos:

  1. Algunos servicios tienen la regla de negocios dentro de los métodos y delegan la persistencia a la aplicación. Me gusta:

    EntityManager.save (entidad);

  2. Algunos servicios simplemente llaman a una función de base de datos (pasando parámetros) Como:

    CallableStatement cls = con.prepareCall ("{call databaseFunction (args)}");

  3. Algunos servicios tienen métodos con ambos comportamientos.

Mis preguntas:

  1. ¿Hay algún problema en hacer que los servicios de aplicaciones llamen, directamente, a las funciones de la base de datos? ¿No se considera esto una mala práctica? ¿Cuál sería un modelo de arquitectura aplicable a un proyecto como este?
  2. ¿Hay algún problema en que el comportamiento se mezcle en el mismo servicio? ¿Como transacciones y consistencia?
  3. En el caso del mantenimiento, ¿esta encapsulación hace que sea oscuro para el desarrollador que también debe cambiar las funciones en la base de datos? ¿Cómo evitar esto?
  4. ¿Este escenario ocurre en otras aplicaciones alrededor del mundo o fue solo un error arquitectónico?
linuxunil
fuente

Respuestas:

7

¿Hay algún problema en hacer que los servicios de aplicaciones llamen, directamente, a las funciones de la base de datos? ¿No se considera esto una mala práctica?

Creo que hay Está colocando un conocimiento sobre las partes internas de la base de datos al servicio de la aplicación. Cambiar la base de datos de cualquier manera (cambiar el motor de almacenamiento o incluso cambiar el nombre de un campo o crear un índice) puede requerir que cambie el servicio de la aplicación y eso viola SRP .

¿Cuál sería un modelo de arquitectura aplicable a un proyecto como este?

Ver comentario a continuación.

¿Hay algún problema en que el comportamiento se mezcle en el mismo servicio? ¿Como transacciones y consistencia?

No creo que haya un problema técnico, pero sí uno lógico. Simplemente combina dos enfoques en la aplicación, lo que la hace vaga, menos estructurada y difícil de adaptar a los cambios. Vea los comentarios anteriores sobre la violación de SRP también.

En el caso del mantenimiento, ¿esta encapsulación hace que sea oscuro para el desarrollador que también debe cambiar las funciones en la base de datos?

Claro que si.

¿Cómo evitar esto?

Coloque métodos y funciones que trabajen directamente con la base de datos en un nivel separado de abstracción (ya sea una capa DAO o un patrón de repositorio simple, depende de la complejidad de su aplicación)

¿Este escenario ocurre en otras aplicaciones alrededor del mundo o fue solo un error arquitectónico?

Creo que en nuestro mundo todo sucede;)

Vladislav Rastrusny
fuente
Si lo entiendo correctamente, puede haber un problema técnico en el sentido de que si hay actualizaciones en funciones / procesos almacenados y también a través de un ORM, es muy difícil razonar sobre los estados de una transacción determinada. Si bien la aplicación podría funcionar en su estado actual, un pequeño cambio podría generar algunos problemas realmente grandes. Mi experiencia con Hibernate es que si no dejas que administre todo el conjunto de tablas con las que funciona, tendrás muchos problemas molestos.
JimmyJames
Buena y concisa respuesta. SRP fue lo primero que me vino a la mente la primera vez que miré el código. Algunos compañeros de trabajo dicen que el método no viola SRP debido al hecho de que solo llama a la función de base de datos. Pero algunas de esas funciones seleccionan, insertan y actualizan. Entonces, ¿viola o no el SRP? (¿tal vez esta es otra pregunta para discutir por separado?)
linuxunil
1
+1 para esa línea , creo que en nuestro mundo todo sucede;)
linuxunil
@linuxunil SRP debe respetarse en todos los niveles de la arquitectura. En mi caso, me refería a SRP a nivel de servicio, no a nivel de método. @ JimmyJames Sí. La mayoría de los ORM no funcionan bien con los procedimientos almacenados. Pero a veces el proceso almacenado es necesario.
Vladislav Rastrusny
3

Según lo que dijo, hay una capa de servicio, por lo que el patrón arquitectónico que parece adecuado es la Arquitectura en capas. Referencia adicional

Sí, generalmente es una mala práctica hacer llamadas directas a la base de datos en una capa que no sea de acceso a datos, de esa manera la capa de negocios solo accede a una abstracción de la base de datos.

En cuanto a los comportamientos de mezcla, el uso de algún patrón de diseño como el patrón DAO o el patrón de repositorio podría ayudar a delegar esas responsabilidades mejorando así el código.

Algunas de las ventajas de usar un patrón de diseño y un ORM es la legibilidad de su código, la encapsulación de las responsabilidades, por lo que si su acceso a la base de datos cambia, su capa empresarial no debería cambiar mucho.

J. Pichardo
fuente
No estoy seguro de por qué esto fue rechazado. Esta respuesta recomienda separar el código que se ocupa de diferentes preocupaciones . Se siente como un director de programación aquí ... no estoy seguro de qué es ... Hombre. Si tan solo pudiera pensar en el nombre. +1 BTW
Greg Burghardt
¿No es uno de los principios sólidos?
J. Pichardo
3
No. La "S" en SOLID es la S ingle Principal Responsabilidad (SRP). Pero la separación de preocupaciones, que está recomendando, es una razón válida para separar la lógica de servicio de la lógica de acceso a datos. La otra respuesta de Vladislav menciona al director de responsabilidad individual. Francamente, The SRP y Separation of Precerns van bien juntos, como el vino y el queso.
Greg Burghardt