gpt4 book ai didi

c# - 带孙子的 .NET DDD 域模式

转载 作者:太空宇宙 更新时间:2023-11-03 20:57:42 24 4
gpt4 key购买 nike

我想在我的 .NET Core 域模型中实现 DDD 模式。以下是具有聚合子实体和聚合孙实体的聚合根示例:

public class Supplier
: Entity, IAggregateRoot
{
private string _name;

private readonly List<Catalog> _catalogs;
public IReadOnlyCollection<Catalog> Catalogs => _catalogs;

protected Supplier() { _catalogs = new List<Catalog>(); }

public Supplier(string name)
{
_catalogs = new List<Catalog>();
_name = name;
}

public void AddCatalog(string name)
{
var catalog = new Catalog(name);
_catalogs.Add(catalog);
}

public void AddCatalogItem(int catalogId, string name)
{
var catalogItem = new CatalogItem(name);
_catalogs.Single(c => c.Id == catalogId).AddCatalogItem(catalogItem);
}
}

这里是聚合子项的代码:

public class Catalog
: Entity
{
private string _name;

private readonly List<CatalogItem> _catalogItems;
public IReadOnlyCollection<CatalogItem> CatalogItems => _catalogItems;

protected Catalog() { _catalogItems = new List<CatalogItem>(); }

public Catalog(string name)
{
_catalogItems = new List<CatalogItem>();
_name = name;
}

public void AddCatalogItem(CatalogItem catalogItem)
{
_catalogItems.Add(catalogItem);
}
}

和聚合孙子:

public class CatalogItem
: Entity
{
private string _name;

protected CatalogItem() { }

public CatalogItem(string name)
{
_name = name;
}
}

这是实现 DDD 模式的正确方法吗?
或者这是否违反了我不知道的 DDD 规则?

最佳答案

它本身并没有违反任何 DDD 规则 - 但它是一种经常被劝阻的方法,原因如下:

  • DDD 鼓励您根据系统需要支持的操作、流程和规则对域进行建模,同时管理状态的更改
    • 您建模的关系可能存在于现实世界中 - 它们可能有助于可视化数据 - 但它们对于您的模型真的是必需的吗?
  • DDD 中的良好做法是设计小型 聚合。聚合是真正的“一致性”边界——你使一致性边界越大,你会产生一些后果:
    • 大多数操作不涉及所有数据 - 但所有数据在每个操作期间都必须事务锁定
    • 在协作的多用户域中,这可能会导致并发问题,其中任一用户由于他们想要操作的数据被不必要地锁定而被阻止
  • 为什么可能这样的关系对建模有用?
    • 如果您有一条规则(不变的)必须在所有子聚合中具有事务一致的数据,例如:
      • 每个供应商必须有最多 4 个目录 - 要执行此规则,您必须在供应商中拥有交易一致的目录列表
      • 目录中目录商品的价格总和不得超过 $X - 同样,您需要以交易一致的方式提供所有商品

备选方案

那么 - 如果您没有任何此类规则,并且您已被说服创建“小型”聚合,您可以做什么?

  • 每个实体都成为它自己的集合体
  • 通过引用 链接实体。在这种情况下:
    • 供应商不会有目录列表
    • Catalog 将有一个“SupplierId”以将目录链接到供应商,并便于供应商获取目录列表
    • Catalog 不会有一个 CatalogItem 列表
    • CatalogItem 将有一个“CatalogId”链接到目录 - 同样,有助于按目录获取项目列表

这种方法的含义是您将在聚合之间具有事务一致性 - 但除非您的规则要求它,否则您不需要它,那么为什么要强制执行它?

您真的需要事务一致性吗?

DDD 鼓励的另一条建议是挑战对事务一致性的需求——这真的有必要吗?

使用上面的简单示例 - 如果供应商最终有 5 个目录会怎样?世界会崩溃吗?即使您确实需要该规则,它是否需要在事务上保持一致?使用较小的聚合,您可以:

  • 如果供应商已经有 4 个目录,则包括客户端验证以防止操作
  • 在创建目录时发布事件,触发检查和补偿操作 - 如果处理程序确定供应商现在有 5 个目录,则发出警报或更新供应商状态,直到用户删除目录,或自动使最旧的目录过期 - 在您的域中最有意义的目录

总结

建议是:

  • 设计小聚合
  • 拥抱最终一致性

关于c# - 带孙子的 .NET DDD 域模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48734375/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com