在DDD聚合根中,检查现有聚合的逻辑应该放在哪里

In DDD aggregate root, where should be placed logic of checking existing aggregate

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

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

我正在使用事件源、CQRS、命令处理程序。抱歉,我无法 post 验证码。

So how to implement this check that complies with DDD principles?

"It depends".

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

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

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

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

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

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

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

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

For example I need to check if table is already taken, and if it is, decline order creation. This table service may reside in another AppDomain, and network call maybe needed.

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