Monolitos a la sombra del micro

Compartir por correo electrónico

Los microservicios están surgiendo hoy en día por la sencilla razón de que las aplicaciones monolíticas son complejas de mantener, evolucionar y administrar. Por ello, era necesario segmentar nuestro monolito en multitud de fragmentos. Estos fragmentos permiten una evolución técnica y/o funcional mucho más sencilla.
Esta evolución es ya habitual en el ámbito del backend. Sin embargo, el problema del monolito no está reservado exclusivamente al backend, también se puede encontrar en las tecnologías frontales. Las SPA se han extendido cada vez más con la ayuda de frameworks como Angular, React o incluso Vue, pero siguen siendo monolitos. Aunque una multitud de herramientas dentro de los frameworks nos permiten mejorar la arquitectura y optimizar la segmentación, el código sigue siendo mutualista. Por lo tanto, es necesario, para acercarse lo más posible a los microservicios, segmentar y evolucionar hacia los microfrontales.


Los microservicios han aparecido en las arquitecturas de backend con el objetivo de segmentar el código en una multitud de aplicaciones autónomas e independientes. Este enfoque permite mejorar la escalabilidad y la mantenibilidad de una aplicación.
En el ámbito del Frontend, las prácticas van en la misma dirección con el uso de módulos y bibliotecas que pueden reutilizarse en toda la aplicación. Esta segmentación tiene ventajas tanto a nivel técnico como organizativo. En efecto, esta práctica ofrece a un equipo la posibilidad de gestionar una empresa lógica de la A a la Z. Desde la gestión de la base de datos, pasando por la exposición de los datos (Microservicio), hasta la implementación de una interfaz gráfica (Frontend). De este modo, la evolución de una funcionalidad concreta sería dominada por un único equipo que se centraría en la integración de esa funcionalidad y no en la integración de esa funcionalidad en una arquitectura determinada.
Actualmente, si estudiamos todas las soluciones disponibles en el mercado, nos encontramos rápidamente con las tecnologías de Web Components con Webpack 5 y el uso de "Module Federation". Estas prácticas parecen ser las más adecuadas para ceñirse a un enfoque de microfrontales, tanto desde el punto de vista técnico como de la experiencia del usuario.

Evolución del monolito a los microservicios

Como podemos ver hoy en día en nuestras líneas de productos, el desarrollo de aplicaciones se hacía a través de una arquitectura monolítica que estaba compuesta por todos los ladrillos de una aplicación (la capa de acceso a la base de datos, la lógica de negocio y la presentación).
Como se ha mencionado anteriormente, la arquitectura de una aplicación ha evolucionado, o más bien se ha segmentado, para optimizar su mantenimiento y evolución. La figura 1 que aparece a continuación pone de manifiesto esta evolución y orienta nuestro pensamiento para los Microfrontends.

Figura 1. Evolución de las arquitecturas aplicativas

Monolito

Todos los ladrillos que componen una aplicación se encuentran en la misma aplicación. El acceso a la base de datos, la lógica de negocio y la interfaz de usuario están agrupados. Durante el mantenimiento o el desarrollo, todos los ladrillos deben volver a desplegarse.

Arquitectura Backend / Frontend

La segmentación del backend y el frontend apareció con la llegada de las "peticiones xml http", que permitieron la manipulación y comunicación de datos mediante el protocolo http. El frontend es ahora autónomo y el backend sigue estando compuesto por la lógica empresarial/técnica y el acceso a los datos.

Arquitectura de microservicios

La segmentación del monolito en el backend con el uso de Microservicios ha permitido definir una aplicación por dominio de negocio y así distribuir mejor las cargas en los equipos de desarrollo (un dominio asociado a un equipo, por ejemplo). Nos encontramos pues con un conjunto de aplicaciones autónomas e independientes capaces de proporcionar un único servicio asociado a su lógica de negocio. Con este tipo de arquitectura, vemos la aparición de API Gateways que permiten redirigir y asegurar las peticiones entrantes.

¿Y el monolito en la parte delantera?

