La Arquitectura Hexagonal, también conocida como Ports and Adapters, es un patrón de arquitectura de software que busca aislar la lógica del negocio de cualquier interacción con el mundo exterior, creando una aplicación altamente desacoplada y mantenible. Este patrón fue propuesto por Alistair Cockburn, y promueve la idea de que la lógica del negocio de una aplicación debe ser independiente de cualquier detalle externo como la base de datos, la interfaz de usuario, o la comunicación entre sistemas.

La clave de esta arquitectura radica en su enfoque en puertos y adaptadores. Los "puertos" son interfaces en el núcleo de la aplicación que definen los comportamientos esperados por la lógica del negocio. Los "adaptadores", por otro lado, son implementaciones de estos puertos que interactúan con el mundo exterior.

La Arquitectura Hexagonal se llama así debido a la forma en que se visualiza conceptualmente. En su diagrama, el núcleo de la lógica de negocio se representa en el centro de un hexágono. Los distintos lados o "caras" del hexágono representan los "puertos" a través de los cuales la lógica del negocio interactúa con el mundo exterior. Por lo tanto, no importa en qué dirección mires (o desde qué lado del hexágono accedas), siempre estás interactuando con un puerto que conecta con la lógica de negocio central. 

Diagrama Arquitectura Hexagonal

Algunas ventajas del uso de la arquitectura hexagonal son:

  • Desacoplamiento: La lógica del negocio queda completamente aislada de las preocupaciones externas, lo que significa que los cambios en las interfaces externas (como una nueva base de datos o tecnología de interfaz de usuario) no deberían afectar a la lógica del negocio en sí.
  • Testabilidad: Gracias al desacoplamiento, es más sencillo realizar pruebas unitarias de la lógica del negocio. Puedes usar adaptadores de prueba en lugar de los reales para probar el comportamiento de tu sistema bajo diferentes condiciones.
  • Mantenibilidad y capacidad de evolución: El código es más fácil de mantener y evolucionar a lo largo del tiempo. Dado que la lógica del negocio no está mezclada con el código que interactúa con el mundo exterior, los desarrolladores pueden concentrarse en mejorar la lógica del negocio sin preocuparse de los detalles técnicos.

Sin embargo, esta arquitectura presenta algunos inconvenientes que se deben tener en cuenta antes de decantarse por ella:

  • Complejidad añadida: Este tipo de arquitectura puede ser excesiva para aplicaciones más pequeñas o menos complejas. Puede haber una cantidad considerable de código dedicado a la organización de la arquitectura, lo que puede parecer innecesario si la aplicación es suficientemente sencilla.
  • Curva de aprendizaje: Aprender a trabajar con la arquitectura hexagonal puede llevar algo de tiempo. Los desarrolladores deben entender cómo se organizan los puertos y adaptadores y cómo interactúan entre sí.
  • Retos en la integración: Aunque la arquitectura desacopla la lógica del negocio del resto del sistema, la integración con sistemas externos puede seguir siendo un desafío, especialmente si estos sistemas no siguen los mismos principios de diseño.

Pros y contras de la arquitectura hexagonal

 

Estructura

La Arquitectura Hexagonal se basa en la idea de separar claramente las funciones internas y externas de una aplicación, lo que permite la independencia de la lógica de negocio respecto a los dispositivos o servicios externos.

La estructura interna de una aplicación que sigue este patrón se puede dividir en tres partes principales:

  • Dominio de aplicación o Core: Este es el núcleo de la arquitectura hexagonal y es donde reside la lógica de negocio. El dominio de la aplicación define las reglas y comportamientos esenciales del sistema y está completamente aislado de las influencias externas.
  • Puertos: Los puertos son interfaces o contratos definidos por el dominio de aplicación. Los puertos primarios o "puertos de conducción" definen las funcionalidades que ofrece el dominio de aplicación. Los puertos secundarios o "puertos impulsados" definen las funcionalidades que espera el dominio de la aplicación del mundo exterior.
  • Adaptadores: Los adaptadores son la implementación de los puertos que interactúan con los componentes externos al dominio de la aplicación. Pueden ser adaptadores de entrada (que implementan puertos primarios) como controladores de interfaz de usuario o servicios de petición de API, o adaptadores de salida (que implementan puertos secundarios) como acceso a bases de datos, servicios de mensajería, etc.

