【问题标题】:Domain Logic - Read Model领域逻辑 - 读取模型
【发布时间】:2015-12-15 12:21:58
【问题描述】:

我有两个聚合。

Person {
    private personID personID;
    private nodeID nodeID; //belongs to node
}
Node {
    private nodeID nodeID; //node's id
    private nodeID parent; //parent node reference by id

    public void assign(Person person);
}

现在我为我的人分配服务有了域逻辑: 可以将人员分配给节点"X",前提是他属于节点"Y",该节点是节点"X" 的父级或曾祖父或曾曾祖父或...。

要找出答案,我需要查询Read Model。 我在域中,所以我不能只使用我的读取模型来查询它。 我认为我不能只添加到我的存储库,连接到读取模型,因为它连接到我的事件存储。特别是当Read Model可以放在另一个服务器上,成为另一个应用程序。

实现它的正确方法是什么?

【问题讨论】:

  • 读取模型只是一个抽象,你可以在你的领域中使用它。 CQRS 是关于如何对业务用例建模的设计原则,它不是将 2 个桶分开的规则。事实上,CQRS 应用于有界上下文,因为模型的某些部分用于更改业务状态(命令),而其他部分不更改任何内容(查询)
  • 好吧。我理解,读取和写入在同一个有界上下文中。但问题在于技术层面。我不能只查询读取模型并在那里查找我的聚合,因为聚合之类的东西在那边不存在。读取模型包含非规范化数据,因此我将无法从中构建事件源聚合。什么负责查询读取模型、存储库?还是某种抽象,实际上会向读取模型的 REST API 发送请求?
  • 您不使用 RM 来查询聚合,只是为了获取业务决策所需的数据。我的观点是,你的聚合试图做太多事情,你应该使用它来改变概念状态,而不是用于与概念相关的所有事情。对于业务查询,您拥有根据业务规则解释现有状态(读取模型)的域服务。聚合的目的只是强制执行保持概念有效/一致的业务约束,所有其他行为都属于域服务。
  • 那么以这种方式实现它是完全没问题的吗? PersonAssigningService -> 将保护与聚合本身无关的分配不变量,并将使用 PersonAllowedToAssignToNodeStrategy (不能有更好的名称 atm :)),策略将是接口。此策略的实施将查询 RM Rest API 以获取必要的信息。
  • 我的意思是你应该在那个服务器上也有一个读取模型,用于本地查询。因此,您的“命令”服务器上有一个(也许更具体,定制的)RM,而“查询”服务器上有另一个。是的,这意味着 RM 重复(实际上,只需在两台服务器上使用相同的库),但这也意味着您的服务器没有耦合并且性能不会受到影响。称之为权衡。

标签: java c# domain-driven-design cqrs event-sourcing


【解决方案1】:

以下是一个约束:

只有属于节点“Y”的人才能被分配到节点“X” 哪个是父母或曾祖父或曾曾祖父或... 节点“X”。

如果是必须强制执行的约束,您可以在写入端的单独聚合中对层次结构进行建模(例如,Graph),其唯一目的是确保完整性。

【讨论】:

  • 有趣的想法。因此,每当我添加新节点或编辑现有节点时,我都应该更新图表,对吗?但是这样的聚合根本没有逻辑,它的目的是为我提供域内的读取模型。是不是太过分了?
  • 该聚合是层次结构的唯一真实来源,而不是读取模型。一致性逻辑该聚合的逻辑。
【解决方案2】:

执行此操作的正确方法是在命令模型中支持祖先检查。这是您要强制执行不变量的地方,因此模型需要支持这一点。

如果您需要能够进行无限制的祖先检查,树结构通常会导致性能问题。因此,您可能需要实施性能优化​​来改进这些类型的查询。

我看到以下可能性:

  • 使用直接支持所需查询的数据存储。如果你想做 ES,这可能会很困难。
  • 使用快照。这可能可行,也可能不可行,具体取决于您的树结构。
  • 使用缓存。这类似于快照,但将信息存储在缓存中而不是事件存储中。
  • 使用读取模型。确保您了解后果,尤其是异步数据传播和增加的复杂性。我只建议将此作为最后的手段,但 YMMV。

【讨论】:

  • 感谢您的回答。好吧,在我的整个应用程序中,我只有一个地方有这种逻辑。因此,我不会因此而离开我的 Event Store。老实说,我真的不明白在这种情况下快照或缓存如何帮助。我会在域中对单个聚合进行快照/缓存。而我需要编写的是递归查询,以找到我正在寻找的结果。
猜你喜欢
  • 2011-04-21
  • 1970-01-01
  • 2014-02-24
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-20
相关资源
最近更新 更多