Si has llegado a este artículo a través de una búsqueda orgánica, es razonable asumir que ya posees una sólida base de conocimientos en varios aspectos fundamentales para entender cómo diseñar eficientemente un agregado. Es más, es muy probable que ya estés versado en conceptos cruciales como el Contexto Delimitado, los Submodelos, las Entidades y los Objetos de Valor, entre otros. Estos términos, pilares fundamentales de la arquitectura de software, son esenciales para entender correctamente cómo diseñar agregados en el marco del Domain Driven Design (DDD).
Sin embargo, si estos términos te son ajenos porque eres un lector frecuente de nuestro blog, pero aún no has tenido la oportunidad de familiarizarte con estos conceptos, no te preocupes. En este artículo tomaremos el tiempo para explicar brevemente qué es cada uno de ellos, cómo se utilizan en el contexto del diseño de software y, sobre todo, cómo pueden ayudarte a desarrollar sistemas más robustos, escalables y mantenibles. Así, tanto si eres un veterano en estas materias como si estás dando tus primeros pasos, este artículo pretende aportarte una visión más clara y profunda de lo que implica un buen diseño de agregado en DDD.
Términos que debes conocer para diseñar agregados en el marco Domain Driven Design
Value Objects
Primero, hablemos de los Objetos de Valor (Value Objects). En el Domain Driven Design, un Objeto de Valor es una pieza diminuta pero crucial del modelo de dominio, que contiene atributos, pero no tiene una identidad individual. Usualmente son inmutables y se comparan según el estado que contienen y no por una identidad. Ejemplos comunes de Objetos de Valor pueden ser un correo electrónico, una contraseña o una dirección.
Bounded Contexts
A continuación, tenemos los Contextos Delimitados (Bounded Contexts), que es un término esencial para definir las fronteras de los distintos modelos de dominio de una aplicación. Un Contexto Delimitado es la definición de un espacio donde un modelo en particular aplica y tiene sentido. Suele encapsular un subdominio de la lógica del negocio y se utiliza para dividir un sistema grande y complejo en subsistemas más manejables.
Entities
En conjunto con estos conceptos, encontramos otro muy familiar para cualquier desarrollador: las Entidades. Las Entidades se distinguen por tener una identidad única y consistente, a diferencia de los Objetos de Valor. Cada instancia de una entidad se caracteriza por su individualidad innegociable. Su identidad se mantiene constante a lo largo de su vida útil, incluso si sus atributos pueden variar. Por ejemplo, en el contexto comercial, cada producto o cada cliente posee características que lo distinguen de los demás y, por tanto, cada uno de ellos puede considerarse una entidad. El hecho de que cada producto tenga su identificador único o que cada cliente pueda ser identificado por su correo electrónico ilustra el carácter individual y perpetuo que define a las entidades
Submodels
Finalmente, los Submodelos son partes del sistema que representan un detalle o aspecto específico y necesario del modelo dentro de un Contexto Delimitado. Permiten dividir un sistema en partes de menor tamaño, y por lo tanto más fáciles de administrar y entender.
Aggregate
Todos los anteriores elementos no son más que bloques de construcción que mejoran la escalabilidad, mantenibilidad y cohesión de la arquitectura de software. Ahora que hemos establecido una base sólida, podemos regresar a nuestro tema principal, el diseño de agregados.
Si el Domain Driven Design (DDD) nos ha introducido un concepto nuevo, ese es el de «agregado». Antes de explicar cómo diseñarlo, conviene profundizar en por qué resulta ventajoso considerar el uso del modelo de agregado.
El primer aspecto a tener en cuenta es el del encapsulamiento. Un AggregateRoot garantiza la coherencia de un dominio y su integridad al encapsular y agrupar entidades y objetos de valor relacionados. Este grupo de entidades afines facilita significativamente la interacción con los mismos como una unidad cohesiva.
En adición, la utilización de agregados puede simplificar enormemente el Modelo del Dominio. Al tratar conglomerados de entidades y objetos de valor relacionados como una entidad única, se reduce la complejidad del modelo. Este enfoque permite a los desarrolladores centrarse más en la lógica del negocio.
En lo referente a la lógica del negocio, los agregados contribuyen a aislar las Reglas del Negocio. Las reglas y lógica del negocio quedan encapsuladas dentro de un AggregateRoot, generando por tanto una protección de la coherencia en el contexto de las reglas de negocio.
Desde el punto de vista de la gestión de persistencia, los AggregateRoots pueden representar una transacción de base de datos. Esta correspondencia puede simplificar el manejo de la persistencia, facilitando a su vez la gestión de las operaciones de las bases de datos.
Puntos clave para diseñar agregados en el marco Domain Driven Design
Habiendo comprendido el panorama general en torno al agregado y las razones por las cuales deberíamos emplearlos, procedamos a analizar cuáles son los aspectos esenciales para estructurar el agregado idóneo para nuestros submódulos.
Persistencia
Aunque no todos los submódulos están orientados a la persistencia –podemos tener un submódulo, por ejemplo, que simplemente realiza una solicitud CURL para enviar datos fuera de nuestro ecosistema–, aquellos que sí implican persistencia deben considerar que todos sus cambios son de naturaleza transaccional. Esto significa que, al momento de persistir, tendremos que almacenar el objeto completo en cada ocasión dentro del respectivo submódulo o contexto. La integridad transaccional es una de las grandes ventajas de este enfoque, ya que asegura que los datos almacenados estén siempre en un estado consistente. Además, esto nos libera de tener que escribir código adicional para manejar las posibles inconsistencias de datos, simplificando así todavía más la lógica del negocio.
Invariantes
Los agregados tienen un papel vital en la preservación de las reglas de negocio y en la garantía de la consistencia en nuestro dominio. Una forma en que los agregados realizan esta tarea es a través de la gestión de las invariantes del negocio.
Las invariantes del negocio son condiciones o reglas que siempre deben cumplirse, no importa cuándo ni dónde se vean en el ciclo de vida de un objeto de dominio. En otras palabras, son verdades que siempre son válidas para un conjunto de entidades. Estos se mantienen a través de las transacciones, lo que significa que cuando una transacción se completa, todas las invariantes en los agregados afectados se cumplen.
Por ejemplo, un «Artículo» que tiene «Valoraciones», una invariante de agregado podría ser, en este caso, hacer la media de las valoraciones. Esta es una propiedad derivada (es decir, se calcula en base a otros atributos o entidades) que quiere persistirse para evitar cálculos repetitivos. Así, cada vez que se agrega o elimina una valoración, se actualiza esta invariante para mantener la coherencia. Por lo tanto, en lugar de tener que hacer la media de las valoraciones cada vez que se necesita saber, se conserva y actualiza este valor como una propiedad del agregado ‘Artículo’.
Este enfoque optimiza en gran medida la eficiencia del sistema al reducir la necesidad de ejecutar cálculos redundantes. Sin embargo, la implementación de esta invariante de agregado plantea un desafío esencial: garantizar la sincronización continua entre este valor pre-calculado y los datos relacionados actuales.
Resulta pertinente reafirmar que la persistencia de invariantes de agregado puede simplificar de manera notable la recopilación de información derivada, incrementando al mismo tiempo la eficiencia del sistema al evitar cálculos innecesarios. A fin de definir de manera óptima el agregado, conviene pre-calcular la mayor cantidad de datos posible. No obstante, esta técnica puede originar una incongruencia temporal en los datos, y es responsabilidad del negocio decidir si dicha incongruencia puede tolerarse por un periodo determinado o si debe rectificarse inmediatamente dentro del agregado, actualizándose cada cierto tiempo o tras cada cierto número de eventos acumulados. Un ejemplo común de esta situación es el recuento de suscriptores en un video de YouTube, que a menudo demora algunos segundos en actualizarse.
En plataformas a gran escala como YouTube, se puede observar de manera evidente cómo decisiones estratégicas relacionadas con el manejo de los agregados e invariantes pueden ejercer un impacto significativo en la eficiencia global del sistema. Dentro de este entorno, uno de los campos pre-calculados de mayor relevancia podría ser, indudablemente, el contador de visualizaciones de los videos.
Ante la abundancia de interacciones que suceden cada instante, mantener un conteo en tiempo real y preciso de las visualizaciones podría resultar en un consumo considerable de recursos computacionales. En lugar de sostener un seguimiento detallado, YouTube podría optar por actualizar este dato en bloques progresivos, como, por ejemplo, de 1000 en 1000 visualizaciones, tal como se puede inferir de la imagen.
Este enfoque garantiza que el recuento de visualizaciones es no sólo razonablemente exacto, sino, además, eficiente en su mantenimiento.
No obstante, si por razones particulares el negocio determinara que el numero debe reflejar la realidad con mayor rigidez (o sea, un número exacto), será necesario asumir el coste computacional que esto implique. Esto ilustra la importancia de las decisiones comerciales en el diseño e implementación de los sistemas y su impacto en el diseño de software.
Referencias de otras Entidades
Es importante destacar que un agregado no necesariamente tiene que comprender entidades completas. En numerosos casos, puede ser más eficiente y provechoso que un agregado mantenga simplemente una referencia a una entidad en lugar de la entidad en sí misma.
Esta consideración se torna especialmente relevante en contextos de alto desempeño o en situaciones donde los recursos son limitados.
En el agregado de un Pedido, es posible que no necesitemos la totalidad de la entidad del Usuario. En su lugar, podemos simplemente requerir su identificador único (ID).
Este enfoque optimiza la utilización de la memoria y los recursos computacionales. En lugar de cargar todo el objeto de Usuario, que puede incluir una gran cantidad de atributos y relaciones, simplemente recuperamos y manejamos el identificador del Usuario, que es un valor ligero y manejable.
Este planteamiento es un buen ejemplo de cómo las decisiones de diseño e implementación pueden mejorar la eficiencia y la precisión del sistema, reforzando al mismo tiempo principios como el de la mínima exposición de datos.
Un solo agregado por caso de uso
La creación o modificación de un agregado generalmente ocurre como resultado de la ejecución de un caso de uso específico.
Los cambios en el estado del sistema se realizan a través de comportamientos bien definidos que se corresponden con casos de uso del mundo real.
Por ejemplo, en el contexto de un sistema de comercio electrónico, podríamos tener un caso de uso denominado «Crear Pedido». Este caso de uso estaría a cargo de recoger la información del usuario, los artículos que desea comprar y otros detalles pertinentes, para luego crear un nuevo agregado de Pedido y guardarlo en la base de datos.
Los agregados son responsables de crear o modificar sus entidades
Un agregado es responsable de crear y modificar sus propias entidades. Esto se logra a través de los llamados Factory Methods, que encapsulan la lógica para la creación y modificación de entidades.
Los métodos de fábrica proporcionan una manera de asegurar que un agregado siempre esté en un estado válido, ya que el propio agregado tiene el control total sobre cómo y cuándo se crean o modifican sus entidades. Este patrón promueve el encapsulamiento y fortalece la cohesión en el código.
Un ejemplo podría ser la lógica para añadir un artículo a un pedido. En lugar de permitir que los clientes del código creen directamente una entidad Articulo, el agregado Pedido podría proporcionar un método addArticle(params)
Recomendaciones
Si desean profundizar aún más en este concepto y obtener una comprensión más completa de cómo aplicarlo en sus proyectos, les recomiendo explorar los libros esenciales sobre Domain Driven Design. Dos de las obras más influyentes y autorizadas en el campo son conocidas comúnmente como el ‘libro azul’ y el ‘libro rojo’ de DDD.
El ‘libro azul’, titulado ‘Domain-Driven Design: Tackling Complexity in the Heart of Software’ escrito por Eric Evans, es una lectura obligatoria para cualquier persona interesada en DDD. Ofrece una visión profunda y detallada de la metodología, incluyendo el concepto de Agregados y muchos otros aspectos clave.
Por otro lado, el ‘libro rojo’, llamado ‘Implementing Domain-Driven Design’ y escrito por Vaughn Vernon, proporciona una guía práctica sobre cómo llevar a cabo DDD en proyectos del mundo real, lo que incluye una cobertura exhaustiva de los Agregados y su implementación efectiva.
Estos libros son recursos valiosos que te permitirán profundizar en el mundo de DDD y perfeccionar tus habilidades en el diseño de software centrado en el dominio. Así que, si deseas convertirte en expertos en Agregados y DDD, no dudes en explorar estas fuentes de conocimiento.
En hiberus, somos especialistas en Domain-Driven Design y clean arquitecture. Dedicamos cada día a mejorar y perfeccionar nuestro software. Nos respaldan años de experiencia y un constante aprendizaje, utilizando patrones arquitectónicos reconocidos para garantizar la máxima eficacia y desempeño de nuestras soluciones.
Creemos en un enfoque colaborativo y nos encantaría tener la oportunidad de trabajar junto a ti para potenciar tu sistema. Si sientes que podemos contribuir en tu organización, no dudes en contactarnos. Estamos aquí para ayudarte a alcanzar tus objetivos.
¿Quieres más información sobre nuestros servicios de agencia digital y tecnología para ecommerce?
Contacta con nuestro equipo de hiberus digital
This is an insightful post! Designing aggregates within the Domain Driven Design (DDD) framework is crucial for maintaining consistency and encapsulating business logic. I appreciate how you highlighted the importance of understanding the bounded context and ensuring that aggregates reflect the core domain model. It’s also great to see the emphasis on performance and how aggregates can help manage complexity in larger systems. Looking forward to more discussions on DDD best practices!
and also check – https://www.sparkouttech.com/ui-ux-design-agency-germany/