Gracias a esta estructura, la lógica de negocio (el dominio de la aplicación) puede desarrollarse y probarse de manera independiente de la infraestructura que se utilizará. Los puertos y adaptadores permiten que cualquier tecnología externa (bases de datos, bibliotecas, frameworks, etc.) pueda ser intercambiada con mínimos cambios en el dominio de la aplicación. Esto hace que la arquitectura sea flexible y adaptable a diferentes tecnologías y a cambios en los requisitos del sistema.

También cabe destacar que esta arquitectura se centra en la organización del código y las interacciones entre diferentes partes de un sistema, y no prescribe cómo se deben manejar los procesos o la distribución del código.

La estructura de puertos y adaptadores en la arquitectura hexagonal permite un alto nivel de desacoplamiento y modularidad en el código, pero esto no implica que todo el sistema se deba implementar en un solo código base o se deba ejecutar en un único proceso.

Es posible tener una arquitectura hexagonal en la que diferentes partes del sistema se implementen en diferentes bases de código y se ejecuten en diferentes procesos o incluso en diferentes servidores. Por ejemplo, podrías tener un sistema con un servicio de backend que implementa la lógica de negocio y los puertos, y varios adaptadores que se implementan como microservicios independientes.

Por otro lado, también es posible tener una arquitectura hexagonal que se implemente en una única base de código y se ejecute en un solo proceso. Esto podría ser apropiado para una aplicación más pequeña o si el equipo de desarrollo prefiere mantener todo el código relacionado en un solo lugar para facilitar el mantenimiento y la comprensión del código.

Así que, en resumen, la arquitectura hexagonal se trata de cómo estructuras y organizas tu código para mantener la lógica de negocio separada de los detalles de entrada/salida y la infraestructura, y no tiene reglas estrictas sobre cómo se deben manejar las bases de código o los procesos.

 

Estructura de la arquitectura hexagonal

Dominio de la aplicación o Core

El Dominio de Aplicación, también conocido como Core, es el corazón de la arquitectura hexagonal. Aquí es donde reside la lógica de negocio central de la aplicación. El dominio de aplicación contiene todas las reglas y comportamientos esenciales del sistema y es completamente independiente de cualquier capa externa.

En el dominio de aplicación se incluyen todas las entidades, servicios de dominio, eventos y excepciones que definen el negocio o el propósito de la aplicación. Las entidades son los objetos de negocio centrales que representan los conceptos clave del sistema y contienen la lógica empresarial asociada.

En una arquitectura hexagonal, el dominio de aplicación no debe tener ninguna dependencia directa con la infraestructura, es decir, con los detalles de la base de datos, la interfaz de usuario, los servicios de mensajería, etc. En lugar de ello, el dominio de aplicación se comunica con el mundo exterior a través de interfaces o contratos conocidos como puertos.

Esta independencia del dominio de aplicación respecto a la infraestructura facilita la realización de pruebas unitarias y de integración, ya que la lógica de negocio puede probarse en aislamiento. También hace que el código de la aplicación sea más fácil de entender y mantener, ya que los cambios en los detalles de la infraestructura no afectan a la lógica de negocio. Asimismo, esta separación del dominio de aplicación de los detalles técnicos facilita la adaptabilidad y la evolución del sistema.

 

Dominio de la aplicación en arquitectura hexagonal

Puertos

Los puertos son una pieza fundamental de la arquitectura hexagonal y actúan como puntos de entrada y salida para la interacción entre el dominio de la aplicación (o Core) y los actores externos (por ejemplo, usuarios, sistemas externos o infraestructura de la propia aplicación como bases de datos o servicios de mensajería). Los puertos se definen mediante interfaces en el código, estableciendo un contrato sobre cómo el dominio de la aplicación puede interactuar con el mundo exterior.

Hay dos tipos de puertos en una arquitectura hexagonal:

  • Puertos primarios o conducidos: También conocidos como puertos de entrada, definen las operaciones que la aplicación puede realizar en respuesta a una petición externa. Estas operaciones son típicamente acciones de alto nivel correspondientes a las capacidades de negocio de la aplicación. Por ejemplo, en un sistema de gestión de pedidos, un puerto primario podría definir operaciones como "crear pedido", "actualizar pedido" o "eliminar pedido".
  • Puertos secundarios o de conducción: También conocidos como puertos de salida, definen las operaciones que la aplicación puede solicitar a los elementos externos. Un puerto secundario podría, por ejemplo, definir operaciones de persistencia de datos como "guardar pedido" o "buscar pedido".

