Conecta con nosotros

Opinión

Journey to Cloud Tales VI: la coexistencia ¿una Máquina Diabólica?

Publicado el

A lo largo de los capítulos anteriores he ido introduciendo la problemática de acometer un proyecto de modernización complejo de forma iterativa. Un escenario que demanda establecer una coexistencia en las iteraciones entre partes del sistema modernizado y las que aún permanecen en el sistema original, y me alegra decir que, tras consultar a varios modelos de Inteligencia Artificial Generativa, todavía la experiencia y el punto de vista humano siguen aportando aspectos de interés.

Esta coexistencia fue denominada con gran éxito “Máquina Diabólica”, apodo que le dio la directora de un  proyecto al ver el diseño de arquitectura que hicimos para comunicar partes de una aplicación movida a la cloud con 200 aplicaciones aún en un mainframe. Por cierto, es un apodo a evitar en ciertas reuniones.

Pero no por suavizar el nombre el reto disminuye o desaparece. Y es otro de los aspectos curiosos en los grandes proyectos de modernización. Normalmente se ignora su complejidad, no se piensa en ella cómo arquitectura y por tanto se afronta con soluciones parciales, ineficientes y redundando en incrementos del coste, riesgo y plazos, lo que a veces  deriva en el fracaso del propio proyecto.

¿Big-bang o proyecto iterativo?

La primera pregunta que debemos hacernos es: ¿para qué necesito coexistir? La respuesta es fácil, si puedo hacer un big-bang no lo necesito; pero si acometo el proyecto de modernización de forma iterativa, permitiendo obtener beneficios de forma paulatina, tendremos que ir comunicando de alguna manera las partes modernizadas con las que siguen en su estado original.

¿Integración o coexistencia?

Es importante distinguir entre integración y coexistencia. La integración debe pensarse para comunicar de forma continua una aplicación con otros sistemas y aplicaciones, al tiempo que la arquitectura de coexistencia es el mecanismo para comunicar de forma transitoria entre componentes modernizados y originales mientras se finaliza un proyecto de modernización iterativo.

Aunque se utilicen los mismos mecanismos, si queremos desconectar sistemas al final del proyecto ambas arquitecturas deben estar separadas por diseño y construcción. De hecho, una arquitectura de coexistencia bien diseñada debe desaparecer por sí misma una vez finalice el proyecto de modernización.

¿Por qué es tan complicada la coexistencia?

A priori parece relativamente sencillo. Una aplicación tiene interfases, en cada iteración de modernización se generan componentes aplicativos que también tienen interfases, es tan simple como llamar de un sitio a otro. Pero empecemos a complicarlo…

En artículos previos, ya comentamos el elevado número de componentes y el acoplamiento existente entre los mismos de aplicaciones legadas. Esto complica sobremanera distinguir los componentes que forman parte de cada aplicación y, más aún, dónde están las conexiones con el resto de las aplicaciones. Pero imaginemos que hemos sido capaces de identificar ambos aspectos; conocemos el contexto de la aplicación a modernizar y dónde se relaciona con las demás.

Esto plantea un problema menor, ya que, en las aplicaciones tradicionales se utilizan protocolos de comunicación muy eficientes como SNA, RMI y RPC. Sin embargo, en las aplicaciones modernas, la comunicación se basa en la exposición y consumo de funcionalidades utilizando protocolos basados en otros estándares como HTTP y GRPC.

Además, para evitar crear nuevos monolitos, hemos diseñado las aplicaciones nuevas con las mejores prácticas de diseño y desarrollo modular, por tanto, hemos evitado la consistencia estricta entre bases de datos diferentes. Pero cabe preguntarse:

  • ¿Cómo combino con una aplicación donde el sistema proporciona consistencia estricta por defecto?
  • ¿Qué pasa con los cientos / miles de programas que llaman a programas que ya están en otra tecnología y han desaparecido de la plataforma origen?
  • ¿Qué hago con los datos cuando el nuevo modelo de datos ha variado mucho?
  • Habiendo reducido / eliminado los procesos masivos nocturnos, ¿cómo garantizo que un proceso masivo a las 3:00 am tiene disponibles los datos del nuevo sistema que necesita para su procesamiento?

¿Cuándo aplica la coexistencia?

Esta pregunta por sí misma está en la base del éxito o el fracaso de muchos proyectos. Ilustrémoslo con el caso paradigmático de las direcciones. Tradicionalmente, éstas se almacenaban en un string de caracteres; sin embargo, actualmente se almacenan normalizadas y separadas por sus campos. Está claro que cuando se pasen datos desde el sistema inicial al destino, algo se tendrá que ocupar de dividir el string en sus diferentes campos:

Y lo mismo ocurre a la inversa, al devolver datos al sistema origen, algo tendrá que agrupar los datos en el string que espera el sistema origen.

