Desafíos de duplicación de lógica en arquitecturas de microservicios y cómo resolverlos

Desafíos de duplicación de lógica en arquitecturas de microservicios y cómo resolverlos

Las arquitecturas de microservicios, con su promesa de modularidad, escalabilidad y despliegue independiente, han ganado terreno en el panorama del desarrollo de software. Estos sistemas, al dividir aplicaciones en componentes más pequeños y especializados, ofrecen una gestión más ágil y eficiente. No obstante, esta división no está exenta de complicaciones. Una de las más notables es la duplicación de lógica entre servicios. Esta repetición, aunque puede surgir de un intento por mantener la autonomía de cada microservicio, conlleva a problemas de consistencia, errores y desafíos de mantenimiento.

¿Por qué ocurre la duplicación de lógica?

En sistemas de microservicios, es habitual que varios de ellos requieran realizar acciones similares. Esto lleva a que la lógica sea reimplementada en múltiples lugares, generando posibles inconsistencias y dificultando el mantenimiento.

Soluciones a la duplicación de lógica, pros/contras

Servicio de cálculos centralizado

Este servicio actúa como una autoridad única encargada de realizar todos los cálculos necesarios para la plataforma. En lugar de tener múltiples servicios replicando lógicas similares de cálculo, delegan esta responsabilidad al servicio centralizado, que devuelve los resultados a los solicitantes., las estrategias más populares que se utilizan para resolver este problema son:

gRPC: Como mencionamos anteriormente, gRPC es eficiente para la comunicación entre servicios gracias a su naturaleza binaria y a Protocol Buffers. Proporciona comunicación rápida y segura. RESTful APIs: Las APIs basadas en HTTP/REST son universales y se integran fácilmente con una amplia variedad de clientes y servicios.

  • Pros: Centraliza la lógica, facilita actualizaciones y mantiene coherencia.
  • Contras: Puede convertirse en un cuello de botella o en un punto único de falla, introduciendo latencia y afectando la disponibilidad.

Librerías compartidas

A librerías compartidas me refiero a encapsular la lógica en paquetes de distribución que podrías utilizar luego en npm, Maven Central Repository, Nexus Repository, JFrog Artifactory, PyPI, NuGet, RubyGems, Crates, Composer, etc.

  • Pros: Evita un servicio adicional, centraliza la lógica.
  • Contras: La gestión de versiones puede ser compleja, y cambios pueden afectar múltiples servicios.

Event sourcing y CQRS (Command Query Responsibility Segregation)

Event Sourcing, es un patrón donde el estado de una aplicación se determina mediante una secuencia de eventos en lugar de un estado fijo. Al "reproducir" estos eventos desde el inicio, puedes reconstruir el estado actual de la entidad.

CQRS, es un patrón que separa la lógica que actualiza datos (comandos) de la lógica que lee datos (consultas). Esto permite escalar, optimizar y controlar las operaciones de lectura y escritura de manera independiente.

  • Pros: Facilita la auditoría, separa comandos de consultas.
  • Contras: Complejidad en la implementación, manejo de secuencias de eventos que en proyectos grandes, implementer éstas estrategias toman tiempo.

Cache compartida

Usa un sistema de caché (como Redis) para almacenar resultados de cálculos.

  • Pros: Reduce la necesidad de cálculos repetidos y mejora la eficiencia.
  • Contras: Gestión de la caducidad de la caché y la coherencia de datos entre servicios.

Documentación exhaustiva

Un diagrama puede ayudar a representar estas soluciones. Imagina un círculo representando cada microservicio. En el modelo de "servicio centralizado", tendríamos flechas dirigidas desde cada microservicio hacia el "servicio de cálculos". En la "librería compartida", cada microservicio tendría un componente interno (la librería) representado.

sequenceDiagram
    participant U as Usuario
    participant MS as Microservicio
    participant BD as Base de Datos

    U->>MS: RealizarPago(monto,cuentaOrigen,cuentaDestino)
    MS->>MS: ValidarPedido()
    alt pedido valido
        MS->>BD: GuardarEvento(PagoRealizado)
        MS->>MS: ProcesarEvento(PagoRealizado)
        MS-->>U: Pago realizado!
    else pedido invalido
        MS-->>U: Error al procesar pago
    end

Esto genera un diagrama de secuencia que muestra:

  • El usuario envía un comando al microservicio para realizar un pago
  • El microservicio valida el pedido
  • Si es válido, guarda el evento asociado y lo procesa
  • Luego responde al usuario con éxito o error según corresponda

De esta forma se ilustra cómo se separan los comandos o queries de los eventos, guardándolos por separado y procesándolos después para modificar el estado.

  • Pros: Ayuda a los desarrolladores a comprender y mantener el sistema.
  • Contras: Mantener la documentación actualizada y garantizar que el equipo la consulte.

Revisión de responsabilidades

Reevaluar la responsabilidad de cada microservicio para reducir la lógica duplicada.

  • Pros: Redefinir responsabilidades puede llevar a un diseño más coherente.
  • Contras: Puede requerir cambios significativos en la arquitectura existente.
  1. Contratos claros y diseño

Es la definición precisa y bien estructurada de las interacciones entre servicios o componentes. En el contexto de microservicios o sistemas distribuidos, un "contrato" es típicamente una especificación de cómo un servicio o componente se comunica con otros: qué datos espera, qué datos devuelve, qué errores puede generar, etc.

Cuando hablamos de "contratos claros", estamos hablando de:

  1. Definición explícita: Establecer claramente qué esperamos como entrada y qué proporcionaremos como salida.
  2. Estabilidad: Una vez definido un contrato, no debe cambiarse a la ligera. Si es necesario cambiarlo, el proceso debe ser gestionado cuidadosamente para evitar romper servicios dependientes.
  3. Versionado: Si un servicio cambia, versiona su contrato para que los consumidores antiguos no se rompan.
  4. Documentación: Proporcionar documentación adecuada para que los desarrolladores entiendan cómo interactuar con el servicio.

Algunas herramientas que podrías utilizar para la definición de contratos podrían ser: gRPC, REST/HTTP, SOAP, Thrift (de Apache), estos son solo algunos ejemplos de muchos disponibles.


La duplicación de lógica en microservicios puede ser un desafío, pero con las herramientas y estrategias adecuadas, se puede alcanzar un sistema coherente, escalable y mantenible. La prevención activa y la adopción de mejores prácticas son esenciales para aprovechar al máximo las ventajas de los microservicios.

Happy coding! :D


Photo by Amir-abbas Abdolali on Unsplash

Jack Fiallos

Jack Fiallos

Te gustó este artículo?