Adaptarse al cambio - AWS Guía prescriptiva

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

Adaptarse al cambio

Los sistemas de software tienden a complicarse. Una de las razones de esto podría ser los cambios frecuentes en los requisitos empresariales y el poco tiempo para adaptar la arquitectura del software en consecuencia. Otra razón podría ser la inversión insuficiente para configurar la arquitectura del software al principio del proyecto a fin de adaptarla a los cambios frecuentes. Sea cual sea el motivo, un sistema de software podría complicarse hasta el punto de que sea casi imposible realizar un cambio. Por lo tanto, es importante construir una arquitectura de software fácil de mantener desde el principio del proyecto. Una buena arquitectura de software puede adaptarse fácilmente a los cambios.

En esta sección se explica cómo diseñar aplicaciones fáciles de mantener mediante una arquitectura hexagonal que se adapte fácilmente a los requisitos empresariales o no funcionales.

Adaptarse a los nuevos requisitos no funcionales mediante el uso de puertos y adaptadores

Como núcleo de la aplicación, el modelo de dominio define las acciones que se requieren del mundo exterior para cumplir con los requisitos empresariales. Estas acciones se definen mediante abstracciones, que se denominan puertos. Estos puertos se implementan mediante adaptadores independientes. Cada adaptador es responsable de la interacción con otro sistema. Por ejemplo, puede tener un adaptador para el repositorio de la base de datos y otro adaptador para interactuar con una API de terceros. El dominio no conoce la implementación del adaptador, por lo que es fácil reemplazar un adaptador por otro. Por ejemplo, la aplicación puede cambiar de una base de datos SQL a una base de datos NoSQL. En este caso, se debe desarrollar un nuevo adaptador para implementar los puertos definidos por el modelo de dominio. El dominio no depende del repositorio de la base de datos y utiliza abstracciones para interactuar, por lo que no sería necesario cambiar nada en el modelo de dominio. Por lo tanto, la arquitectura hexagonal se adapta con facilidad a los requisitos no funcionales.

Se adapta a los nuevos requisitos empresariales mediante el uso de comandos y controladores de comandos

En la arquitectura clásica en capas, el dominio depende de la capa de persistencia. Si desea cambiar el dominio, también tendrá que cambiar la capa de persistencia. En comparación, en la arquitectura hexagonal, el dominio no depende de otros módulos del software. El dominio es el núcleo de la aplicación y todos los demás módulos (puertos y adaptadores) dependen del modelo de dominio. El dominio utiliza el principio de inversión de dependencias para comunicarse con el mundo exterior a través de los puertos. La ventaja de la inversión de dependencias es que puede cambiar el modelo de dominio libremente sin miedo a descifrar otras partes del código. Como el modelo de dominio refleja el problema empresarial que se intenta resolver, actualizar el modelo de dominio para adaptarlo a los cambiantes requisitos empresariales no es un problema.

Al desarrollar software, la separación de las preocupaciones es un principio importante a seguir. Para lograr esta separación, puede utilizar un patrón de comandos ligeramente modificado. Se trata de un patrón de diseño conductual en el que toda la información necesaria para completar una operación se encapsula en un objeto de comando. A continuación, los controladores de comandos procesan estas operaciones. Los controladores de comandos son métodos que reciben un comando, modifican el estado del dominio y, a continuación, devuelven una respuesta a la persona que llama. Puede usar diferentes clientes, como colas sincrónicas APIs o asíncronas, para ejecutar comandos. Se recomienda utilizar comandos y controladores de comandos para cada operación del dominio. Si sigue este enfoque, puede añadir nuevas funciones mediante la introducción de nuevos comandos y controladores de comandos, sin cambiar su lógica empresarial actual. Por lo tanto, el uso de un patrón de comandos facilita la adaptación a los nuevos requisitos empresariales.

Desacoplar los componentes mediante la fachada de servicio o el patrón CQRS

En la arquitectura hexagonal, los adaptadores principales son responsables de acoplar de forma flexible las solicitudes de lectura y escritura entrantes de los clientes al dominio. Hay dos formas de lograr este acoplamiento flexible: mediante un patrón de fachada de servicio o mediante el patrón de segregación de responsabilidades por consultas de comandos (CQRS).

