我有这个简单的域模型。用户执行具有持续时间和距离的活动。对于每个活动,可以分配使用的齿轮项目(用于跑步的鞋子)。分配后,持续时间和距离将添加到齿轮项目的总计中。
Activity和GearItem都是聚合根。当我将项目分配给活动时,我需要将项目ID添加到活动中并更新项目上的总计。
如何协调此操作?
GearItem.AssignUsage()
?Activity.AddItem()
GearItem.AssignUsage()
之后调用Activity.AddItem()
(它违反了每个AR的一个交易规则)。GearItem AR,包含来自活动的总计:
public class GearItem: Entity<GearItem>
{
...
public Usage AssignedUsage { get; private set; };
public void AssignUsage(Activity activity)
{
AssignedUsage = new Usage(AssignedUsage.Time + activity.Time,
AssignedUsage.Distance + activity.Distance, AssignedUsage.Uses + 1);
}
}
活动AR,包含已分配的GearItems的ID:
public class Activity: Entity<Activity>
{
...
private List<int> items = new List<int>();
public TimeSpan Time { get; }
public double Distance { get; }
public bool AddItem(GearItem item)
{
if (items.Contains(item.Id)) return false;
items.Add(item.Id);
return true;
}
}
使用价值对象:
public class Usage: ValueObject<Usage>
{
...
public TimeSpan Time { get; private set; }
public double Distance { get; private set; }
public int Uses { get; private set; }
}
答案 0 :(得分:2)
您应该抵制在单个事务中修改两个聚合的诱惑。有两条规则可以帮助您不要这样做:
因此,为了更新AssignedUsage
的{{1}},您将使用最终的一致性。
您可以使用域事件或定期计算所有GearItem
的使用情况来执行此操作。
使用域名活动:
在为活动分配GearItems
后,您发布GearItem
个活动,该活动由在新交易中调用GearItemAssignedToActivity
的{{1}}抓住(首先加载GearItem使用其来自存储库的ID。)
定期更新GearItem的使用
在cron /计划任务/您重置每个Process manager
的使用情况的任何内容中,然后加载每个GearItem.AssignUsage(Time,Distance)
并为每个已分配的GearItem
加载并致电Activity
。< / p>
另外,我建议您解耦两个聚合并且不传递对方法调用的引用。例如,您不应将整个活动聚合传递给GearItem.AssignUsage(Time,Distance)
方法,而只传递所需的属性。这样,GearItem
一定不能知道或取决于整个GearItem.AssignUsage
。