我知道我们不应该直接更改聚合根的子节点,而应该通过聚合根上的方法来执行它们。例如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 聚合是否有效以保存、聚合是否不可修改、粗粒度的乐观并发检查等。但是我怎样才能做到这一点?