Esta separación de responsabilidades y el desacoplamiento entre el dominio de la aplicación y los elementos externos, permiten que cualquier cambio en la infraestructura (como la migración a una nueva base de datos) tenga un impacto mínimo en el código del dominio de la aplicación. Al mismo tiempo, facilita la realización de pruebas, ya que los puertos secundarios pueden ser fácilmente sustituidos por implementaciones de prueba (mocks) durante las pruebas unitarias.

Puertos en la arquitectura hexagonal

 

Puertos primarios o conducidos

Los puertos primarios, también conocidos como puertos conducidos o puertos de entrada, representan la capa de abstracción entre el dominio de la aplicación y el mundo exterior. Estos puertos definen las interfaces a través de las cuales los actores externos pueden interactuar con el dominio de la aplicación.

En una arquitectura hexagonal, los puertos primarios son responsables de definir las operaciones de alto nivel que la aplicación puede realizar. Las operaciones definidas por los puertos primarios se centran en las capacidades de negocio de la aplicación y definen la lógica de negocio de alto nivel.

Por ejemplo, en un sistema de gestión de pedidos, los puertos primarios podrían definir operaciones como "crear pedido", "actualizar pedido" o "eliminar pedido". Estas operaciones son las que los actores externos, como los usuarios o los sistemas externos, pueden invocar.

Los puertos primarios son esencialmente contratos que definen cómo se puede interactuar con el dominio de la aplicación. Estos contratos establecen las reglas para la interacción entre el dominio de la aplicación y el exterior, asegurando que la lógica de negocio permanezca aislada y protegida de los cambios en las capas externas de la arquitectura.

En el desarrollo de software, los puertos primarios se implementan a menudo como interfaces en el código. Las interfaces proporcionan una descripción abstracta de las operaciones que la aplicación puede realizar, sin entrar en detalles sobre cómo se implementan estas operaciones. La implementación concreta de estas operaciones se proporciona en los adaptadores de la aplicación, que interactúan con el dominio de la aplicación a través de los puertos primarios.

Puertos secundarios o de conducción

Los puertos secundarios, también conocidos como puertos de conducción o puertos de salida, representan las interfaces a través de las cuales el dominio de la aplicación interactúa con el mundo exterior. Estos puertos abstraen los detalles técnicos de la infraestructura externa, permitiendo que el dominio de la aplicación se comunique con los sistemas externos de una manera que está desacoplada de los detalles específicos de la implementación.

Por ejemplo, supongamos que el dominio de la aplicación necesita interactuar con una base de datos. En lugar de interactuar directamente con la base de datos, el dominio de la aplicación interactuaría con un puerto secundario que define las operaciones de alto nivel que se pueden realizar en la base de datos, como "guardar pedido" o "obtener pedido". Esto permite que la lógica del dominio de la aplicación esté aislada de los detalles técnicos de cómo se accede y se manipula la base de datos.

En un nivel de implementación, los puertos secundarios se realizan a menudo como interfaces en el código. Estas interfaces definen las operaciones que el dominio de la aplicación puede realizar en la infraestructura externa, pero no proporcionan ninguna implementación concreta de estas operaciones. En su lugar, la implementación se proporciona a través de los adaptadores de la aplicación, que implementan las interfaces definidas por los puertos secundarios.

Los puertos secundarios desempeñan un papel crucial en la promoción de la inversión de dependencias en la arquitectura hexagonal. Al interactuar con la infraestructura externa a través de los puertos secundarios, el dominio de la aplicación puede mantenerse desacoplado de los detalles de la implementación de la infraestructura. Esto facilita la adaptación a los cambios en la infraestructura sin afectar la lógica del dominio de la aplicación.

Adaptadores

Los adaptadores son componentes fundamentales en la arquitectura hexagonal, funcionando como el puente entre los puertos y la infraestructura externa, es decir, las tecnologías y sistemas externos al dominio de la aplicación.

  • Adaptadores para Puertos Primarios: Estos adaptadores reciben solicitudes de la infraestructura externa y las traducen a un formato que el dominio de la aplicación pueda entender y manejar. Por ejemplo, un adaptador de entrada podría ser un controlador de una API que recibe solicitudes HTTP, las convierte en llamadas a los métodos de los casos de uso dentro del dominio de la aplicación.
  • Adaptadores para Puertos Secundarios: Estos adaptadores interactúan con la infraestructura externa en nombre del dominio de la aplicación. Implementan las interfaces definidas por los puertos secundarios y manejan los detalles técnicos de cómo interactuar con sistemas específicos, como bases de datos, servicios web, mensajería, etc. Por ejemplo, un adaptador de salida podría ser un repositorio que implementa las operaciones definidas en un puerto secundario, traduciéndolas en operaciones SQL específicas para acceder a una base de datos.

