【发布时间】:2011-05-03 10:27:09
【问题描述】:
我知道我们不应该直接更改聚合根的子节点,而应该通过聚合根上的方法来执行它们。
例如。 order.SetOrderLineQty(product, qty);
但是如果聚合根的子节点是抽象的呢? 假设您有 Car 聚合根,其中包含 IWheel 列表作为聚合的一部分。您将如何通过其聚合根添加/更改轮子的属性(谁对它们可能是什么具体类型的轮子一无所知)?
一个更真实的例子是这样的: 医生可以创建一个 MedicalRerport(聚合根),其中包含 IMedicalNote 列表(作为 MedicalReport 聚合的一部分)。 IMedicalNote 是一个基类/接口,它被子类化为几个具体的子类,例如BloodCheckNote、TemperatureNote、MineralConcentrationNote等。
每个子类都有不同的属性,它们都是可编辑的。 MedicalReport 聚合可能包含一个或多个这些注释中的任何一个。 (每个笔记子类都有一个特定的用户控件供用户输入/更新详细信息,在 MedicalReport 大屏幕下显示为面板/选项卡)
我的问题是,如何严格通过其聚合根 (MedicalReport) 添加/编辑这些注释的属性?由于我不允许直接更改这些注释属性,一个丑陋的选择是在聚合根 (MedicalReport) 上公开所有可能的注释属性,即:
report.SetWhiteBloodCellCount(cellCount);
report.SetBloodCheckComment(comment);
report.SetTemperature(bodyPart, temperature);
report.AddMineral(mineral, concentration);
这些方法中的每一个都将更新(或创建新)其内部子集合中的笔记项。这有两个明显的问题:
- 我们必须预先定义聚合根上所有可能的 IMedicalNote 子类的所有可用属性。这是不可接受的,因为子类的数量肯定会增长,这取决于我们想要捕获的医疗数据类型,而这首先是继承的重点。
- 列表中可以有多个相同笔记类型的实例。这个 API 会失败,因为我们不能只说
report.SetBloodCheckComment(comment)并期望它会更新列表中的 BloodCheckNote 项目,因为我们允许列表中有多个 BloodCheckNote 项目。
我仍然希望通过它的聚合根来维护与这些注释的所有交互,因为它必须控制整个 MedicalReport 聚合是否有效以保存,聚合是否不可修改,粗粒度的乐观并发检查,等等。但是我该怎么做呢?
【问题讨论】:
标签: domain-driven-design aggregateroot