Al hilo de este artículo en el que se plantea si un microservicio debe tener su propia base de datos, me viene a la cabeza una reflexión sobre el principio de autonomía de SOA que dice así:
Para que un servicio pueda llevar a cabo sus funciones de manera consistente y confiable, la lógica se ejecuta dentro del mismo debe tener un grado significativo de control sobre su entorno y recursos.
De la teoría a la práctica
Recuerdo que cuando lo vi por primera vez no me dejaba de sonar como algo un poco extravagante ¿cómo iba un servicio por si mismo a tener completa autonomía sobre el entorno sobre el que se ejecuta?. Se daba por descontado que cualquier software de este tipo iba a utilizar una base de datos de compartida con otros, en un servidor de aplicaciones igualmente compartido que se ejecutaría sobre una máquina sobre la que se ejecutan estos y otros procesos. En resumen, más bien se consideraba como un principio que se quedaba poco más o menos en el plano teórico.
Pero en los últimos tiempos, con el auge del concepto de microservicios, este principio ha tomado una especial relevancia. Y es que al día de hoy, gracias al cloud y a la contenerización (como Docker) podemos tener un servicio con completa autonomía con un coste y esfuerzo bastante bajo.
Gracias a la contenerización que se puede obtener hoy en día, desplegado en un cloud, podemos tener una «maquina» únicamente para un servicio. Por fin, en la práctica podemos cumplir con el principio de autonomía que forma parte de la base de la orientación a servicios.
Principio de autonomía también dentro del propio servicio
Pero yo diría que el concepto de autonomía va incluso más allá… no sólo en lo relativo a los recursos de infraestructura que necesita un servicio para ejecutarse. Habría que aplicarlo también como concepto en el propio código fuente, aunque sea dentro de una sola aplicación, y me explico…
Desde el momento mismo en que aprendemos programación, se nos dice que un trozo de código no puede estar repetido, por aquello de la mejora de mantenimiento. Que tener repetido el mismo código en varias partes de una aplicación es una mala práctica… y por eso diseñamos un software para que tenga clases comunes reutilizadas en todo el código, ya sea mediante la herencia, la delegación, como una paquete de utilidad, etc. etc.
Evidentemente, el mantenimiento mejora porque cuando este código cambie únicamente hay un sitio donde cambiarlo… pero como todo, tiene su contrapartida… y es que nuestro código será más frágil. ¿Que pasa si se cambia esta parte común y ampliamente reutilizada y tenemos un error? pues toda la aplicación se vendrá abajo.
Si pensamos en que nuestra aplicación, por ejemplo, de gestión de clientes tiene, digamos, 25 servicios y todos usan una misma clase común, por ejemplo, la clase padre de Cliente, un sólo cambio con un bug nos echará por tierra los 25 servicios. Ahora bien, si duplicamos el código y cada servicio tiene su propias líneas de código de uso exclusivo (a costa de dificultar el mantenimiento global de la aplicación), es evidente que un problema en una servicio no afectará al resto.
¿Podríamos llamar a esto autonomía de un servicio intra-aplicación? Tal vez… pero en algún caso concreto y tipo de aplicación, yo dormiría más tranquilo teniendo el código un poquito repetido, con unos servicios más autónomos respecto a sus hermanos de aplicación.
17/01/2016 at 23:34
El tema de la autonomía de los servicios es legítimo, y está bien presentado en esta sesión. Sin embargo, no estoy seguro que las recomendaciones que se hacen sean la única forma de abordar este problema.
Un servicio que tiene un problema de autonomía es un servicio que maneja una cantidad de datos con un alto nivel de re utilización. Es cierto que la solución pasa por asignar un servidor (físico o virtual) al servicio, pero no sé como esto afecta el régimen de licenciamiento del administrador de base de datos, puesto que, claramente, será una base de datos individual la que tendrá que correr en este servidor. ¿Será que los nuevos administradores de bases de datos pueden operar como servicios, y los datos están en otros servicios distribuidos? Veo que me he mantenido alejado de las bases de datos demasiado tiempo.
Pero los temas del código y de la duplicación de código -aunque sea mínima- como solución para enfrentar los problemas de manejo de versiones de servicios – porque de esto se trata, en final de cuenta, el manejo de versiones – merecen algo más de consideración, me parece.
Resulta que hay una cantidad de patrones de diseño SOA que permiten abordar estos aspectos y evitar así el problema de desnormalización. Solo los voy a citar sin describirlos: Capa de Utilitarios Transversales(267), Punto de entrada al inventario(260), Versionamiento canónico(286), Fachada de servicios (333), Implementación redundante(345), Replicación de datos (350), Validación parcial (362), Desnormalización de contrato(414), Contratos concurrentes (421), Envoltura de herencia (441), File gateway (457), Cambios compatibles (465), Identificación de versiones (472), Notificación de terminación (478), Service refactoring (484), Decomposición de servicios (489), Capacidad proxi (497), Capacidad descompuesta (504), Capacidad distribuida (510) y Autonomía de composición (616).
¿No hay aquí una cantidad de patrones de diseño que podrían evitar de considerar duplicar código?
Cordialmente.
30/01/2016 at 13:52
Completamente de acuerdo, con el comentario anterior con respecto al tema de la duplicidad del código. Ya que una cosa es design-time y otra runtime. Otra cosa es que vayamos a un modelo donde yo tenga mis propias instancias de un servicio que este replicado, pero no su código. Simplemente que este replicado para que no haya esa dependencia con un servicio sobre utilizado, pero eso ya es una práctica actual.
30/01/2016 at 13:54
Ya decía en el post que no se consideraba una buena práctica, pero estaremos de acuerdo que reutilizar un código a lo largo de varios servicios… Un solo fallo en ese punto hará que fallen todos…
30/01/2016 at 14:29
Sin duda, pero también es verdad que replicar el código aumenta las posibilidades de que alguno de ellos falle y dificulta el mantenimiento y reporte de bugs. Es más facil detectar errores en algo que usan miles de personas que algo que usan tres.
Pero vamos en principio con un modelo de microservicios, estaríamos hablando más de reutilizar un servicio más que de su código.
30/01/2016 at 15:09
Estamos de acuerdo. Mi idea era cuestionar de alguna manera una regla establecida… A veces es necesario hacerlo 😉
30/01/2016 at 21:41
Completamente de acuerdo, Muchas veces se dan por verdades absolutas cosas que se asentaron en entornos tecnologicos tan diferentes al actual que cometemos errores de perpetuarlas simplemente por no cuestionarlo. Un placer leerle 🙂
30/01/2016 at 22:43
Gracias a ti por tus comentarios 🙂