El uso de adaptadores permite un alto grado de desacoplamiento y modularidad. Los detalles de la infraestructura externa están confinados dentro de los adaptadores, manteniendo la lógica del dominio de la aplicación limpia y centrada en la lógica del negocio. Esto también facilita la prueba, ya que los adaptadores pueden ser fácilmente reemplazados por dobles de prueba en un entorno de prueba. Además, si alguna tecnología externa necesita ser reemplazada, solo se necesitaría actualizar o reemplazar el adaptador correspondiente, minimizando el impacto sobre el dominio de la aplicación.

 

Adaptadores en arquitectura hexagonal

Adaptadores para puertos primarios o de entrada

Los adaptadores para puertos primarios, también conocidos como adaptadores de entrada, son los que permiten la interacción entre el usuario o cualquier agente externo y la aplicación. Estos adaptadores reciben las solicitudes desde el exterior y las traducen a un formato comprensible para el dominio de la aplicación.

Por ejemplo, supongamos que tenemos un servicio web que expone una API REST. Cuando un cliente realiza una petición HTTP a nuestro servicio, esta petición llegará primero a uno de nuestros adaptadores para puertos primarios. Este adaptador, a menudo un controlador en un marco MVC, es responsable de tomar esa petición HTTP y transformarla en una llamada al caso de uso apropiado dentro del dominio de la aplicación.

Esto puede involucrar la extracción de los parámetros necesarios del cuerpo de la petición, la validación de estos parámetros y finalmente la invocación del caso de uso correspondiente con estos parámetros.

Una de las ventajas de este enfoque es que aísla completamente el dominio de la aplicación de los detalles específicos de la infraestructura de entrada, lo que permite cambiar la forma en que la aplicación es accesible sin afectar a la lógica del dominio. Por ejemplo, podríamos decidir cambiar de una API REST a una API GraphQL sin tener que cambiar nada en nuestra lógica de negocio; simplemente necesitaríamos crear nuevos adaptadores para manejar las peticiones GraphQL.

Adaptadores para puertos secundarios

Los adaptadores para puertos secundarios, también conocidos como adaptadores de salida, actúan como intermediarios entre el dominio de la aplicación y cualquier sistema externo o servicio del que dependa la aplicación. Estos adaptadores son responsables de traducir las interacciones del dominio de la aplicación con estos sistemas externos.

Un ejemplo común de adaptador para puertos secundarios es un repositorio de datos. Supongamos que el dominio de la aplicación necesita persistir o recuperar datos de una base de datos. En lugar de interactuar directamente con la base de datos, lo que acoplaría el dominio de la aplicación a un tipo específico de base de datos, el dominio interactúa con una interfaz de repositorio que es parte de los puertos secundarios. La implementación concreta de esta interfaz es manejada por el adaptador del puerto secundario.

Por ejemplo, podríamos tener un "RepositorioUsuario" que define operaciones como "guardarUsuario" y "buscarUsuario". La lógica del dominio de la aplicación utiliza estas operaciones sin saber cómo se implementan. Y tenemos un "AdaptadorRepositorioUsuario" que implementa estas operaciones para una base de datos MySQL específica.

De esta manera, si en algún momento decidimos cambiar de una base de datos MySQL a una base de datos NoSQL, solo tendríamos que implementar un nuevo adaptador que cumpla con la interfaz del "RepositorioUsuario". La lógica del dominio de la aplicación no necesita ser cambiada, ya que sigue interactuando con la misma interfaz del repositorio.

De esta forma, los adaptadores para puertos secundarios permiten mantener aislada la lógica del dominio de las especificidades de las tecnologías de infraestructura de salida utilizadas, facilitando el mantenimiento y evolución del software.

Manejo de Peticiones

