19

Actualmente estoy trabajando mucho con DDD, y tengo un problema al cargar/operar en las raíces de agregación de otras raíces agregadas.Agregado Raíz hace referencia a otras raíces agregadas

Foreach Raíz agregada en mi modelo, también tengo un repositorio. Ahora el repositorio es responsable de manejar las operaciones de persistencia para la raíz.

Digamos que tengo dos raíces agregadas, con algunos miembros (entidades y objetos Value).

AggregateRoot1 y AggregateRoot2

AggregateRoot1 tiene un elemento de entidad que hace referencia a AggregateRoot2

  1. Cuando cargo AggregateRoot1, debería cargar aggregateRoot2 así?
  2. ¿Es el repositorio de aggregateRoot2 quién debería ser responsable de esto?
  3. Es así, ¿está bien que la entidad en aggregateRoot1 llame al repositorio de aggregateRoot2 para cargar?

También, cuando se crea una asociación entre la entidad en AggregateRoot1 a la AggregateRoot2, debería que hacerse a través de la entidad, o a través del repositorio para aggregateRoot2.

Espero que mi pregunta tenga sentido.

[EDIT]

solución actual

Con la ayuda de Twith2Sugars Yo he llegado con la siguiente solución:

Como se describe en la pregunta, una' raíz agregado puede tener hijos que tengan referencias a otras raíces. Al asignar root2 a uno de los miembros de root1, el repositorio de root1 será responsable de detectar este cambio y de delegar esto al repositorio de root2.

public void SomeMethod() 
{ 
    AggregateRoot1 root1 = AggregateRoot1Repository.GetById("someIdentification"); 
    root1.EntityMember1.AggregateRoot2 = new AggregateRoot2(); 
    AggregateRoot1Repository.Update(root1); 
} 

public class AggregateRoot1Repository 
{ 
    public static void Update(AggregateRoot1 root1) 
    { 
     //Implement some mechanism to detect changes to referenced roots 
     AggregateRoot2Repository.HandleReference(root1.EntityMember1, root1.EntityMember1.AggregateRoot2) 
    } 
} 

Esto es sólo un ejemplo sencillo, sin Ley de Demeter u otros mejores principios/prácticas incluidas :-)

Otros comentarios apreciados

+0

Personalmente puedo ver que este enfoque actual se está volviendo complicado y creo que la solución de DavidMasters84 es más una solución elegante. Es decir, mantener las referencias como id y extraer este tipo de lógica de dominio a un servicio de dominio. –

+0

Messy es un buen adjetivo para este enfoque. Se me permite decir que debido a que originalmente traté de implementar este problema de la misma manera, y un desastre es en lo que me encontré :) es posible que desee leer las sugerencias aquí también para una pregunta similar: http://stackoverflow.com/questions/2118088/aggregate-roots-how-far-do-the-rabbit-hole-go/4936021 # 4936021 –

+0

Te escucho, pero no hay repositorios allí para gestionar las raíces agregadas, y con buena voluntad, las relaciones entre raíces. ¿Y los Servicios de dominio para manejar comportamientos que no encajan naturalmente en una sola entidad? Me parece que hacer que el Servicio de Dominio sea responsable de manejar las referencias entre las raíces es el lugar equivocado al leer la definición de un Servicio de Dominio ... Podría estar equivocado, por lo que se agradecería un argumento respaldado, gracias. – tschmuck

Respuesta

-3

Tal vez el repositorio AggregateRoot1 podría llamar repositorio AggregateRoot2 cuando está construyendo la entidad AggregateRoot1.

No creo que esto invalide ddd ya que los repositorios todavía están a cargo de obtener/crear sus propias entidades.

+0

Consideré esto también, pero ¿qué pasa si Aggregate2 tiene una referencia a Aggregate3, y aggregate3 a otro y así uno? Potencialmente, esto podría ser un gráfico de objetos bastante grande. ¿Cuáles son las estrategias sugeridas para estos escenarios? – tschmuck

+0

Es cierto, sé que se supone que no debes preocuparte demasiado por la implementación en DDD, pero en ese momento Id lazyload los agregados si pensara que el gráfico es demasiado grande. – TWith2Sugars

+0

Ok, hasta ahora todo bien. :-) Pero cuando estoy creando la relación entre AggregateRoot1.Entity1 -> AggregateRoot2, debe hacerse a través de AggregateRootRepository1.AddRoot2ToEntity1 (root1, root2) o a través de AggregateRepository2.AddRoot2ToRoot1 (root1, root2) o una asignación más directa: root2.Entity1.AddRoot2 (root2) – tschmuck

48

He estado en esta situación yo mismo y llegué a la conclusión de que es demasiado dolor de cabeza hacer que los agregados infantiles funcionen de una manera elegante. En cambio, consideraría si realmente necesita hacer referencia al segundo agregado como hijo del primero. Hace la vida mucho más fácil si solo conserva una referencia de la ID del agregado en lugar del agregado en sí.Entonces, si hay una lógica de dominio que implica tanto a los agregados esto puede ser extraído a un servicio de dominio y ser algo como esto:

public class DomainService 
{ 
    private readonly IAggregate1Repository _aggregate1Repository; 
    private readonly IAggregate2Repository _aggregate2Repository; 

    public void DoSomething(Guid aggregateID) 
    { 
     Aggregate1 agg1 = _aggregate1Repository.Get(aggregateID); 
     Aggregate2 agg2 = _aggregate2Repository.Get(agg1.Aggregate2ID); 

     agg1.DoSomething(agg2); 
    } 
} 

EDIT:

I REALMENTE recomiendan estos artículos sobre el tema : https://vaughnvernon.co/?p=838

+1

+ 1. Esto también es lo que Vaughn Vernon argumenta en su regla 'Referencia Otro Agregado por Identidad'. Las ventajas incluyen el tamaño global del Agregado que permite un mejor rendimiento y una partición más fácil. La desventaja, supongo, es que a veces hace que el código del modelo sea menos expresivo, por lo que es una compensación como de costumbre: http://dddcommunity.org/sites/default/files/pdf_articles/Vernon_2011_2.pdf – Dmitry

+0

Con este enfoque no está almacenando la relación entre Aggregate1 y Aggregate2 en db, ¿qué harás si hay un requisito para recordar esa relación? – redzedi

+0

@redzedi - Sí, lo eres. En el ejemplo anterior, Aggregate2 almacena la ID de su Aggregate1 relacionado. –

Cuestiones relacionadas