Patrones de arquitectura

0
482
patrones

Vamos a hablar un poco de que son los patrones, los tipos de patrones que hay, y nos centraremos en algunos de los patrones de arquitectura más usados.

Intentaré dar explicaciones sencillas, con ejemplos que sean fácilmente entendibles.

Para definiciones formales o grandes gurús, todos ya sabemos usar google o chatGPT.

Empecemos.

Tabla de contenido

¿Qué son?

Los patrones son soluciones conocidas y probadas para problemas recurrentes.

Pues eso, los patrones son una forma, que sabemos que funciona, de resolver problemas que ya conocemos y que nos encontramos al diseñar software.

Tipos de patrones

Basándonos en el nivel de detalle y escala, se pueden clasificar:

Arquitectura, Son patrones a más alto nivel, plantean la forma de crear aplicaciones. Modelan la lógica del negocio, interfaces, y otros aspectos. Por ejemplo, SAGA, BFF.

Diseño, Definen los componentes de un sistema y la relación entre ellos. Se utilizan para implementar la lógica de los componentes. Facade, singleton serían algunos de ellos.

Dentro de los patrones de diseño, a su vez se dividen en 3 tipos.

Creacionales, Son patrones que solucionan problemas que se nos dan al crear objetos.

• singleton ( para restringir la creación de nuevas instancias de una clase a un objeto determinado.)
• factory method (usas interfaz para crear objetos en una superclase, mientras permite a las subclases alterar el tipo de objetos),

Comportamiento, Son patrones relacionados con algoritmos y acciones, por ejemplo:

• observer (varios objetos interesados (suscriptores) en un objeto en particular (notificador) pueden recibir notificaciones de su comportamiento )
• cadena de responsabilidad (permite pasar solicitudes a lo largo de una cadena de manejadores. Al recibir una solicitud, cada manejador decide si la procesa o si la pasa al siguiente), etc..

Estructurales, Son patrones que tratan la manera en que unos objetos se relacionan con otros, por ejemplo:

• proxy (te permite proporcionar un sustituto para otro objeto. controla el acceso al objeto original, permitiéndote hacer algo antes o después de que la solicitud llegue al objeto origina)
• facade (proporciona una interfaz simplificada para acceder a una biblioteca, un framework o cualquier otro grupo complejo de clases.), etc..

Idioms(lenguajes), se aplican a lenguajes de programaciones concretos y solucionan problemas propios de ese lenguaje (por ejemplo, la gestión de memoria en C).

Patrones

Estos son los patrones que veremos a continuación, y la arquitectura en que son más característicos.

• BFF (micro servicios)
• SAGA (micro servicios)
• CRQS (micro servicios)
• Aggregate root (DDD)
• ACL (DDD)
• Outbox Pattern (bus eventos)

BFF (Backend for frontend)

Es característico de la arquitectura de microservicios. Optimiza y adapta la comunicación entre el frontend y los microservicios (backend), introduciendo un elemento propio por cada frontend delante de los servicios.

Imaginar el caso de varias interfaces de usuarios (aplicación IOS, aplicación Android y varias SPAS o microfontend. ) que muestran información sobre pedidos y direcciones. Las aplicaciones móviles y una de las spas muestran un listado de pedidos y las direcciones en las que se ha entregado cada uno de los pedidos de un cliente. La otra spa muestra todas las direcciones en las que un cliente ha recibido pedidos.

La composición que hagan de esa información no será la misma cada uno de los frontend. Tendrán que adaptar lo que reciben de los Servicios a lo que necesitan, e incluirán la lógica de la composición con la parte visual.

Mediante la creación de 4 BFF, uno para cada uno de los frontales, se consigue hacer la composición necesaria para adaptar las respuestas de los Servicios, a lo que se desea mostrar en cada una de las interfaces de usuarios.

Ventajas:

• independizas la parte visual de las composiciones que tengas que hacer para formar la visual.
• Mejoras el rendimiento, pues la llamada de los bff a los microservicios se hace dentro de la misma infraestructura, con lo que tiene menos latencia y solo hay una petición desde los frontend. También el tiempo de renderizado es menor, pues la estructura está adaptada a lo que se quiere visualizar.

SAGA

Es una solución para el tratamiento de transacciones distribuidas, ya sea mediante coreografía u orquestación.

Cuando tienes todo en una aplicación monolítica si algo falla, echas para atrás toda la transacción y solucionado.