En la arquitectura hexagonal, las peticiones de los usuarios o sistemas externos son manejadas mediante la interacción de varios componentes clave: los adaptadores, los puertos y el dominio de la aplicación.

  • Entrada de peticiones: Las peticiones de los usuarios o de otros sistemas son recibidas inicialmente por los adaptadores de entrada. Estos adaptadores, también conocidos como adaptadores primarios, pueden ser interfaces de usuario, API, consumidores de mensajes, etc. Estos adaptadores son responsables de traducir las peticiones recibidas en un formato que pueda ser comprendido por el dominio de la aplicación.
  • Procesamiento de peticiones: Una vez que la petición es traducida por el adaptador de entrada, es pasada al dominio de la aplicación a través de un puerto primario. El dominio de la aplicación, también conocido como el "core" del sistema, contiene la lógica de negocio que maneja la petición. La lógica de negocio puede implicar operaciones como validar los datos de la petición, realizar cálculos, o interactuar con los puertos secundarios para persistir o recuperar datos.
  • Respuesta a las peticiones: Después de que la lógica del dominio ha procesado la petición, la respuesta se pasa de nuevo al adaptador de entrada a través del puerto primario. El adaptador de entrada entonces traduce la respuesta del dominio de la aplicación a una forma que el usuario o el sistema externo pueda entender y la envía de vuelta.

De esta manera, la arquitectura hexagonal maneja las peticiones y respuestas de una manera que mantiene la lógica del dominio aislada de los detalles específicos de los sistemas de entrada y salida. Esto permite una mayor flexibilidad, ya que los adaptadores de entrada y salida pueden ser intercambiados sin afectar a la lógica del dominio.

 

Gestión de peticiones en arquitectura hexagonal

Entrada de peticiones

En la arquitectura hexagonal, las peticiones de los usuarios o de otros sistemas ingresan al sistema a través de los adaptadores primarios o de entrada. Estos adaptadores son responsables de interactuar con el mundo exterior, que puede ser una interfaz de usuario, una solicitud de API, un sistema de mensajes, entre otros.

El adaptador de entrada tiene la tarea principal de traducir las peticiones recibidas del mundo exterior en un formato que la capa de dominio de la aplicación pueda entender y procesar. En otras palabras, el adaptador de entrada convierte las solicitudes externas en comandos o consultas para el dominio de la aplicación.

Por ejemplo, si un usuario realiza una petición a través de una interfaz de usuario web, el adaptador de entrada puede ser un controlador en un patrón MVC (Modelo-Vista-Controlador). El controlador recibe la petición HTTP, extrae la información necesaria de la petición (como los parámetros de la URL o los datos del formulario) y la traduce en comandos o consultas que se pasan al dominio de la aplicación a través de un puerto primario.

Este proceso de traducción permite un aislamiento efectivo entre la lógica de negocio (en el dominio de la aplicación) y las entradas y salidas específicas del sistema. Esto significa que los cambios en las interfaces de usuario o en las tecnologías de la API no deberían afectar a la lógica de negocio, lo que a su vez facilita el mantenimiento y mejora la capacidad de prueba de la lógica de negocio.

Procesamiento de peticiones

El procesamiento de peticiones en una arquitectura hexagonal se lleva a cabo en el dominio de la aplicación, que es también el núcleo de la arquitectura. En este modelo de arquitectura, el dominio de la aplicación se encuentra completamente aislado y no tiene dependencias directas con ninguna capa externa. Las peticiones llegan a él a través de los puertos primarios y es aquí donde se lleva a cabo toda la lógica de negocio.

En la etapa de procesamiento, la lógica de negocio se encarga de realizar las acciones correspondientes para cada petición. Estas acciones pueden variar desde operaciones sencillas, como obtener datos, hasta procesos complejos que implican múltiples pasos.

La lógica de negocio puede interactuar con las entidades del dominio y los servicios del dominio para llevar a cabo sus tareas. Una entidad del dominio puede representar un concepto o un objeto de negocio, como un producto en un ecommerce, mientras que los servicios del dominio encapsulan comportamientos que no pertenecen naturalmente a una entidad.

Cuando el procesamiento de la petición implica la necesidad de interactuar con recursos externos, como una base de datos o un servicio web, se utiliza un puerto secundario para encapsular esta comunicación. Un adaptador adecuado se encarga de implementar la interacción real, permitiendo que la lógica de negocio permanezca aislada de las particularidades de los sistemas externos.

Una vez que la petición ha sido procesada y se ha generado una respuesta, esta respuesta también se puede enviar a un adaptador de salida a través de un puerto secundario.

