代码之家  ›  专栏  ›  技术社区  ›  Arunas

CQRS:阅读按需构建的模型?

  •  7
  • Arunas  · 技术社区  · 12 年前

    据我所知,CQRS主张将读取模型与领域模型分离,并为每个必要的领域模型投影提供特定的读取模型。

    从使用角度来看,读取模型的存储和检索方式应该是透明的——您可以发出查询并获得读取模型,而不必关心它是如何生成的。

    许多示例和文章使用单独的表来存储读取模型,并通过响应域模型更改来重新生成它们。

    我不太喜欢这种方法,原因如下:

    • 并非所有可能的阅读模型都会经常被需要;
    • 需求更改可能会使现有的读取模型失效,因此需要重新生成所有读取模型;
    • 如果由于某种原因,读取模型包含无法在生成时存储但需要计算的属性,您将被迫使用存储过程/函数/视图;
    • 由于在域模型更改时使用应用程序级缓存的情况下,读取模型与域模型是分开的,因此您需要通知所有应用程序需要从缓存中逐出旧的读取模型;
    • 有时,完全去规范化复杂对象图是不可能的,也不可取,因此您需要具有针对特定域实体版本一致的读取模型,也就是说,它们需要在同一事务中生成;
    • 有些域实体的属性经常更改,但需要包含在每个读取模型中。

    基于此,我认为查询服务应该:

    • 对于需要频繁生成和/或是域实体的简单投影的读取模型:不存储它们,而是通过查询数据库中的域模型实体通过ORM生成它们;
    • 对于不需要频繁生成并且是复杂域实体投影的读取模型,生成它们并存储在数据库表中。

    我还看到一些人建议将read模型存储为Blob。将读取模型存储为Blob的问题是,如果您需要在它们上进行搜索,则需要提取属性进行索引,如果需要全文搜索,则必须以全文工具可以理解的格式存储它们。

    正如您所看到的,我基本上希望有一个read模型,它只存在于查询执行之后,而不是基于域更改事件生成的。CQRS是否可以接受此解决方案?我研究CQRS的原因是通过将可缓存视图模型与用户操作处理分离来改进应用程序体系结构,让AJAX支持的web应用程序在用户操作后进行异步更新,并通过将业务逻辑放在各处来减少初级开发人员生成不可维护代码的空间,甚至CQRS的非忠实实现对我来说似乎是朝着正确方向迈出的一大步。

    1 回复  |  直到 12 年前
        1
  •  12
  •   Marijn    11 年前

    CQRS没有 要求 读取模型存储在单独的表中(如果使用文档数据库,则存储在文档中),尽管这通常是一种很好的方法,并且与事件源相结合也很好。阅读模型 可以 例如由数据库视图或ORM查询支持。

    当将CQRS引入遗留系统的部分时,这可能是一个很好的方法。

    你在这里建议的方法以前也有人建议过,例如,请参阅 this post by Ayende ;我认为它被称为“瘦阅读模式”或类似的模式。我会说去吧。

    你可能对阅读感兴趣