En primer lugar, debe exponer interfaces para obtener referencias a su raíz de agregado (es decir, orden()). Utilice el patrón de fábrica para volver a generar una nueva instancia de la raíz agregada (es decir, orden()).
Dicho esto, los métodos en sus contros de Raíz agregada tienen acceso a sus objetos relacionados, no a sí mismo. Además, nunca exponga un tipo complejo como público en las raíces agregadas (es decir, la colección IList Lines() que indicó en el ejemplo). Esto infringe la ley de decremeter (sp ck), que dice que no puede "Dot Walk" su camino a métodos, como Order.Lines.Add().
Y también, viola la regla que permite al cliente acceder a una referencia a un objeto interno en una raíz agregada. Raíces agregadas can devuelve una referencia de un objeto interno. Siempre y cuando el cliente externo no tenga permiso para mantener una referencia a ese objeto. Es decir, su "OrderLine" pasa a RemoveLine(). No puede permitir que el cliente externo controle el estado interno de su modelo (es decir, Order() y sus OrderLines()). Por lo tanto, debe esperar que OrderLine sea una nueva instancia para actuar en consecuencia.
public interface IOrderRepository
{
Order GetOrderByWhatever();
}
internal interface IOrderLineRepository
{
OrderLines GetOrderLines();
void RemoveOrderLine(OrderLine line);
}
public class Order
{
private IOrderRepository orderRepository;
private IOrderLineRepository orderLineRepository;
internal Order()
{
// constructors should be not be exposed in your model.
// Use the Factory method to construct your complex Aggregate
// Roots. And/or use a container factory, like Castle Windsor
orderRepository =
ComponentFactory.GetInstanceOf<IOrderRepository>();
orderLineRepository =
ComponentFactory.GetInstanceOf<IOrderLineRepository>();
}
// you are allowed to expose this Lines property within your domain.
internal IList<OrderLines> Lines { get; set; }
public RemoveOrderLine(OrderLine line)
{
if (this.Lines.Exists(line))
{
orderLineRepository.RemoveOrderLine(line);
}
}
}
no olvide su fábrica para crear nuevas instancias de la Orden():
public class OrderFactory
{
public Order CreateComponent(Type type)
{
// Create your new Order.Lines() here, if need be.
// Then, create an instance of your Order() type.
}
}
Su cliente externo tiene el derecho de acceder al IOrderLinesRepository directamente, a través de la interfaz para obtener una referencia de un objeto de valor dentro de su raíz agregada. Pero, trato de bloquear eso forzando mis referencias fuera de los métodos de la Raíz Agregada. Por lo tanto, podría marcar el IOrderLineRepository anterior como interno para que no quede expuesto.
En realidad, agrupo todas mis creaciones de raíz agregada en varias fábricas. No me gustó el enfoque de "Algunas raíces agregadas tendrán fábricas para tipos complejos, otras no". Es mucho más fácil tener la misma lógica seguida a lo largo del modelado del dominio. "Oh, entonces Sales() es una raíz agregada como Order(). También debe haber una fábrica para eso".
Una nota final es que si tiene una combinación, es decir, SalesOrder(), que utiliza dos modelos de Sales() y Order(), usaría un Servicio para crear y actuar en esa instancia de SalesOrder() como ninguno Sales() or Order() Aggregate Roots, ni sus repositorios o fábricas, poseen control sobre la entidad SalesOrder().
Recomiendo encarecidamente this free book por Abel Avram y Floyd Marinescu en Domain Drive Design (DDD) ya que responde directamente sus preguntas, en una página grande de 100 páginas de shrot. Junto con cómo desacoplar más sus entidades de dominio en módulos y tal.
Editar: añadido más código
Supongo que esta expansión significa que no está utilizando un ORM directamente en las entidades de su dominio. Esperaba poder evitar el trabajo extra que describes arriba, al tener linq a sql automáticamente persistir los cambios que realizo en el objeto de dominio ... –
y, ese es el verdadero problema. He estado haciendo lo anterior. Veo comentarios todo el tiempo en Nhibernate apoyando escenarios más avanzados, pero no he visto cómo funciona con este tipo de escenario (que no es solo el uso de POCO) – eglasius
Gracias; aunque no terriblemente ideal (falla de LTS, no es tu respuesta) esto parece confirmar mis propias corazonadas sobre cómo necesitaría hacer esto ... – Funka