使用来自其他聚合的数据检查命令的有效性

时间:2018-01-02 17:03:43

标签: web domain-driven-design aggregate

我目前正在研究我的第一个更大的DDD应用程序。现在它运作得很好,但是我从一开始就遇到了一个问题,我不能不停地思考:

在我们的一些聚合中,我们保留了对整个应用程序非常重要的另一个聚合根的引用(基于它们的ID,因此没有硬引用 - 删除也基于事件/最终一致性)。现在,当我们创建一个新的实体" Entity1"我们发送一个新的CreateEntity1Command,它包含引用的聚合根的ID。

现在我该如何检查这个引用的ID是否有效?现在我们通过读取其他聚合来检查它(没有修改任何东西) - 但这种方法在某种程度上感觉很脏。我想只是"信任"命令,因为无法手动输入ID但必须选择。问题是,我们的应用程序是一个Web应用程序,并且信任您到达那里的用户输入是不安全的(即使公众无法访问它)。

我是否忽略了针对这些问题的任何可能解决方案,还是应该忽略需要更好解决方案的感觉?

3 个答案:

答案 0 :(得分:2)

验证另一个引用的Aggregate是否存在不是Aggregate的责任。它会打破Single responsibility principle。当CreateEntity1Command到达Aggregate时,应该认为其他引用的Aggregate处于有效状态,即存在

在Aggregate的边界之外,这种检查最终是一致的。这意味着,即使它最初通过,也可能在此之后变为无效(即deletedunpublished或任何其他无效域状态)。你需要确保:

  • 如果引用的Aggregate尚不存在,则拒绝该命令。在使用域服务将命令分派给Aggregate之前,请在负责用例的应用程序服务中执行此检查。

  • 如果引用的Aggregate之后进入无效状态,则会执行更正操作。你应该在Saga / Process经理里面这样做。如果使用CQRS,您订阅相关事件;如果没有,您使用cron。它取决于您的域名的正确行动是什么,但主要想法是应将其建模为流程。

所以,长话短说,聚合的责任不会超出其一致性边界

P.S。抵制将服务(域或非域)注入聚合(通过构造函数或方法参数)的诱惑。

答案 1 :(得分:1)

Direct Aggregate-to-Aggregate交互是DDD中的反模式。聚合A不应直接向聚合B发送命令或查询。聚合是严格的一致性边界。

我可以想到2个问题的解决方案:假设你有2个聚合根(AR) - A和B.每个AR都有一堆命令处理程序,每个命令引发一个或多个事件。 A中的命令处理程序取决于B中的一些数据。

  1. 您可以订阅B提出的事件并在A中维护B的状态。您只能订阅指示有效性的事件。

  2. 您可以在A和B之间进行完全独立的服务(S)协调,而不是直接将您的请求发送给A,将您的请求发送给S,负责B的查询(以检查有效性)引用的ID)然后将请求转发给A.这有时称为流程管理器(PM)。

  3. 例如,在您创建新实体“Entity1”的情况下,请将此请求发送给PM,其作业将验证请求中的数据是否有效,然后将您的请求路由到负责创建的聚合“ENTITY1”。发送一个新的CreateEntity1Command,其中包含引用的聚合根的ID到此PM,它使用引用的AR的ID来确保它是有效的,如果它是有效的,那么只有它会向前传递您的请求。

    有用的链接:http://microservices.io/patterns/data/saga.html

答案 2 :(得分:0)

  

我是否忽略了解决此问题的任何可能解决方案

你做到了。 “域名服务”为您提供了一个可能的循环漏洞。

聚合是一致性边界;

约束他们的行为
  • 聚合的当前状态
  • 他们传递的论据。

如果聚合需要与其边界之外的某些内容进行交互,那么您将域服务传递给聚合根以封装该交互。聚合可以自行决定调用域服务提供的方法来实现工作。

通常,域服务只是应用程序或基础结构服务的包装器。例如,如果聚合需要知道某些外部数据是否可用,那么您可以传入一个支持该查询的域服务,检查一些数据缓存。

但是 - 这就是诀窍:你需要意识到来自聚合边界之外的数据必然是陈旧的。即使您查询过时的副本,也可能有另一个进程更改数据。

  

问题是,我们的应用程序是一个Web应用程序,并且信任您到达那里的用户输入并不是真的安全(即使公众无法访问它)。

这是真的,但它通常不是域名问题。例如,我们可能会指定API中的端点需要某个命令消息的JSON表示 - 但这并不意味着域模型负责获取原始字节数组并为其创建DOM。应用层将承担这一责任;聚合的责任是域名问题。

可以仔细考虑区分不同问题之间的界限。这个字节序列是聚合的有效标识符吗?显然是一个应用问题。另一个聚合是否处于允许某些行为的状态?显然是一个域名关注。汇总是否存在......?无论如何都可以。