Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Sugerencia
Este contenido es un extracto del libro electrónico, ".NET Microservices Architecture for Containerized .NET Applications" (Arquitectura de microservicios de .NET para aplicaciones de .NET contenedorizadas), disponible en Documentación de .NET o como un PDF descargable y gratuito que se puede leer sin conexión.
Defina un modelo de dominio enriquecido para cada microservicio empresarial o Contexto enlazado.
El objetivo es crear un único modelo de dominio cohesivo para cada microservicio empresarial o contexto enlazado (BC). Tenga en cuenta, sin embargo, que un microservicio BC o empresarial a veces podría estar compuesto de varios servicios físicos que comparten un modelo de dominio único. El modelo de dominio debe capturar las reglas, el comportamiento, el lenguaje empresarial y las restricciones del único microservicio de negocio o contexto enlazado que representa.
Patrón de entidad de dominio
Las entidades representan objetos de dominio y se definen principalmente por su identidad, continuidad y persistencia a lo largo del tiempo, y no solo por los atributos que los componen. Como dice Eric Evans, "un objeto definido principalmente por su identidad se denomina entidad". Las entidades son muy importantes en el modelo de dominio, ya que son la base de un modelo. Por lo tanto, debe identificarlos y planificarlos con cuidado.
La identidad de una entidad puede cruzar varios microservicios o contextos enlazados.
La misma identidad (es decir, el mismo Id
valor, aunque quizás no sea la misma entidad de dominio) se puede modelar en varios contextos enlazados o microservicios. Sin embargo, esto no implica que la misma entidad, con los mismos atributos y lógica se implementaría en varios contextos enlazados. En su lugar, las entidades de cada contexto enlazado limitan sus atributos y comportamientos a los necesarios en el dominio del contexto enlazado.
Por ejemplo, la entidad compradora puede tener la mayoría de los atributos de una persona que están definidos en la entidad de usuario del microservicio de identidad o perfil, incluida la identidad. Pero la entidad compradora en el microservicio de ordenación podría tener menos atributos, ya que solo ciertos datos del comprador están relacionados con el proceso de pedido. El contexto de cada microservicio o contexto enlazado afecta a su modelo de dominio.
Las entidades de dominio deben implementar el comportamiento además de implementar atributos de datos.
Una entidad de dominio en DDD debe implementar la lógica de dominio o el comportamiento relacionados con los datos de entidad (el objeto al que se accede en memoria). Por ejemplo, como parte de una clase de entidad de pedido, debe tener lógica de negocios y operaciones implementadas mediante métodos para tareas como añadir un artículo al pedido, validación de datos y cálculo total. Los métodos de la entidad se encargan de las invariables y reglas de la entidad en lugar de tener esas reglas distribuidas en la capa de aplicación.
En la figura 7-8 se muestra una entidad de dominio que implementa no solo atributos de datos, sino operaciones o métodos con lógica de dominio relacionada.
Figura 7-8. Ejemplo de diseño de entidad de dominio que implementa datos más comportamiento
Una entidad de modelo de dominio implementa comportamientos a través de métodos, es decir, no es un modelo "anémico". Por supuesto, a veces puede haber entidades que no implementen ninguna lógica dentro de la clase de entidad. Esto puede ocurrir en entidades secundarias dentro de un agregado si la entidad secundaria no tiene ninguna lógica especial porque la mayoría de la lógica se define en la raíz de agregado. Si tiene un microservicio complejo que tiene lógica implementada en las clases de servicio en lugar de en las entidades de dominio, podría caer en el modelo de dominio anémico, que se explica en la sección siguiente.
Modelo de dominio enriquecido frente al modelo de dominio anémico
En su publicación AnemicDomainModel, Martin Fowler describe un modelo de dominio anémico de esta manera:
El síntoma básico de un modelo de dominio anémico es que a primera vista parece real. Hay objetos, muchos denominados después de los nombres del espacio de dominio, y estos objetos están conectados con las relaciones enriquecidas y la estructura que tienen los modelos de dominio verdaderos. Lo interesante aparece cuando se examina el comportamiento y se descubre que apenas hay comportamiento en estos objetos, lo que los convierte en poco más que conjuntos de captadores y establecedores.
Por supuesto, cuando se usa un modelo de dominio anémico, esos modelos de datos se usarán desde un conjunto de objetos de servicio (denominados tradicionalmente la capa de negocio) que capturan todo el dominio o la lógica de negocios. La capa empresarial se sitúa encima del modelo de datos y utiliza el modelo de datos como si fueran datos.
El modelo de dominio anémico es simplemente un diseño de estilo de procedimiento. Los objetos de entidad anémicos no son objetos reales porque carecen de comportamiento (métodos). Solo contienen propiedades de datos y, por tanto, no es un diseño orientado a objetos. Al colocar todo el comportamiento en objetos de servicio (la capa de negocio), básicamente termina con scripts de transacción o código de espaguetis y, por lo tanto, pierde las ventajas que proporciona un modelo de dominio.
Independientemente de si el microservicio o el contexto enlazado es muy sencillo (un servicio CRUD), el modelo de dominio anémico en forma de objetos de entidad con solo propiedades de datos podría ser lo suficientemente bueno, y es posible que no valga la pena implementar patrones DDD más complejos. En ese caso, será simplemente un modelo de persistencia, porque se ha creado deliberadamente una entidad solo con datos para fines CRUD.
Por ese motivo las arquitecturas de microservicios son perfectas para un enfoque de múltiples arquitecturas según cada contexto delimitado. Por ejemplo, en eShopOnContainers, el microservicio de ordenación implementa patrones DDD, pero el microservicio de catálogo, que es un servicio CRUD simple, no.
Algunas personas dicen que el modelo de dominio anémico es un antipatrón. Realmente depende de lo que esté implementando. Si el microservicio que está creando es lo suficientemente sencillo (por ejemplo, un servicio CRUD), siguiendo el modelo de dominio anémico, no es un antipatrón. Sin embargo, si necesitas abordar la complejidad del dominio de un microservicio que tiene muchas reglas de negocio cambiantes, el modelo de dominio anémico podría ser un antipatrón para ese microservicio o Contexto Delimitado. En ese caso, diseñarlo como un modelo enriquecido con entidades que contienen datos más comportamiento, así como implementar patrones DDD adicionales (agregados, objetos de valor, etc.) puede tener grandes ventajas para el éxito a largo plazo de dicho microservicio.
Recursos adicionales
DevIQ. Entidad de dominio
https://deviq.com/entity/Martin Fowler. El modelo de dominio
https://martinfowler.com/eaaCatalog/domainModel.htmlMartin Fowler. El modelo de dominio anémico
https://martinfowler.com/bliki/AnemicDomainModel.html
El patrón de objeto de valor
Como ha señalado Eric Evans, "Muchos objetos no tienen identidad conceptual. Estos objetos describen ciertas características de una cosa".
Una entidad requiere una identidad, pero hay muchos objetos en un sistema que no, como el patrón Value Object. Un objeto value es un objeto sin identidad conceptual que describe un aspecto de dominio. Se trata de objetos que se instancian para representar elementos de diseño que solo te preocupan temporalmente. Te preocupas por lo que son, no por quiénes son. Algunos ejemplos incluyen números y cadenas, pero también pueden ser conceptos de nivel superior, como grupos de atributos.
Algo que es una entidad de un microservicio podría no ser una entidad en otro microservicio, porque en el segundo caso, el contexto enlazado podría tener un significado diferente. Por ejemplo, una dirección de una aplicación de comercio electrónico podría no tener una identidad en absoluto, ya que podría representar solo un grupo de atributos del perfil del cliente para una persona o empresa. En este caso, la dirección debe clasificarse como un objeto de valor. Sin embargo, en una aplicación para una empresa de servicios de energía eléctrica, la dirección del cliente podría ser importante para el dominio empresarial. Por lo tanto, la dirección debe tener una identidad para que el sistema de facturación se pueda vincular directamente a la dirección. En ese caso, una dirección debe clasificarse como una entidad de dominio.
Una persona con un nombre y apellido suele ser una entidad porque una persona tiene identidad, incluso si el nombre y el apellido coinciden con otro conjunto de valores, como si esos nombres también hacen referencia a una persona diferente.
Los objetos value son difíciles de administrar en bases de datos relacionales y ORM como Entity Framework (EF), mientras que en las bases de datos orientadas a documentos son más fáciles de implementar y usar.
EF Core 2.0 y versiones posteriores incluyen la característica Entidades de propiedad que facilita el control de objetos de valor, como veremos en detalle más adelante.
Recursos adicionales
Martin Fowler. Patrón de objeto de valor
https://martinfowler.com/bliki/ValueObject.htmlObjeto de Valor
https://deviq.com/value-object/Objetos de valor en desarrollo de Test-Driven
https://leanpub.com/tdd-ebook/read#leanpub-auto-value-objectsEric Evans. "Domain-Driven Design: Tackling Complexity in the Heart of Software" (Diseño orientado al dominio: abordar la complejidad en el corazón del software). (Libro; incluye una explicación de los objetos de valor)
https://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/
El patrón de agregado
Un modelo de dominio contiene clústeres de diferentes entidades de datos y procesos que pueden controlar un área significativa de funcionalidad, como el suministro de pedidos o el inventario. Una unidad DDD más específica es el agregado, que describe un clúster o grupo de entidades y comportamientos que se pueden tratar como una unidad cohesiva.
Normalmente, defines un agregado basado en las transacciones que necesitas. Un ejemplo clásico es un pedido que también contiene una lista de elementos de pedido. Normalmente, un elemento de pedido será una entidad. Pero será una entidad secundaria dentro del agregado de pedido, que también contendrá la entidad de pedido como su entidad raíz, denominada normalmente raíz agregada.
La identificación de agregados puede ser difícil. Un agregado es un grupo de objetos que deben ser coherentes juntos, pero no puede elegir un grupo de objetos y etiquetarlos como agregados. Debe empezar con un concepto de dominio y pensar en las entidades que se usan en las transacciones más comunes relacionadas con ese concepto. Esas entidades que deben ser coherentes de forma transaccional son las que forman un agregado. Pensar en las operaciones de transacción probablemente es la mejor manera de identificar agregados.
El modelo de raíz agregada o entidad raíz
Un agregado se compone de al menos una entidad: la raíz agregada, también denominada entidad raíz o entidad principal. Además, puede tener varias entidades secundarias y objetos de valor, con todas las entidades y objetos que funcionan conjuntamente para implementar el comportamiento y las transacciones necesarios.
El propósito de una raíz de agregado es garantizar la coherencia del agregado; debe ser el único punto de entrada para las actualizaciones del agregado a través de métodos o operaciones en la clase raíz agregada. Debe realizar cambios en las entidades dentro del agregado solo a través de la raíz del agregado. Es el guardián de la coherencia del conjunto, teniendo en cuenta todas las invariantes y reglas de coherencia que podrían ser necesarias cumplir en el conjunto. Si cambia de forma independiente una entidad secundaria o un objeto de valor, la raíz de agregado no puede asegurarse de que el agregado está en un estado válido. Sería como una mesa con una pata coja. Mantener la coherencia es el propósito principal de la raíz agregada.
En la figura 7-9, puede ver agregados de ejemplo como el agregado de comprador, que contiene una sola entidad (el agregado raíz Comprador). El agregado de pedido contiene varias entidades y un objeto de valor.
Figura 7-9. Ejemplo de agregados con varias entidades o únicas
Un modelo de dominio DDD se compone de agregados, un agregado puede tener solo una entidad o más, y también puede incluir objetos de valor. Observe que el agregado Comprador podría tener entidades secundarias adicionales, según su dominio, como ocurre en el microservicio de pedidos de la aplicación de referencia eShopOnContainers. En la figura 7-9 solo se muestra un caso en el que el comprador tiene una sola entidad, como ejemplo de un agregado que contiene solo una raíz de agregado.
Con el fin de mantener la separación de agregados y mantener claros los límites entre ellos, es un procedimiento recomendado en un modelo de dominio DDD para no permitir la navegación directa entre agregados y tener solo el campo de clave externa (FK), tal como se implementa en el modelo de dominio de microservicios de pedidos en eShopOnContainers. La entidad Order solo tiene un campo de clave externa para el comprador, pero no una propiedad de navegación de EF Core, como se muestra en el código siguiente:
public class Order : Entity, IAggregateRoot
{
private DateTime _orderDate;
public Address Address { get; private set; }
private int? _buyerId; // FK pointing to a different aggregate root
public OrderStatus OrderStatus { get; private set; }
private readonly List<OrderItem> _orderItems;
public IReadOnlyCollection<OrderItem> OrderItems => _orderItems;
// ... Additional code
}
La identificación y el trabajo con agregados requieren investigación y experiencia. Para obtener más información, consulte la siguiente lista de recursos adicionales.
Recursos adicionales
Vaughn Vernon. Diseño de agregado efectivo: parte I: modelado de un único agregado (de https://dddcommunity.org/)
https://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_1.pdfVaughn Vernon. Diseño de agregado efectivo: parte II: hacer que los agregados funcionen juntos (de https://dddcommunity.org/)
https://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_2.pdfVaughn Vernon. Diseño de agregado efectivo: parte III: obtención de información a través de la detección (de https://dddcommunity.org/)
https://dddcommunity.org/wp-content/uploads/files/pdf_articles/Vernon_2011_3.pdfSergio Grybniak. Patrones de diseño táctico de DDD
https://www.codeproject.com/Articles/1164363/Domain-Driven-Design-Tactical-Design-Patterns-PartChris Kemp. Desarrollo de microservicios transaccionales mediante agregados
https://www.infoq.com/articles/microservices-aggregates-events-cqrs-part-1-richardsonDevIQ. El patrón de agregado
https://deviq.com/aggregate-pattern/