Respuesta a las peticiones

Después de que la lógica de negocio ha procesado la petición en el dominio de aplicación, la respuesta se genera y se envía de vuelta a través de los puertos primarios. Este proceso de salida también está controlado y gestionado por los adaptadores correspondientes, que se encargan de transformar los datos del dominio en el formato que el cliente externo espera o necesita.

Las respuestas pueden variar según la naturaleza de la petición y los requisitos del sistema. Podrían ser tan sencillas como confirmaciones de que una acción ha sido completada con éxito, o podrían ser conjuntos más complejos de datos si la petición implicaba la recuperación de información.

Es importante notar que la lógica de negocio no se preocupa por cómo se manejará o presentará la respuesta una vez que salga del dominio de la aplicación. Este detalle queda en manos del adaptador de salida correspondiente. Por ejemplo, si la petición vino a través de una interfaz de usuario web, el adaptador de salida transformaría los datos del dominio en HTML o JSON. Si la petición era de un sistema de cola de mensajes, el adaptador de salida podría transformar y enviar los datos como un mensaje en la cola.

El uso de adaptadores para manejar la presentación y entrega de las respuestas permite que el dominio de la aplicación se mantenga desacoplado y agnóstico a las tecnologías y sistemas externos, favoreciendo así la mantenibilidad y la adaptabilidad del sistema en general.

Escalabilidad

La escalabilidad en una arquitectura hexagonal es una característica inherente debido a su naturaleza desacoplada y modular. Aunque las consideraciones de escalabilidad pueden variar dependiendo de la implementación y de las necesidades específicas del negocio, hay algunas formas generales en las que la arquitectura hexagonal puede escalar:

  • Escalabilidad Vertical: El desacoplamiento entre el dominio de aplicación y los adaptadores permite mejorar las capacidades de un único sistema al agregar más recursos, como CPU o memoria, según sea necesario. Esto se puede hacer sin cambiar la lógica del dominio de aplicación, y solo se requiere que los adaptadores sean capaces de aprovechar los recursos adicionales.
  • Escalabilidad Horizontal: La modularidad y el desacoplamiento inherentes a la arquitectura hexagonal también facilitan la escalabilidad horizontal, es decir, la adición de más instancias del sistema para manejar cargas de trabajo mayores. Por ejemplo, podrías tener múltiples instancias del dominio de aplicación, cada una con su propio conjunto de adaptadores, corriendo en paralelo y balanceando la carga entre ellas. Los adaptadores deben ser diseñados para permitir este tipo de escalabilidad, por ejemplo, ser capaces de compartir sesiones o manejar correctamente la concurrencia.
  • Escalabilidad Funcional: Otra forma de escalar en una arquitectura hexagonal es a través de la escalabilidad funcional, donde nuevas características o funcionalidades pueden ser añadidas como nuevos adaptadores sin afectar el núcleo de la lógica de negocio. Esto permite a un sistema crecer y evolucionar con el tiempo sin requerir grandes reescrituras o reestructuraciones del código existente.

La arquitectura hexagonal mejora la resiliencia del sistema al permitir que fallos en un adaptador o en un sistema externo no afecten al núcleo del dominio de la aplicación. Esto significa que el sistema puede seguir funcionando, o al menos fallar de manera más controlada, en caso de que una parte del sistema falle.

 

Escalabilidad en la arquitectura hexagonal

En resumen, la escalabilidad en una arquitectura hexagonal es lograda a través de un diseño cuidadoso que se centra en el desacoplamiento y la modularidad, permitiendo al sistema crecer y adaptarse a nuevas condiciones y requerimientos sin necesidad de grandes cambios estructurales. Sin embargo, esto también implica que los detalles de cómo se maneja la escalabilidad son dependientes de la implementación y pueden variar ampliamente entre diferentes sistemas.

Desarrollo y ciclo de vida

El proceso de desarrollo en una arquitectura hexagonal comienza con la definición del dominio de aplicación o del core. Aquí es donde se modela la lógica de negocio de la aplicación, incluyendo las reglas y comportamientos que la definen.

Una vez definido el core, se identifican los diferentes puertos. Los puertos primarios son las interfaces que representan las operaciones que el dominio de la aplicación puede realizar, mientras que los puertos secundarios son las interfaces a través de las cuales el dominio de la aplicación interactúa con los sistemas externos.