Por último, cuando observamos con más detenimiento nuestra arquitectura de microservicios, nos damos cuenta de que esta segmentación sólo se ha realizado en el backend. De hecho, el backend se beneficia de una buena segmentación en dominios de negocio, expone una API en consecuencia y se vuelve completamente independiente. Sin embargo, la aplicación del frontend sigue siendo muy coherente. Por tanto, el problema del monolito sólo se ha resuelto parcialmente. Este problema es aún más visible en las grandes aplicaciones con una escalabilidad que va bastante bien en el backend pero que es más problemática en el frontend (obligación de retomar y volver a desplegar toda la aplicación en el frontend).
Aparecen problemas técnicos:

  • Una evolución desde el punto de vista de la funcionalidad en el backend equivale a instanciar una nueva aplicación (Microservicio) pero en el frontend, equivale a añadir una funcionalidad entre otras. Esto significa que acabamos desplegando una aplicación cada vez más consecuente (mayor riesgo de crash).
  • La migración es una parte integral de nuestro trabajo actual, es necesario pensar en los usos futuros y en la posibilidad de obsolescencia de las tecnologías actuales. Cuanto más compacto y estrechamente vinculado esté nuestro código/arquitectura, más compleja será la evolución.
  • La siguiente cuestión se deriva directamente de la anterior, con la dificultad de encontrar desarrolladores dentro de unos años, cuando la tecnología esté obsoleta.

Al igual que con el backend, teníamos que encontrar una arquitectura y una forma de desacoplar nuestra aplicación front-end en varios dominios independientes y reutilizables. Esto garantizaría una mejor mantenibilidad e integración en diferentes aplicaciones.
La componentización permitía particionar funcionalidades que cumplían una misma función y ello con independencia del entorno en el que se integraran. El desarrollo correría a cargo de un único equipo de desarrollo responsable de toda la cadena de negocio (Microfrontend API). Esto nos lleva a otra ventaja, que es la capacidad de modular una aplicación en función del cliente. En efecto, si cada componente de negocio es autónomo, independiente y puede integrarse en cualquier entorno, es muy posible agregar estos componentes para hacer una aplicación.

Figura 2. Evolución hacia una arquitectura micro-frontend

Por último, desde el punto de vista del usuario, la aplicación será una agregación de componentes compartidos, cada uno de los cuales gestiona un dominio empresarial concreto. El "contenedor" será, pues, el garante de la orquestación de todos estos componentes (véase la figura 3).

Figura 3. Arquitectura del microfrontón desde la perspectiva de la interfaz de usuario

Tener la capacidad de dividir nuestro frontend en varios Microfrontends nos está llevando cada vez más hacia una división de los equipos de desarrollo por dominio de negocio. Esto permitiría al equipo encargarse de la lógica de negocio de la A a la Z (del Microservicio al Microfrontend). Por último, los integradores de aplicaciones frontales ya no tendrán que conocer a fondo el dominio de los microservicios. Sólo tendrán que integrar el componente creado por el equipo de Microservicios.
Cuando el microservicio evolucione, el componente adaptado será desarrollado al mismo tiempo por el mismo equipo (pero probablemente por diferentes expertos técnicos) y estará así listo para ser integrado rápidamente por todas las aplicaciones cliente.

Ventajas y desventajas

Aunque el núcleo del problema era la dificultad de evolución y mantenimiento dentro de un frontend monolítico, también se notaba que en el desarrollo, los equipos del final de la cadena tenían que conocer todos los microservicios con sus limitaciones, restricciones, etc.
Ahora los equipos se organizan en torno a dominios de negocio y se encargan del desarrollo integral de un servicio. La ventaja es que no tienen que preocuparse del entorno en el que se integrará todo. Pueden concentrarse únicamente en sus áreas de negocio. En cuanto a los equipos de integración, su único objetivo es integrar una aplicación con una multitud de Microfrontends. Ya no tienen que preocuparse por las cuestiones de negocio. Por último, de forma más general, hace que un equipo sea más especializado y evita que sea generalista.
Una de las desventajas que se pueden observar con este tipo de arquitectura es la necesidad de un conocimiento técnico más amplio. En efecto, cada equipo empresarial será responsable del desarrollo tanto del Microfrontend como del Microservicio.

En la práctica...

La web actual nos proporciona un enorme número de herramientas para crear nuestras aplicaciones. Sin embargo, la elección de una tecnología o un framework se basa principalmente en la necesidad, el tiempo de entrega o incluso el presupuesto. Cuando hablamos de Microfrontend, distinguimos dos categorías de soluciones: las aplicaciones que compartirán el mismo entorno de ejecución y las que no.
La gran mayoría de las aplicaciones Frontend que se desarrollan hoy en día son aplicaciones que dan un entorno de ejecución compartido para garantizar el mejor resultado para el desarrollador pero también para el usuario.