Pero cuando tienes varios microservicios que se encargan por ejemplo:

• Crear un pedido
• Hacer el cobro
• Control de stock
• Gestión del operador logístico

¿Cómo lo solucionas si te falla la llamada a uno de estos microServicios? Esto es lo que pretende solucionar el patron SAGA.

Coreografía

Una forma de hacerlo es mediante coreografía.

Para el caso anterior (creación de pedido, gestión cobro, control de stock, gestión de envío a través del operador logístico) cada uno de los microservicios encargados de una parte del negocio, cuando lo ha hecho emite un evento, que es escuchado por el siguiente, y en caso de fallo emite un evento de compensación indicando que ha fallado, y los microservicios que anteriores se suscriben para hacer las acciones correspondientes para deshacer su operativa.

Por ejemplo, si la creación del pedido ha ido bien se emite un evento que lee el microservicio encargado del cobro, y si esto va bien, emite otro evento destinado a la gestión del stock. Si su parte va bien emite otro evento para el envío la OL.

Pero supongamos que todo va bien hasta la gestión del stock.

Y en esta parte se produce un error. El micro encargado de la gestión de stock emitiría un evento de compensación destinado a que la parte de cobro deshiciera su parte, y este a su vez emitiría otro evento para que la gestión del pedido pudiera deshacer su operativa.

Esto sería el diagrama con todos los posibles mensajes de ok y ko.

las Ventajas y desventajas de este planteamiento son :

Ventajas:

• No hay un punto único de fallo, como si lo hay en la implementación por orquestación, que veremos ahora.
• No tengo que implementar nada adicional, solo los servicios propios del negocio.

Desventaja:

• Para transacciones distribuidas que puede tener muchos pasos, puede llegar a complicarse esta solución.

Orquestación

Otra forma de coordinar la transacción distribuida es mediante un orquestador.

• Es el encargado de enviar eventos para la realización de las distintas partes.
• Escucha el resultado de las transacciones “parciales” y en función del resultado continua con la operative o echa para atrás las partes anteriores.

Aquí lo que habrá son los servicios anteriores.

• (creación de pedido, gestión cobro, control de stock, gestión de envío a través del operador logístico).
• Un orquestador encargado de enviar una petición (de creación o vuelta atrás) a cada uno de los servicios, en función de la respuesta del micro anterior.
• 2 tópicos por cada uno de los micro servicios, uno para recibir las peticiones, donde escribe el mensaje el orquestador, y recibirá la petición el micro. Y otro para los resultados, donde escribirá el resultado de cada petición y leerá el orquestador. Para decidir si echa para atrás las operaciones anteriores o continua con el flujo normal.

Para el caso anterior en que el pedido y el cobro iba OK, fallando el aprovisionamiento de stock.

La tarea del orquestador al recibir ese KO, sería lanzar los mensajes de cancelación del cobro anterior y del pedido.

las ventajas y desventajas de la orquestación son.

Ventajas:

• Soporta transacciones complejas.
• Los servicios no saben unos de otros, si tengo que añadir un nuevo servicio, o modificar el orden, el único que necesita saberlo es el orquestador.

Desventaja:

• Tienes un punto de error crítico, el orquestador.
• Tienes que hacer implementaciones adicionales, el orquestador hay que implementarlo.

CRQS (command query responsibility segregation)

Consiste en la separación de las responsabilidades de consultas (lectura) y comandos (escritura).

Tradicionalmente en las aplicaciones monolíticas tenías un pool de conexiones para acceder a una BBDD compartida por varias aplicaciones.

Ya en la arquitectura de microservicios lo que se proponen es el tener una bbdd por cada uno de los microservicios. Un paso más allá es la separación entre la parte de consulta y escritura, que es lo que sugiere este patron.

Pensemos en cuando entras a comprar algo en amazon, pasas un rato (siempre fuera del horario laboral) visualizando un montón de productos, opiniones. Y la carga de productos es mínima.

Un porcentaje mayoritario de las operaciones que has hecho son de lectura, luego lo correcto es tener dimensionados correctamente la parte de lectura y escritura.

Una manera de tener separado los commandos de las consultas es mediante 2 Servicios distintos, uno se encarga de las escrituras y otro de las lecturas, lo cual te permite haces escalados independientes para cada uno de las partes. Al ser BBDD independientes las puedo mantener optimizadas (indices, vistas, etc. ) una para las escrituras, y otra para las escrituras. Por ejemplo los índices perjudican a la escritura, pero favorecen muchísimo la lectura.