¿Cuándo hay que hacer este cambio? Pues si reflexionamos un poco, observaremos que ese cambio deberá hacerse en múltiples momentos y escenarios:

  • Durante la migración de datos (y en todas las pruebas previas de ese proceso de migración).
  • En las llamadas transaccionales entre componentes de ambos sistemas (y además en ambos sentidos).
  • Con los procesos masivos de tratamiento de datos que intercambien información.
  • Al implementar los sistemas de replicación de datos.
  • En los procesos de pruebas en paralelo de los sistemas.
  • Muy recomendable, en sistemas de auditoría que permitan validar que el sistema funciona.

Si se hace la misma transformación tantas veces, ¿por qué se suele codificar de manera diferente en cada uno de esos subsistemas? Además del elevado coste, es una fuente de errores que ha encontrado un sitio donde ocurrir.

¿Hace falta una arquitectura?

Buena pregunta. Una opción es ir integrando punto a punto allí donde se necesita. Esto sería una buena noticia para el equipo encargado del mantenimiento futuro, pero pésima para el cliente; ya que, además del elevado número de errores de calidad de datos que se detectarán, impedirá desconectar el sistema original y demandará un equipo solo para mantener toda la maraña de integraciones.

Principios de una arquitectura de coexistencia

Dada su importancia y complejidad, la experiencia enseña que deben considerarse una serie de principios fundacionales cuando se diseña una arquitectura de coexistencia:

  • No por evitar el problema éste va a desaparecer. Por tanto, hace falta una arquitectura y, como tal, debe ser estimada, diseñada y construida.
  • Principio básico: la búsqueda de la simplicidad, aunque para lograrlo haya que renunciar a ciertas funcionalidades.
  • Segundo principio básico: Solo debe existir un maestro de datos, inicialmente el origen, posteriormente el destino, el resto serán copias.
  • Debe diseñarse una arquitectura efímera separada del origen y destino que permita su desmantelamiento una vez finalizado el proyecto.
  • Visión clara y documentada del mapeo de datos y la transformación entre origen y destino que permita realizar siempre la misma transformación ante la misma situación.
  • Evitar siempre realizar modificaciones específicas en el sistema modernizado; en caso de ser necesario, considerar modificar en el sistema origen, ya que así se garantizará el decomisionamiento de la arquitectura de coexistencia generada.

Componentes

Si es tan difícil, ¿cómo debe construirse?, ¿qué componentes se necesitan? Aunque busquemos la simplicidad máxima, en el caso más complejo existen una serie de componentes básicos a considerar:

  • Inventario del mapa de aplicaciones que permita conocer los componentes de cada aplicación y, sobre todo, las relaciones entre ellos.
  • Uso del concepto grifo o discriminador, el famoso strangler pattern que permite redirigir el tráfico de la aplicación entre el antiguo y el nuevo sistema.
  • Sistema de mapeo que recoja la correspondencia entre los modelos de datos antiguos y nuevos, así como las reglas de transformación a aplicar.
    • Si es posible, efectuar una codificación única de esta transformación que pueda ser invocada desde cada punto donde se precisa la coexistencia.
  • Mecanismos de comunicación transaccional (APIs, eventos, etc.).
  • Replicación de datos para las migraciones; también, y por motivos de rendimiento, suele ser recomendable la habilitación de copias de datos en modelo lectura (patrón CQRS).
    • Este aspecto demanda la existencia de conectores a bases de datos que permitan detectar cambios en los mismos (normalmente a los sistemas de logs de estos) propagando los cambios entre los modelos de datos.
  • Habilitación de un sistema de pruebas en paralelo que permita verificar resultados y comparar entre ambos sistemas. Muchos de los sistemas a modernizar manejan cantidades económicas o información sensible, por tanto no es admisible que los resultados del nuevo sistema tengan porcentajes de éxito menores al 100%.
  • Basados en estos sistemas de paralelos, no es obligatorio pero si muy recomendable mantener mecanismos de auditoría que permitan saber si todo va bien y, sobre todo, detectar si algo ha ido mal y ayudar a la detección inmediata de la causa raíz del problema. De hecho, hay historias de terror reales sobre el tiempo que se ha tardado en detectar problemas en sistemas de facturación o de cobros a clientes…

Bueno, ya tenemos nuestra arquitectura de coexistencia, hemos desarrollado en paralelo el nuevo sistema y las pruebas han sido un éxito. Ha llegado el momento de desconectar el sistema antiguo y empezar a trabajar con el nuevo pero, como dice el chiste, “apágalo tú que a mí me da la risa”.

Firmado: José María Silva Bravo (Application Engineering Services – Practice Leader SPGI, IBM Consulting)

Lo más leído