Entorno de ejecución independiente

Las aplicaciones que siguen este patrón tienen la posibilidad de garantizar una separación clara y precisa del resto de la aplicación. Aunque es beneficioso por un lado, tiene desventajas, especialmente cuando se trata de la comunicación con el mundo exterior. Sin embargo, desde el punto de vista del usuario, el Microfrontend aparecerá como un ladrillo (más o menos integrado) de la aplicación.

Iframes

Este es probablemente el concepto más conocido de todos, los iframes tienen la capacidad de ejecutar una aplicación web dentro de otra. El usuario ve una sola página pero la separación técnica está ahí, demasiado.
Esta herramienta tiene, como ya se ha dicho, la capacidad de hacer cohabitar varias páginas/aplicaciones, pero conlleva muchos inconvenientes. La comunicación de datos dentro de una aplicación es un criterio importante para que una interfaz sea lo más "amigable" posible. En el caso de un iFrame, la comunicación entre marcos es más que limitada y la integración de varios Iframes sigue siendo superficial desde el punto de vista del usuario. La última desventaja, que podría ser la mayor, es la gestión de CORS, que se vuelve compleja.
Por último, el iFrame es una herramienta bastante anticuada hoy en día y que responde a viejos problemas. Este enfoque se utiliza para una integración puramente estática de una página, completamente sellada de su entorno de ejecución.

Micro Apps

En el caso de las micro apps, la separación es menos clara que en el caso de los iFrames, pero sigue estando presente con el uso del enrutamiento de aplicaciones para servir a un Microfrontend u otro. En este caso, nos acercamos a una segmentación por dominio de negocio. Ejemplo:

Sin embargo, esta práctica implica la implementación de un hub que permita proponer al usuario y redirigirlo al Microfrontend adecuado. Esto permite acercarse al máximo a los microservicios con segmentación por dominio de negocio, pero requiere una buena gestión de la transferencia de identidades (autenticación, preferencias, etc.). Además, la comunicación entre los microfrontales y su conocimiento mutuo sigue siendo complicada.
Aunque esta solución es la que más se acerca a nuestra visión de los microfrontales, dista mucho de ser satisfactoria en la actualidad. Sobre todo desde el punto de vista del usuario, que sufrirá una experiencia algo confusa.

Entorno de ejecución compartido

Cuando nuestra aplicación ofrece un entorno de ejecución compartido, todos los recursos están disponibles para todos los componentes de la aplicación. Hablamos entonces de Microfrontend como componentes de distinto tamaño que se integran en la misma aplicación. Esta segmentación por componentes es tan visible en el lado del usuario como en el lado técnico.

Componentes de la web

Los Web Components son bloques de código que engloban la estructura interna de los elementos HTML, incluidos CSS y JavaScript, y permiten utilizar el código en cuestión en el lugar deseado en sitios y aplicaciones web.
Pueden integrarse en una aplicación del mismo modo que los actuales bloques que ofrece HTML (div, input, etc.). Con los componentes web, tenemos la posibilidad de crear ladrillos HTML/CSS/JS que cumplen una función precisa y pueden integrarse en cualquier aplicación.
La web es hoy en día un campo que evoluciona muy rápido, cada mes salen nuevos frameworks y librerías y es difícil hacer una elección en esta masa de herramientas. Los componentes web están saliendo al mercado para garantizar la durabilidad de nuestro desarrollo con encapsulación JS/CSS y soporte W3C. La comunicación entre componentes se simplifica con el sistema de "eventos". La idea aquí no es detallar el funcionamiento de los componentes web, sino que la armonía entre los componentes web se rige por una "aplicación base" que lo orquesta todo.
Tenemos una solución real que es sostenible y nos permite optimizar nuestra aplicación. Sin embargo, un microfrontend no puede reducirse a un componente. Está asociado a un dominio de negocio y, por tanto, a una lógica de negocio, a llamadas REST, a transformaciones de datos, a varias interfaces, etc. Sería reductor decir que un micro-frontend es un componente. Este problema ha sido resuelto por los frameworks javascript.

Marco Javascript

