DDD 一个聚合,两个可能的数据源
DDD One aggregate, two possible data sources
我有一个场景,我们决定在内部提取一些我们早就应该做的功能,因为它是我们核心领域的一部分。作为过渡的一部分,我们将暂时使用外部服务来存储和检索 Widget
s 或我们的数据库,具体取决于类型。当与我们的本地数据库交互时,我们将使用乐观并发,这将向我们的 Widget
添加一个 version
字段,而在与外部服务交互时该字段不存在。
这里规范的领域驱动设计解决方案是什么?对此进行抽象的最佳方法是什么?应该在哪里实施?我的第一直觉是在应用程序服务层实现一个抽象工厂模式,但有人可能会争辩说这都可以抽象到存储库中。这样,当我们拉出外部服务时,消费者就不需要进行更改。由于我们正在使用聚合设计并且没有过于复杂的用例,因此我们不需要担心工作单元或类似的东西。交易问题完全在存储库中维护。
由于存储库负责存储抽象,我认为存储库也有责任与多个存储进行协调。
您可以实现类似于:
现在,如果您必须支持 expectedVersion
,您可以在接口的合同中明确指出 expectedVersion
可能不会被所有实现支持,并且会抛出或根本不会被兑现。
"There would be a unique constraint on the entity ID + version
number."
这适用于并发冲突,但无论如何都无法防止 non-concurrent 丢失更新,例如
客户端 C1 在屏幕上加载小部件 W(v1)。
客户端 C2 在屏幕上加载小部件 W(v1)。
客户端 C2 进行更改并保存(例如更新描述)。
存储库在内存中加载 W(v1) 并保存回 W(v2)。
客户端 C1 进行更改并保存(例如更新描述)。
存储库在内存中加载 W(v2) 并保存回 W(v3)。
最终C2的description
更新无声无息的丢失了。您通常可以通过将预期版本与命令一起发送来解决此问题。
我有一个场景,我们决定在内部提取一些我们早就应该做的功能,因为它是我们核心领域的一部分。作为过渡的一部分,我们将暂时使用外部服务来存储和检索 Widget
s 或我们的数据库,具体取决于类型。当与我们的本地数据库交互时,我们将使用乐观并发,这将向我们的 Widget
添加一个 version
字段,而在与外部服务交互时该字段不存在。
这里规范的领域驱动设计解决方案是什么?对此进行抽象的最佳方法是什么?应该在哪里实施?我的第一直觉是在应用程序服务层实现一个抽象工厂模式,但有人可能会争辩说这都可以抽象到存储库中。这样,当我们拉出外部服务时,消费者就不需要进行更改。由于我们正在使用聚合设计并且没有过于复杂的用例,因此我们不需要担心工作单元或类似的东西。交易问题完全在存储库中维护。
由于存储库负责存储抽象,我认为存储库也有责任与多个存储进行协调。
您可以实现类似于:
现在,如果您必须支持 expectedVersion
,您可以在接口的合同中明确指出 expectedVersion
可能不会被所有实现支持,并且会抛出或根本不会被兑现。
"There would be a unique constraint on the entity ID + version number."
这适用于并发冲突,但无论如何都无法防止 non-concurrent 丢失更新,例如
客户端 C1 在屏幕上加载小部件 W(v1)。
客户端 C2 在屏幕上加载小部件 W(v1)。
客户端 C2 进行更改并保存(例如更新描述)。
存储库在内存中加载 W(v1) 并保存回 W(v2)。
客户端 C1 进行更改并保存(例如更新描述)。
存储库在内存中加载 W(v2) 并保存回 W(v3)。
最终C2的description
更新无声无息的丢失了。您通常可以通过将预期版本与命令一起发送来解决此问题。