Muchas empresas tienen todavía aplicaciones monolíticas, costosas de mantener y difíciles de evolucionar, pero críticas para el proceso de negocio. Mejorar y modernizar estas aplicaciones no suele ser una tarea sencilla y, por ello, es necesario disponer de una estrategia y los perfiles técnicos adecuados que permitan desmontar el monolito de forma gradual, partiéndolo en trozos funcionales desacoplados “más manejables” e independientes tecnológicamente.
La velocidad de respuesta es una de las máximas en el panorama actual. Existe una necesidad real de dar una respuesta rápida a las nuevas necesidades que se van planteando desde Negocio. Pero, en la actualidad, toda­vía hay muchas empresas que cuentan con aplicaciones legacy desarrolladas a medida, que en muchos casos son las que sustentan su negocio y que no está preparadas para el cambio.

Los principales retos que se suelen encontrar en estos escenarios son:

  • Alto riesgo de afectar al negocio. Las fuertes depen­dencias de código provocan que estas aplicaciones ne­cesiten estrictas pruebas de aseguramiento de calidad. Antes de realizar cualquier despliegue en producción hay que probar toda la aplicación, en muchos casos de forma manual, con independencia de la parte de código modificada.
  • Dificultad de mantenimiento. Normalmente cuen­tan con muchas líneas de código y/o formadas por mu­chos módulos fuertemente relacionados, que dificultan la posibilidad de evolucionar estas aplicaciones.
  • Alto coste. El riesgo y la dificultad elevan el coste de cualquier evolución. Iniciar cualquier proyecto de mejo­ra requiere un elevado esfuerzo de análisis debido a las dependencias. La implementación de la solución suele llevar asociados costes de desarrollo desproporcionados con respecto al contenido de la mejora solicitada.
  • En muchos casos las aplicaciones están desarrolladas con tecnologías obsoletas de las que no existe soporte o es muy complicado encontrar perfiles que puedan evolu­cionar y mantener estas aplicaciones.
  • Todas las situaciones anteriores provocan estrés en los equipos de desarrollo, que deben tener máximo cui­dado con los cambios realizados.
  • Usuarios de negocio afectados, ya que ante nuevas necesidades —pequeñas— reciben tiempos de respuesta elevados e incertidumbre en la calidad de las entregas. Esto merma la credibilidad hacia los equipos de informática.

Los responsables de las aplicaciones —y los CIO— son conscientes de la necesidad de revertir esta situación, pero el alto coste, la falta de presupuesto, el infradimen­sionamiento de los equipos de tecnología e, incluso, el riesgo del cambio suelen poner freno a cualquier iniciativa de mejora.

Hay muchas aplicaciones legacy que son críticas para el negocio, pero que no están preparadas para el cambio

ESTRATEGIA DESDE LA ARQUITECTURA

Hoy en día las arquitecturas de aplicaciones han evolucionado conceptual y tecnológicamente y permiten dar solución a estos escenarios, facilitando que estas aplicaciones ofrezcan una respuesta más ágil frente a las necesidades de Negocio, y a un coste razonable. Hablamos de la eclosión de las arquitecturas basadas en mi­croservicios, acompañadas de tecnologías como el uso de contenedores, plataformas de gestión de contenedores y nubes (públicas, privadas o híbridas) además de otras herramientas “satélite” que generan sinergias.

Pero abordar este cambio no es fácil y tampoco está nor­malizado. De hecho, los equipos de desarrollo quizás no estén preparados para estos nuevos paradigmas. Por este motivo es clave aplicar prácticas de arquitectura que darán soporte al gobierno de este cambio evitando desviaciones en el coste y sorpresas en el resultado final.

El rol de arquitecto de aplicaciones es la persona clave en este proceso. Tiene el objetivo de definir unos principios y una estrategia que garantice el servicio al negocio, ha­ciendo convivir los sistemas actuales y los nuevos.

TECNOLOGÍA

Las arquitecturas basadas en microservicios proporcionan un escenario que resuelve todos los problemas relativos a la evolución y modernización de las aplicaciones monolíticas.

  • Desacoplados e independientes. Cada servicio evoluciona según sus necesidades sin afectar al resto. Esta característica proporciona seguridad a la hora de desplegar un cambio, ya que sólo existe riesgo en el servicio utilizado.
  • Cada servicio tiene su propio repositorio de código y su propia tecnología, permitiendo una mayor flexibilidad al distribuir el trabajo en equipos de desarrollo pequeños.
  • Rendimiento, calidad y alta disponibilidad. Ante cargas de trabajo elevadas, un servicio determinado puede escalar, asegurando la calidad y disponibilidad.

Hay que tener en cuenta que, al convertir un monolito en cientos de aplicaciones, aparecerán nuevos retos desde el punto de vista de operaciones e infraestructura. Por suerte los entornos en la nube proporcionan la tecnología necesaria para poder desplegar estos servicios de forma rápida, escalarlos, supervisarlos y crear pipelines de despliegues automáticos a un coste razonable.