El punto crítico de este planteamiento es la sincronización entre las BBDD, una posible solución seria a través de kafka que te permite a través de sus conectores realizar estas actualizaciones. Este planteamiento tiene que tener en cuenta el decalaje entre las operaciones de escritura y de lectura.

Otro planteamiento de CRQS es implementado es en el mismo dominio/BC, pero separadas los accesos a las entidades. Por un lado, las queries y vistas que tenga modeladas para las consultas y por otro los commandos del dominio. ¿Por qué? Así puedo mantener en DDD las restricciones/invariantes de dominio para la parte de los commandos, y no estar sujeto a ellas en la parte de las consultas.

Las ventajas y desventajas que nos ofrece CRQS.

Ventajas:

• Posibilidad de escalado independiente
• Restricciones de negocio, solo aplicarían a los comandos
• Modelado independiente de BBDD lectura y escritura

Desventajas:

• Mayor complejidad
• Punto crítico en la sincronización
• Retardo entre escritura y consulta

Aggregate Root

Es un patrón táctico de DDD (diseño orientado al dominio), mediante el cual se establece que el acceso a ciertas entidades es a través de otra entidad que le da el sentido.

Pensemos en una cuenta tiene cargos y abonos.

Pero, ¿tiene sentido que existan cargos o abonos sin una cuenta? ¿Cómo se accede a un cargo y un abono?

POST /v1/charge (creación)
PUT /v1/charge/{chargeID} (modificación)
GET /v1/charge/{chargeID} (consulta)

En estos 3 casos, accederíamos directamente a los cargos de una cuenta sin tener en cuenta las invariantes de la cuenta (actualize el saldo de la cuenta, la moneda debe ser en la misma que en la cuenta, debe estar asociado al NIF del emisor de la cuenta, etc.).

Sin embargo, la forma correcta es acceder a través del número de cuenta, pues es la manera de poder garantizar las invariantes del negocio. Este planteamiento de las apis, debiera estar reflejado en el Código, y en los repositorios para acceder a las entidades.

POST /v1/{account}/charge/{id}
PUT /v1/{account}/charge/{chargeID} (modificación)
GET /v1/{account}/charge/{chargeID} (consulta)

A mayores habría que revisar que las apis representan casos de uso del negocio, y no meros CRUD, pero eso ya es otro tema.

Ventajas:

• Garantizas la consistencia entre las entidades de un aggregate, todas las entidades de un aggregate, pertenecen al aggregate que corresponde.
• Garantizas las invariantes del negocio, tengo control sobre las restricciones del negocio.

ACL (Anti corruption layer)

Es una capa intermedia que traduce entre distintos modelos de dominio.

Por ejemplo, imaginemos que tenemos 2 microservicios que modelan la entidad dirección. Uno un microservicio referente entregas de paquetería, y otro para la contabilidad.

En entrega en el operador logístico la dirección me interesa que tenga el mayor detalle posible, tipo de la via, nombre de la via, numero, portal, escalera, piso, letra, Código postal.

Sin embargo, para un microservicio de contabilidad, básicamente lo único que me interesa es la provincia, para conocer la zona fiscal que le corresponde, y el impuesto asociado, iva peninsula, Vizcaya, Álava, Guipúzcoa. O IGIC, o impuesto Ceuta y Melilla.

A la hora de intercambiar información, necesitarán “traducir” la entidad dirección de lo que es un micro a lo que es en el otro.

También esto se da cuando estamos migrando o integrando sistemas legacy con sistemas nuevos. Por ejemplo al crear un nuevo Sistema de compras, la información de un product no tiene por qué coincidir con lo que esté en el Sistema legacy y en el nuevo. Si van a convivir los 2 sistemas, debemos implementar una ACL que nos traduzca esta información.

O cuando nos vamos a integrar con sistemas de terceros.

Aquí tendríamos que cuando se produce un cambio en la dirección de un pedido, se lanza un evento de dominio con el cambio.

BC de entrega está suscrito a ese tópico leyendo los cambios de dirección, y mediante una ACL traduce ese evento a la dirección que él necesita, y lo publica en un tópico interno, que él ya entiende. No existe acoplamiento entre lo que es la dirección del BC de pedido y el BC de entrega.

