首页 > 解决方案 > 领域驱动设计 - 如何实现始终有效的状态

问题描述

我有一个带有 OrderItems 的域模型 Order。

订单必须

  1. 有一个经理
  2. 至少还有一个 orderItem。

我的订单构造函数如下

public Order(Manager manager, IList<OrderItem> orderItems) 
{
    if(manager == null) throw new ArgumentNullException(nameof(manager));
    if(orderItems == null) throw new ArgumentNullException(nameof(orderItems));
    if(orderItems.Count == 0)
        throw new Exception("List must contain at least one item.");
    foreach(var item in orderItems)
        AddItem(item);
    //assign values
    this.manager = manager;
    ...
    ...
}
Manager manager;
IList<OrderItem> orderItems;
...

void AddItem(OrderItem orderItem)
{
   if(orderItem == null) throw new ArgumentNullException(nameof(orderItem));
   if(orderItems.Contains(orderItem))
       throw new Exception("Order Item duplicate");
   orderItems.Add(orderItem);
}

void CreateNewOrder(int managerId, List<int> itemIdList)
{
    Manager manager = managerRepo.FindById(managerId);
    List<OrderItem> itemList =new List<OrderItem>();
    foreach(int itemId in itemIdList)
        itemList.Add(itemRepo.FindById(itemId));

    Order order = new Order(manager, itemList);
    orderRepo.Add(order);
}

我认为它接近持久性模型,而不是域模型。

如果我像下面这样编码怎么办?

public Order(Manager manager)
{ 
    if(manager == null) throw new ArgumentNullException(nameof(manager));
    this.manager = manager;
    ...
    ...
}

public void AddItem(OrderItem orderItem)
{
   if(orderItem == null) throw new ArgumentNullException(nameof(orderItem));
   if(orderItems.Contains(orderItem))
       throw new Exception("Order Item duplicate");
   orderItems.Add(orderItem);
}

public void ReadyForPersistence()
{
    if(orderItems.Count == 0)
        throw new Exception("Not ready for persistence");
}

void CreateNewOrder(int managerId, List<int> itemIdList)
{
    Manager manager = managerRepo.FindById(managerId);
    Order order = new Order(manager);

    //Here order has zero item, does this mean order is in invalid state?

    foreach(int itemId in itemIdList)
        order.AddItem(itemRepo.FindById(itemId));

    order.ReadyForPersistence(); 
    orderRepo.Add(order);
}

我误解了“始终有效的状态”吗?

我怎样才能正确实现“始终有效的状态模型”。

标签: c#validationdomain-driven-design

解决方案


首先,我想说持久性与您的要求无关。问题真的是:空订单在您尝试建模的领域中真的有效吗?

如果空订单是错误的或在您的域中没有任何意义,我会说立即继续并在代码中强制执行此不变量。不允许完成任何会使订单处于不一致状态的方法。应用程序级代码(在本例中为CreateNewOrder方法)最后是否具有有效顺序并不重要。另一个实现者可能会犯错误而忘记在其中添加项目;在这种情况下,您的订单不会强制执行它需要的不变量。

作为旁注,如果空订单有意义,这实际上取决于您正在从事的行业。请与您的主题专家交谈,以检查空订单是否不仅仅是名称不同的东西。您可能会发现空订单是有效的,具有自己的规则和操作,但它们有另一个名称,并且它具有一组不同的不变量,如果这样做,它可以使事情变得更加简单:您可以作为模型的一部分的“订单草稿”将作为您订单的工厂有机地工作。


推荐阅读