¿Pueden los clientes llamar a métodos en entidades distintas de la raíz agregada?

10

Evans presenta en su libro "Diseño controlado por dominio" en el Capítulo 6 "Agregados" el concepto de Agregados. Además define las reglas para traducir ese concepto en una implementación (Evans 2009, pp. 128-129):

La ENTIDAD raíz puede entregar referencias a las ENTIDADES internas a otros objetos, pero esos objetos pueden usarlas solo de manera transitoria y es posible que no se aferren a la referencia.

Después de elaborar otras reglas, las resume en este párrafo:

Agrupe las entidades y los objetos de valor en agregados y defina límites alrededor de cada uno. Elija una entidad para que sea la raíz de cada agregado y controle todo el acceso a los objetos dentro del límite a través de la raíz. Permita que los objetos externos contengan referencias solo a la raíz. Las referencias transitorias a miembros internos pueden pasarse para su uso dentro de una sola operación solamente. Debido a que la raíz controla el acceso, los cambios en las partes internas no pueden dejarlo ciego. Esta disposición hace que sea práctico hacer cumplir todos los invariantes para los objetos en el Agregado y para el Agregado en su conjunto en cualquier cambio de estado.

Entonces, ¿qué significa exactamente el uso transitorio?

Mi colega entiende que solo la raíz agregada expone una interfaz pública para los clientes. Los clientes no tendrán la oportunidad de llamar a ninguna operación en una entidad que no sea la raíz agregada.

Mi comprensión de las oraciones citadas es diferente. Entiendo que, de hecho, permite explícitamente a los clientes llamar a operaciones en entidades internas. Sin embargo, solo después de obtenerlos desde la raíz.

Entonces, tengamos un ejemplo concreto:

Digamos que un Cartconsiste en muchos Items. Cada uno Itemtiene un Quantity. El modelo debe admitir el caso de uso "Aumentar la cantidad de un artículo específico". No se pueden violar invariantes que afecten cualquier cosa fuera del artículo.

¿Está violando un modelo las reglas citadas anteriormente, cuando un cliente puede hacer esto llamando cart.item(itemId).increaseQuantity()o si un cliente solo puede llamar cart.increaseItemQuantity(itemId)? ¿Cuál sería el beneficio de este último?

Markus Malkusch
fuente
¿Cuál tiene más sentido desde una perspectiva comercial?
Robert Harvey
Es un ejemplo artificial. Mi pregunta es sobre la interpretación de los dos párrafos citados del libro de Evans. Pero los expertos en dominios artificiales hablarían sobre "aumentar la cantidad de un artículo de carrito". De modo que el carrito, el artículo y la cantidad son parte de la UL.
Markus Malkusch
1
Su ejemplo no es más artificial que los edictos de Evans. Puede ser útil señalar que DDD no es realmente una técnica de programación, aunque hay muchas personas que intentan usarlo de esa manera.
Robert Harvey
¿Puedes compartir un poco más de texto del libro para que tus citas sin cuerpo tengan más contexto?
Robert Harvey
2
Si gracias. Lo que dice Evans es que debe permitir que la raíz agregada controle su propio estado interno (una buena práctica para cualquier clase, en realidad). Por lo tanto, probablemente tenga más sentido permitir que el carrito controle los aumentos de cantidad con cart.increaseItemQuantity(itemId), si no por otra razón, es una violación menor de la Ley de Demeter. Llamar le cart.increaseItemQuantity(itemId)permite hacer cosas como actualizar las cantidades totales del carrito.
Robert Harvey

Respuestas:

2

Mientras Itemno pueda existir sin Cartestar también presente, entonces no hay diferencia entre las dos opciones. Es posible mantener invariantes en ambos casos.

En el caso de que el método esté activado Item, Itempuede "notificar" a su carrito principal para verificar el invariante cuando necesita cambiar su propio estado. Esto hace las cosas un poco más complicadas, porque entonces hay una dependencia cíclica entre Itemy Cart(lo que supongo que no es un problema gracias a la suposición en la primera oración y algo que la OMI debe existir de cualquier manera).

En caso de que el método esté Cartactivado, lo hace más simple, porque no hay necesidad de Itemhacer referencia Cart. Pero lo complica porque ahora el método no solo verifica la invariabilidad y cambia el estado. Pero también debe asegurarse de que el artículo (o su ID) sea válido para esto Cart. En el otro caso, esto ya se maneja mediante un método que consulta el artículo dado del carrito.

tl; dr; Ambas opciones tienen claras ventajas y desventajas y ninguna parece ser obviamente mejor o peor que otra.

Eufórico
fuente