Después de definir los puertos, se implementan los adaptadores. Los adaptadores son los componentes que interactúan con el mundo exterior, y cada uno de ellos está asociado con un puerto específico. Los adaptadores para los puertos primarios interactúan con los usuarios o los sistemas externos que invocan operaciones en el dominio de la aplicación, mientras que los adaptadores para los puertos secundarios interactúan con los sistemas externos a los que el dominio de la aplicación necesita acceder.

Durante el desarrollo, es importante mantener la separación entre el dominio de la aplicación y los adaptadores. Esto permite cambiar o reemplazar los adaptadores sin afectar la lógica de negocio.

El ciclo de vida de una arquitectura hexagonal sigue un proceso iterativo e incremental. A medida que las necesidades del negocio cambian, es probable que la lógica de negocio en el dominio de la aplicación necesite ser actualizada. Esto puede implicar la adición de nuevas operaciones, la modificación de las operaciones existentes o la eliminación de operaciones que ya no se necesitan.

Además, puede ser necesario añadir, modificar o eliminar adaptadores para reflejar los cambios en los sistemas externos con los que interactúa el dominio de la aplicación. Esto podría ser necesario, por ejemplo, si se decide cambiar a una nueva base de datos, si se añade un nuevo canal de usuario (como una aplicación móvil), o si se decide integrar con un nuevo servicio externo.

En cada iteración, es importante asegurarse de que se mantenga la separación entre el dominio de la aplicación y los adaptadores, y que las pruebas adecuadas estén en lugar para garantizar la correcta operación del sistema.

Ciclo de vida en la arquitectura hexagonal

Casos de uso

Los casos de uso más habituales para la Arquitectura Hexagonal son:

  • Desarrollo de sistemas independientes del entorno: es especialmente útil en contextos donde se quiere que la lógica de negocio sea independiente del entorno de ejecución y de los sistemas externos. Por ejemplo, podría utilizarse en una aplicación empresarial que necesita interactuar con diferentes bases de datos, servicios web y usuarios, pero que quiere mantener su lógica de negocio agnóstica de los detalles de estas interacciones.
  • Sistemas con requisitos de pruebas rigurosas: Dado que la arquitectura hexagonal facilita el aislamiento de la lógica de negocio de los sistemas externos, es una buena opción para sistemas que necesitan ser sometidos a pruebas rigurosas. Los adaptadores pueden ser fácilmente reemplazados por adaptadores de prueba que simulan el comportamiento de los sistemas externos, permitiendo así probar la lógica de negocio en un entorno controlado sin depender de la disponibilidad o estado de estos sistemas.
  • Sistemas con cambios frecuentes en los sistemas externos: En sistemas que necesitan adaptarse a cambios frecuentes en los sistemas externos con los que interactúan, esta arquitectura puede resultar útil. Como los adaptadores son los únicos componentes que necesitan ser cambiados cuando cambia un sistema externo, estos cambios pueden hacerse de una manera controlada y con un impacto mínimo en la lógica de negocio.
  • Aplicaciones con necesidades de refactorización o re-escritura: La arquitectura hexagonal es también una aproximación correcta para la refactorización o re-escritura de aplicaciones existentes que tienen una arquitectura monolítica o una arquitectura de capas tradicional. La descomposición de la aplicación en un dominio de aplicación y adaptadores puede ayudar a clarificar la lógica de negocio y facilitar el cambio a una arquitectura más modular y flexible.
  • Aplicaciones con varios canales de interacción: es ideal para aplicaciones que deben interactuar con diferentes canales de entrada y salida. Por ejemplo, una aplicación que debe admitir interfaces de usuario web, aplicaciones móviles, interfaces de línea de comandos y APIs para otros servicios. En este caso, cada uno de estos canales sería un adaptador en la arquitectura hexagonal, lo que permitiría a la lógica central de la aplicación permanecer sin cambios mientras se agregan, modifican o eliminan canales de interacción.
  • Sistemas distribuidos: Los sistemas que se componen de múltiples servicios o componentes distribuidos también pueden beneficiarse de esta arquitectura. En este caso, cada servicio o componente podría ser modelado como un adaptador que se comunica con la lógica de negocio central a través de un puerto. Esto facilitaría la implementación de patrones de diseño de sistemas distribuidos, como el enrutamiento de mensajes, la gestión de transacciones distribuidas y la tolerancia a fallos.