【问题标题】:In DDD aggregate root, where should be placed logic of checking existing aggregate在 DDD 聚合根中,应该在哪里放置检查现有聚合的逻辑
【发布时间】:2019-07-02 13:09:04
【问题描述】:

假设我有一个Order 聚合根,当我收到创建Order 的命令时,我应该在某些条件下检查其他订单,如果满足这些条件,则拒绝创建。检查这个条件绝对是业务逻辑,但我不应该首先创建订单,而条件不满足。 那么如何实现这个符合 DDD 原则的检查呢? 它是域服务、应用程序服务的一部分吗?

编辑: Order 中有 TableId 属性。 例如,我需要检查表是否已被占用,如果是,则拒绝创建订单。此表服务可能驻留在另一个 AppDomain 中,可能需要网络调用。

我正在使用事件溯源、CQRS、命令处理程序。抱歉,我无法发布代码。

【问题讨论】:

  • 视情况而定。提供的信息太少。当您使用 CQRS 时,请在命令处理程序中执行此操作。您从存储库中获取订单,如果它显然存在,如果它不存在添加它。涉及两个或多个聚合的更复杂的业务逻辑可能会进入域服务(即银行转账)
  • @Tseng 感谢您的反馈,我发布了关于问题的编辑以提供更多背景信息。

标签: domain-driven-design aggregateroot domainservices


【解决方案1】:

那么如何实现这个符合 DDD 原则的检查呢?

“视情况而定”。

如果您需要所有内容都完全一致,那么您可以为您的聚合提供其他数据的缓存副本以计算其逻辑。人们为此使用不同的模式;使用域服务为您获取数据是一回事,将控制权返回给应用程序为您获取数据是另一回事......

----> create order
<---- here is a list of other information I need
----> the other information
<---- here's the order

这要交给业务专家——如果其他数据是一秒前的,计算是否足够准确?

另一方面,如果您需要一切都完全一致,那么您需要能够锁定其他信息,以便在您进行计算时没有人可以更改这些细节。

该锁可以是悲观的(锁定数据,然后进行计算),也可以是乐观的(获取数据的副本,执行计算,然后锁定数据并确保它没有改变)。

这是一个“坏”消息:在域驱动设计模式中定义锁的机制是聚合。聚合是coarse grained lock 模式的表达式;当您需要锁定一堆数据时,这就是业务告诉您数据都应该是相同聚合的一部分。

当您发现业务规则根本不符合这些边界时,有时会发生这样的情况:您拥有一个漂亮的领域模型,其中的聚合表达了一堆明显的领域概念,并且您必须重新-组织您的数据边界以使规则发挥作用。

在开始您的模型设计时将您的聚合想象为进程,并将需要能够锁定彼此数据的进程组合在一起,这通常是一个好主意。

例如,我需要检查表是否已被占用,如果是,则拒绝创建订单。此表服务可能驻留在另一个 AppDomain 中,可能需要网络调用。

当权威数据存在于其他地方时,忘记锁定。从尽力而为、异常报告和冲突缓解方面考虑。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-29
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多