Otras tecnologías como Kubernetes de Google y OpenShift de Red Hat dan un paso más, creando una abstracción por encima de una nube concreta permitiendo orquestar servicios entre diferentes nubes de forma transparente al desarrollador.

Figura 1. La infraestructura de microservicios permite abordar de forma sencilla todas las innovaciones que requiere el actual escenario tecnológico.

MANOS A LA OBRA

Una vez que está clara la arquitectura que se va a implementar es importante establecer una estrategia y un plan para la transición que permita llegar a este objetivo minimizando riesgos y garantizando el objetivo. Esta tarea no es fácil y, con seguridad, necesitará de un proceso de supervisión constante. Por esta razón, es recomendable algunas ayudas o guías que se pueden aplicar:

  • Empezar algo sencillo y transversal a la aplicación. A partir del análisis previo, se debería empezar por el módulo menos crítico y/o aquel con menos dependencias como prueba de concepto. Esto permitiría adquirir experiencia y preparación para el “desembarco” de mi­croservicios, probar y ajustar la nueva infraestructura y definir pipelines de despliegue automatizados. Un buen candidato para empezar puede ser el servicio de auten­ticación.
  • Evitar dependencias hacia el monolito durante el proceso. Es importante no mirar atrás y nunca volver a tener dependencias con el monolito. De esta forma, ante dos módulos del monolito es recomendable realizar un análisis previo y empezar por el que menos dependen­cias tenga.
  • Divide y vencerás. Esta es la fase —ya estamos cómodos con la arquitectura— en la que los macroservi­cios se dividen en microservicios independientes (código y datos). Es útil aplicar patrones o enfoques como por ejemplo DDD (domain-driven design o diseño dirigido por el dominio.

Pero ¿cuándo dejamos de dividir el monolito? Contar con muchos servicios requiere de un elevado nivel de gestión y si se utilizan pocos, existe la posibilidad de encontraremos con minimonolitos. Por tanto, no hay que complicarse. Es recomendable llegar hasta donde se sea capaz de gestionar, empezando de macro a micro, y de forma progresiva. Es posible marcar como un primer objetivo que los módulos más propensos a modificaciones estén desacoplados.

Uno de los puntos clave para empezar este proceso suele ser aplicar SessionLess (no usar la sesión) para las aplicaciones Web.

  • Implementar una interfaz de acceso (API Ga­teway). Habrá que dotar un punto de acceso común a la nueva infraestructura para que el usuario final no perciba los cambios internos. Las herramientas de API Gateway redireccionarán todo el tráfico a los nuevos servicios o, en su defecto, al monolito que se encuentra implantado en la nueva infraestructura. Existen herramientas para este fin como Apigee, Kong, Ambassador, Envoy, Traefik o Gloo.
  • Mejora continua. Una vez aislado el código en servicios ya se puede iniciar un proceso de optimización y refactorización, extrayendo nuevos servicios y aquellas funcionalidades que son transversales, mitigando de forma paulatina la deuda técnica. Es un buen momento para “limpiar” el código, eliminando aquellas partes prescindibles.

Una vez aislado el código en servicios ya se puede iniciar un proceso de optimización y refactorización

NUESTRA EXPERIENCIA

Recientemente, en PFS Tech, hemos abordado un proyecto de este tipo, aplicado a una solución propia desarrollada en Java y con más de un millón de líneas de código. El resultado ha sido satisfactorio, pero, durante un tiempo, los nuevos servicios han tenido que convivir con el monolito.

Para afrontar esta convivencia hemos tenido que considerar otras estrategias que nos han permitido ir apagando una aplicación e ir encendiendo la nueva:

  • Refactorizar con API el monolito. De forma interna, el monolito se prepara para desacoplarse en aquellos puntos donde exista fuertes dependencias.
  • Duplicidad de servicio. El usuario percibe la existencia de dos aplicaciones y salta de una a otra. Es importante utilizar tecnologías como single sign on para dar solución a este contexto.
  • Mediante esta estrategia, los usuarios siguen utilizando la misma aplicación monolítica y se crean dependencias desde los módulos del monolito a los nuevos servicios.

El resultado: ya no tenemos un monolito sino diferentes servicios que seguimos evolucionando. Cada servicio es una “aplicación” independiente y, gracias a esto, nos podemos permitir el lujo de aplicar todas aquellas ideas e innovaciones que teníamos reservadas en nuestro backlog para incorporar al producto, pero que no era viable abordarlas debido a la complejidad técnica.

En la actualidad disponemos de una aplicación que no nos gusta denominar como “acabada”, porque realmente ahora es cuando estamos empezando a evolucionarla con seguridad, agilidad y sencillez, mejorando el aporte de valor al negocio.

 

Autor: Gonzalo Estellés, Director de Arquitectura e Innovación en PFS Tech