Los frameworks Javascript nos permiten crear componentes más complejos con servicios, integrados en un módulo que a su vez están asociados a un dominio de negocio. Podemos citar por ejemplo Angular, React, o VueJS por los más conocidos. Estos frameworks nos permiten segmentar nuestra aplicación en multitud de módulos correspondientes a los dominios de negocio de los microservicios.
Tenga en cuenta que los frameworks modernos utilizan la tecnología de Web Components. Para compartir componentes complejos, ésta es la solución más eficaz, tanto a nivel de desarrollo como de UX. Es posible integrar diferentes módulos de forma transparente para el usuario y gestionar los flujos de trabajo para guiarle en sus tareas.
A título indicativo, es posible hacer cohabitar varias SPA de diferentes marcos utilizando una herramienta como "SingleSpa".

Webpack 5 : Federación de módulos

Webpack es un agrupador de módulos estáticos bien establecido para las aplicaciones modernas de JavaScript. Tiene más de 57.000 estrellas en GitHub y más de 13 millones de descargas semanales en el registro npm. Lanzó la versión 5 el 10 de octubre de 2020, que trae una serie de cambios, incluyendo una nueva característica: Module Federation.
La Federación de Módulos permite que varios componentes web (construidos con webpack) trabajen juntos. Una aplicación puede ejecutar dinámicamente código de otro bundle o build. Esto es un renacimiento para el mundo de los microfrontales.
Cada build de webpack puede ser un host, que es un contenedor para cargar otros builds. También puede ser visto como un remoto, que es un micro-frontend para cargar. Cada aplicación puede ser un remoto y un anfitrión, consumible y consumidor de cualquier otro módulo federado en el sistema.
Además, la Federación de Módulos no necesita necesariamente cargar el punto de entrada principal o toda una aplicación. Sólo necesita cargar el código necesario, que son unos pocos kilobytes de código.
De este modo, cada aplicación tiene la posibilidad de trabajar de forma autónoma e independiente, ya que es, ante todo, una aplicación completa, pero también puede empaquetarse e integrarse en cualquier otra aplicación.
Este enfoque permite referenciar partes del programa que aún no se conocen en el momento de la compilación. Estos pueden ser micro-frontales autocompilados. Además, uno de los puntos importantes de la Federación de Módulos es la posibilidad de compartir bibliotecas entre los distintos microfrontales. Esto reduce considerablemente el tamaño de nuestros paquetes y de toda nuestra aplicación.

Aplicación

El shell de nuestra aplicación puede ser visto como el punto de entrada u orquestador de todos los micro-frontends incrustados en nuestra aplicación. En última instancia, es el anfitrión y los micro-frontales los remotos. La Federación de Módulos permite (Figura 4) compartir librerías entre varios micro-frontends. Podemos distinguir cuatro aplicaciones Angular que comparten la misma pila de bibliotecas, incluyendo Angular.
Con este enfoque, podemos ver que es fácil hacer cohabitar varios microfrontales de diferentes frameworks. De hecho, Webpack5 se encarga de empaquetar nuestros diferentes remotos en componentes web, lo que simplifica mucho su uso.
Es decir, un remoto también puede ser un anfitrión al albergar otros microfrontales (Figura 4).
En la figura siguiente, podemos ver un mecanismo de enrutamiento que permite cargar los distintos microfrontales. Aquí también es posible cargarlos dinámicamente con lazy loading para reducir al máximo el bundle al cargar la página.

Figura 4. Lógica de los microfrontales según la federación de módulos de Webpack 5

Webpack 5 nos permite proponer claramente una solución para los microfrontales acoplando los componentes web a la compartición de bibliotecas. Tenga en cuenta que Angular o React son frameworks de javascript que ya integran Webpack en su pipeline de empaquetado. La federación de módulos es por tanto una característica disponible en estos dos frameworks.

Conclusión

Con frameworks de JavaScript como React y Angular, los desarrolladores pueden definir elementos web reutilizables. Sin embargo, estos frameworks utilizan otro estándar que, en muchos casos, impide la reutilización de prácticos fragmentos de código en diferentes proyectos. Los Web Components, componentes HTML reutilizables e independientes del framework, ayudan a remediar la situación.
Sin embargo, como hemos visto, el uso de componentes web en bruto no permite proponer componentes complejos con una verdadera lógica de negocio detrás. La llegada de Webpack5 con funcionalidades como Module Federation permite acoplar los componentes web y el uso de frameworks javascript.
Por último, la mejor granularidad que las herramientas actuales pueden ofrecer para tener una arquitectura micro-frontend es el uso de frameworks javascript acoplados a Webpack5 para gestionar mejor el uso de componentes web.

Más ...

Scroll al inicio