El patrón de fachada de servicios proporciona una interfaz frontal para atender a los clientes, como la capa de presentación o un microservicio. Una fachada de servicios proporciona a los clientes varias operaciones de lectura y escritura. Se encarga de transferir las solicitudes entrantes al dominio y de mapear la respuesta recibida del dominio a los clientes. Utilizar una fachada de servicios es fácil para los microservicios que tienen una única responsabilidad y varias operaciones. Sin embargo, cuando se utiliza la fachada de servicio, es más difícil seguir los principios de responsabilidad única y de apertura y cierre. El principio de responsabilidad única establece que cada módulo debe ser responsable de una sola funcionalidad del software. El principio de apertura y cierre establece que el código debe estar abierto para su extensión y cerrado para su modificación. A medida que se extiende la fachada de servicios, todas las operaciones se agrupan en una interfaz, se encapsulan más dependencias y más desarrolladores comienzan a modificar la misma fachada. Por lo tanto, recomendamos utilizar una fachada de servicio solo si está claro que el servicio no se extenderá mucho durante el desarrollo.

Otra forma de implementar los adaptadores principales en una arquitectura hexagonal es usar el patrón CQRS, que separa las operaciones de lectura y escritura mediante consultas y comandos. Como se explicó anteriormente, los comandos son objetos que contienen toda la información necesaria para cambiar el estado del dominio. Los comandos se ejecutan mediante métodos de manejo de comandos. Las consultas, por otro lado, no alteran el estado del sistema. Su único propósito es devolver los datos a los clientes. En el patrón CQRS, los comandos y las consultas se implementan en módulos separados. Esto es especialmente ventajoso para los proyectos que siguen una arquitectura basada en eventos, ya que un comando se puede implementar como un evento que se procesa de forma asíncrona, mientras que una consulta se puede ejecutar de forma sincrónica mediante una API. Una consulta también puede usar una base de datos diferente que esté optimizada para ella. La desventaja del patrón CQRS es que su implementación lleva más tiempo que una fachada de servicio. Recomendamos usar el patrón CQRS para los proyectos que planee escalar y mantener a largo plazo. Los comandos y las consultas proporcionan un mecanismo eficaz para aplicar el principio de responsabilidad única y desarrollar software poco acoplado, especialmente en proyectos a gran escala.

El CQRS ofrece grandes beneficios a largo plazo, pero requiere una inversión inicial. Por este motivo, le recomendamos que evalúe su proyecto detenidamente antes de decidir utilizar el patrón CQRS. Sin embargo, puede estructurar la aplicación mediante comandos y controladores de comandos desde el principio sin separar las operaciones de lectura y escritura. Esto le ayudará a refactorizar fácilmente su proyecto para el CQRS si decide adoptar ese enfoque más adelante.

Escalamiento organizacional

Una combinación de arquitectura hexagonal, diseño basado en el dominio y (opcionalmente) el CQRS permite a su organización escalar rápidamente su producto. Según la Ley de Conway, las arquitecturas de software tienden a evolucionar para reflejar las estructuras de comunicación de una empresa. Históricamente, esta observación ha tenido connotaciones negativas, ya que las grandes organizaciones suelen estructurar sus equipos en función de conocimientos técnicos, como bases de datos, autobuses de servicios empresariales, etc. El problema de este enfoque es que el desarrollo de productos y funciones siempre implica preocupaciones transversales, como la seguridad y la escalabilidad, que requieren una comunicación constante entre los equipos. La estructuración de los equipos en función de las características técnicas crea compartimentos innecesarios en la organización, lo que se traduce en una mala comunicación, una falta de implicación y una pérdida de visión del panorama general. Con el tiempo, estos problemas organizativos se reflejan en la arquitectura del software.

La maniobra inversa de Conway, por otro lado, define la estructura organizacional en función de los dominios que promueven la arquitectura del software. Por ejemplo, a los equipos multidisciplinarios se les asigna la responsabilidad de un conjunto específico de contextos acotados, que se identifican mediante la DDD y la tormenta de eventos. Estos contextos acotados pueden reflejar características muy específicas del producto. Por ejemplo, el equipo de cuentas podría ser responsable del contexto de pago. Cada nueva función se asigna a un nuevo equipo que tiene responsabilidades muy cohesionadas y poco coordinadas, por lo que pueden centrarse únicamente en la entrega de esa función y reducir el tiempo de comercialización. Los equipos se pueden escalar en función de la complejidad de las funciones, por lo que las funciones complejas se pueden asignar a más ingenieros.