Uso de un diseño basado en dominios táctico para diseñar microservicios
El diseño controlado por dominio (DDD) se opone a la idea de tener un único modelo unificado para todo el sistema. En su lugar, fomenta la división del sistema en contextos limitados, cada uno con su propio modelo. Durante la fase estratégica de DDD, se mapea el dominio empresarial y se definen contextos delimitados para los modelos de dominio.
El diseño basado en dominios táctico consiste en definir los modelos de dominio con más precisión. Los patrones tácticos se aplican dentro de un único contexto delimitado. En una arquitectura de microservicios, donde cada contexto enlazado es un candidato para microservicios, los patrones de entidad y agregado son de nota. La aplicación de estos patrones ayuda a identificar los límites naturales de los servicios de la aplicación. Para obtener más información, consulte Identificación de los límites de microservicios. Como principio general, un microservicio no debe ser menor que un agregado y no mayor que un contexto delimitado.
En este artículo se revisan los patrones tácticos y, a continuación, se aplican al contexto enlazado de envío en la aplicación Drone Delivery.
Información general sobre los patrones tácticos
En esta sección se proporciona un breve resumen de los patrones de DDD tácticos. Si está familiarizado con DDD, puede optar por omitirlo. Estos patrones se describen con más detalle en los capítulos 5 y 6 del libro de Eric Evans, y en Implementing Domain-Driven Design by Vaughn Vernon.
Entidades. Una entidad es un objeto con una identidad única que persiste en el tiempo. Por ejemplo, en una aplicación bancaria, las cuentas y los clientes serían entidades.
Una entidad tiene un identificador único en el sistema, que se puede usar para buscar la entidad o para recuperarla. Eso no significa que el identificador siempre se exponga directamente a los usuarios. Podría ser un identificado único (GUID) o una clave principal de una base de datos.
Una identidad puede abarcar varios contextos enlazados y puede persistir más allá de la duración de la aplicación. Por ejemplo, los números de cuenta bancaria o los identificadores emitidos por el gobierno no están vinculados a una aplicación específica.
Los atributos de una entidad pueden cambiar con el tiempo. Por ejemplo, el nombre o la dirección de una persona pueden cambiar, pero siguen siendo el mismo individuo.
Objetos de valor. Un objeto de valor no tiene identidad. Solo se define mediante los valores de sus atributos. Los objetos value son inmutables. Para actualizar un objeto de valor, se crea una nueva instancia para reemplazar la antigua. Los objetos value pueden incluir métodos que encapsulan la lógica de dominio, pero esos métodos no deben producir efectos secundarios ni modificar el estado del objeto. Entre los ejemplos comunes de objetos de valor se incluyen colores, fechas y horas y valores de moneda.
Agregados. Un agregado define un límite de coherencia alrededor de una o varias entidades. Una entidad exacta en un agregado es la raíz. La búsqueda se realiza con el identificador de la entidad raíz. Cualquier otra entidad en el agregado es secundaria de la raíz y se hace referencia a ella siguiendo punteros desde esta.
El propósito de un agregado es modelar las invariantes transaccionales. Las cosas en el mundo real tienen redes complejas de relaciones. Los clientes crean pedidos, los pedidos contienen productos, los productos tienen proveedores y así sucesivamente. Si la aplicación modifica varios objetos relacionados, ¿cómo podemos garantizar la coherencia? ¿Cómo se realiza el seguimiento de los elementos invariables y cómo se aplican?
A menudo, las aplicaciones tradicionales han usado las transacciones de base de datos para asegurar la coherencia. En una aplicación distribuida, sin embargo, eso a menudo no es factible. Una sola transacción comercial puede abarcar varios almacenes de datos, puede ser de ejecución prolongada o implicar a servicios de terceros. En última instancia, depende de la aplicación, no del nivel de datos, el aplicar los valores invariables necesarios para el dominio. Eso es lo que los agregados se supone que modelan.
Nota
Un agregado puede constar de una sola entidad, sin entidades secundarias. Lo que lo convierte en agregado es el límite transaccional.
Servicios de aplicación y de dominio. En la terminología del diseño basado en dominios, un servicio es un objeto que implementa alguna lógica sin mantener ningún estado. Evans distingue entre servicios de dominio, que encapsulan la lógica del dominio, y servicios de aplicación, que proporcionan la funcionalidad técnica, como la autenticación del usuario o el envío de un mensaje SMS. Los servicios de dominio a menudo se utilizan para modelar el comportamiento que abarca varias entidades.
Nota
El término servicio está saturado en el desarrollo de software. La definición que se usa aquí no está relacionada directamente con los microservicios.
Eventos de dominio. Los eventos de dominio pueden notificar a otras partes del sistema cuando se produce algo. Como sugiere el nombre, los eventos de dominio deben representar algo significativo dentro del dominio. Por ejemplo, "se insertó un registro en una tabla" no es un evento de dominio. "Se canceló una entrega" es un evento de dominio. Los eventos de dominio son especialmente importantes en una arquitectura de microservicios. Dado que los microservicios se distribuyen y no comparten almacenes de datos, los eventos de dominio permiten la coordinación entre los servicios. Para obtener más información sobre la mensajería asincrónica, consulte Comunicación entre servicios.
Hay algunos otros patrones DDD que no se tratan aquí, incluidos generadores, repositorios y módulos. Estos patrones pueden ser útiles al implementar un microservicio, pero son menos relevantes al diseñar los límites entre microservicios.
Drone Delivery: aplicación de los patrones
Empezaremos con los escenarios que el contexto delimitado de envío debe controlar.
- Un cliente puede solicitar un dron para recoger las mercancías de una empresa que se registre en el servicio de entrega de drones.
- El remitente genera una etiqueta (código de barras o RFID) para colocar en el paquete.
- Un dron recogerá el paquete en la ubicación de origen y lo entregará en la ubicación de destino.
- Cuando un cliente programa una entrega, el sistema proporciona un tiempo estimado de llegada (ETA) según la información de la ruta, las condiciones meteorológicas y los datos históricos.
- Cuando el dron está en vuelo, el usuario puede realizar el seguimiento de la ubicación actual y del tiempo estimado de llegada más reciente.
- Hasta que un dron recoja el paquete, el cliente puede cancelar una entrega.
- Se notifica al cliente cuándo se completa la entrega.
- El remitente puede solicitar al cliente la confirmación de la entrega, en forma de una firma o de una huella digital.
- Los usuarios pueden ver el historial de una entrega completada.
En estos casos, el equipo de desarrollo identificó las siguientes entidades.
- Entrega
- Paquete
- Dron
- Cuenta
- Confirmación
- Notificación
- Etiqueta
Las cuatro primeras (entrega, paquete, dron y cuenta) son todos agregados que representan los límites de la coherencia transaccional. Las confirmaciones y las notificaciones son las entidades secundarias de las entregas y las etiquetas son las entidades secundarias de los paquetes.
Los objetos de valor en este diseño incluyen la ubicación (Location), el tiempo estimado (ETA), el peso del paquete (PackageWeight) y su tamaño (PackageSize).
Para ilustrar esto, se proporciona un diagrama UML del agregado de entrega. Tenga en cuenta que contiene referencias a otros agregados, como son la cuenta, el paquete y el dron.
Hay dos eventos de dominio:
Mientras un dron está volando, la entidad Dron envía eventos DroneStatus que describen la ubicación y el estado del dron (en vuelo, en tierra).
La entidad de entrega (Delivery) envía eventos de seguimiento de la entrega (DeliveryTracking) cada vez que cambia la fase de una entrega. Los eventos DeliveryTracking incluyen DeliveryCreated, DeliveryRescheduled, DeliveryHeadedToDropoff y DeliveryCompleted.
Tenga en cuenta que estos eventos describen aspectos significativos dentro del modelo de dominio. Describen algo sobre este y no están vinculados a una construcción de un lenguaje de programación determinado.
El equipo de desarrollo identificó un área más de funcionalidad, que no encaja claramente en ninguna de las entidades descritas hasta ahora. Una parte del sistema debe coordinar todos los pasos implicados en la programación o actualización de una entrega. Por lo tanto, el equipo de desarrollo agregó dos servicios de dominio al diseño: un Programador que coordina los pasos y un Supervisor que supervisa el estado de cada paso, con el fin de detectar si se produjo un error en los pasos o se agota el tiempo de espera. Este enfoque es una variación del patrón Supervisor del agente de Scheduler.
Pasos siguientes
El siguiente paso consiste en definir los límites de cada microservicio.