Lo mismo para BC de fiscalidad, con lo que se permite que las partes del negocio de fiscalidad y entrega sean independiente de los pedidos y se centren en su dominio.

Este caso sería la traducción entre bounded context.

Otro caso sería la integración con aplicaciones legacy.

Imaginemos que hemos migrado la parte de entregas a un nuevo BC, que se encarga de realizar las entregas, pero la creación de los pedidos sigue existiendo en nuestra aplicación legacy. Y por la noche va a buscar las entregas pendientes del sistema legacy, para gestionar su envío al operador logístico.

En este caso la ACL nos permitiría ser independientes de la definición de la entidad dirección en el sistema legacy, y nuestro negocio funcionaría con la dirección definida en nuestro BC.

El tercer caso sería como puente con aplicaciones de terceros.

Imaginemos un Bounded context de entregas que por las noches normaliza las direcciones de entrega de los pedidos generados ese día con un servicio externo antes de comunicárselo a los operadores logísticos.

Aquí la ACL haría una traducción de la dirección normalizada a la entidad interna de dirección de nuestro BC, con lo que sería independiente nuestro BC y nuestro negocio del servicio externo.

Ventajas:

• Independencia entre las entidades de nuestro negocio y definiciones externas, evitando la corrupción de nuestro modelo.

Outbox

En una arquitectura basada en eventos, outbox busca garantizar la consistencia entre la escritura en BBDD y la publicación de eventos.

Imaginemos que tenemos un servicio que se encarga de la creación de una factura, y una vez creada, lanza un evento de dominio para que otros servicios puedan suscribirse a él (por ejemplo un servicio de fiscalidad) y realizar las acciones correspondientes.

El problema que nos encontramos es que si la escritura en la BBDD se ha realizado correctamente (hemos creado la factura), pero la publicación del evento no, el resto de los servicios no se enterarán de la creación del pedido, y no podrán realizar las acciones correspondientes.

Imaginar el proplema de estar emitiendo facturas, y que no se esté realizando su fiscalización.

Para evitar esto el patron outbox, lo que propone es, en la misma transacción donde guarda la información de sus entidades de dominio en BBDD, graba en una table la información del evento que debe ser publicado (ya sea el mismo evento o la información necesaria) con lo cual garantiza la realización de todas las operaciones en una misma transacción.

Posteriormente, un proceso en batchground, periódicamente, lee la tabla de outbox y realiza la publicación de los eventos correspondientes.

Ventajas:

• Consistencia garantizada: Al escribir los eventos en la tabla outbox dentro de la misma transacción que actualiza la base de datos del servicio emisor, se garantiza que los eventos serán publicados siempre que la transacción sea confirmada, manteniendo la consistencia entre la base de datos del emisor y el sistema de mensajería.
• Escalabilidad: Como el proceso de publicación de eventos se realiza en segundo plano, los servicios emisores no están bloqueados esperando que los eventos sean entregados, lo que permite escalar mejor la capacidad del servicio.
• Tolerancia a fallos: Si el proceso de publicación de eventos falla o se detiene por algún motivo, el registro del outbox aún existe y puede ser procesado por otro proceso de fondo cuando esté disponible, asegurando que los eventos sean entregados eventualmente.
• Cold start: En caso de que el servicio emisor se reinicie, se despliegue en un nuevo entorno se subscriba a los mensajes un nuevo servicio, los eventos pendientes en la tabla outbox serán procesados automáticamente por el proceso de publicación, evitando la pérdida de eventos.S

Adolfo Herrero García
Mi nombre es Adolfo Herrero, soy un apasionado de la tecnología, y me encanta compartir lo que voy aprendiendo. Llevo más de 25 años trabajando en el mundo de la tecnología, y he tenido la suerte de trabajar en empresas de distintos sectores, y de distintos tamaños, lo que me ha permitido aprender mucho de cada una de ellas. Mis roles han sido variados, desde programador, analista de sistemas, arquitecto de software, y siempre he intentado aprender de cada uno de ellos. Actualmente, trabajo para Izertis, como software architect, para un cliente líder a nivel mundial en el sector retail, y colaboro en el área de sostenibilidad intentando potenciar los TL de los equipos. Asegurando que la arquitectura sea eficiente, escalable y sostenible y esté alineada con el ecosistema. Ayudo a gestionar eficientemente las dependencias de los equipos con terceros e identificar entidades.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad