【问题标题】:How to orginize dependencies implementing CQRS and DDD如何组织实现 CQRS 和 DDD 的依赖项
【发布时间】:2019-09-25 16:21:24
【问题描述】:

我尝试使用 CQRS 方法来实现 DDD 服务。我没有使用事件溯源。 所以我有 3 层:应用程序、基础架构和域。很多人说可以绕过域进行查询,没关系。例如,假设由于性能问题,这对我来说是必要的。

在对持久性无知之后,我在基础架构中实现了存储库。正如我在 DDD 和书籍的所有实现中看到的那样,基础设施不应该依赖于应用层。

那么我需要从存储库返回什么?如果 DTO(读取模型,查看模型,实际上没关系)是应用程序关注的问题。将它们放置在基础设施层上会形成从应用程序到基础设施的循环依赖,反之亦然。但是实现查询逻辑(如果我使用 Orm 通过编写原始 SQL 进行查询)是一种不好的方法,因为为此我们在 Infrastructure 中创建了存储库(这就是 https://github.com/dotnet-architecture/eShopOnContainers 的方式)。

另一种方法是从存储库加载聚合,然后将它们转换为 DTO,但由于我的虚构问题,这是不可能的。那么如何以正确的方式处理呢? (这就是https://github.com/JasonGT/NorthwindTraders/的方式)

【问题讨论】:

    标签: architecture dependencies domain-driven-design cqrs


    【解决方案1】:

    如果您想遵循 Robert C. Martin 的 Clean Architecture,您应该将稳定的业务规则(高级抽象)与易变的技术细节(低级细节)分开,定义清晰的界限。您的源代码依赖项应该只指向内部,指向更高级别的策略。 为此,请使用依赖倒置原则。在需要它们的层中为存储库定义接口。然后在基础设施层实现这些存储库。

    这意味着应用层不应该依赖于基础设施层。但是Infrastructure层可以依赖Application层(Infrastructure可以使用Application)。

    【讨论】:

    • 好的,但是在每个 source\article\book DTO 中 - 是一个应用程序关注点,因此我们将它们放入其中。然后,如果您想直接返回 DTO - 它是实现和域的依赖项(因为接口在那里)。如何处理。
    【解决方案2】:

    一个理想化的读取模型看起来很像一个缓存——你得到一个查询,你使用这个查询来计算一个缓存键,你返回使用那个缓存键存储的字节。

    缓存未命中会发生什么?然后你必须去查找数据,并计算返回的字节应该是什么。

    因此,您想要实现的是从持久存储中获取所需的状态,然后将该状态转换为调用者可以理解的序列化表示,而无需大惊小怪。

    例如,假设有一个 Web API,其中客户端向您传递一个目标 uri 并期望得到一个 application/json 响应。您的有状态数据存储是一些 RDBMS,因此您使用现成的 sql 客户端执行查询,该查询会生成 ResultSet。然后,您将使用 DOM 构建器之类的东西来构建树,迭代结果集中的行并将数据列复制到树中。树完成后,您将使用您的 json 库来附加树的 UTF-8 表示。 Tada,您已经获得了响应的表示,您可以将其保存在缓存中并返回给客户端。

    如果您更熟悉 O/RM,那么您可以定义一个内存对象表示,并让 O/RM 担心创建结果的内存表示,然后您将其传递给 JSON 反序列化库。

    这里的重点是,这个翻译组件需要了解如何解释从持久存储中检索到的值,以及如何以客户端可以理解的表示形式表达该值——但你不知道不需要实体。您“只是”接收消息并将其转换为其他消息。

    根据翻译的哪些部分是稳定的以及哪些需要可替代,您可能会在这里找到许多有用的设计中的任何一个。但是你的翻译的实现不需要对你的写模型的实现细节有任何依赖。

    【讨论】:

    • 我不完全理解这个想法,你能提供一段代码或一些git repo吗?据我了解,您谈论的是直接来自某种 ORM 的数据动态绑定?
    【解决方案3】:

    正如我在 DDD 和书籍的所有实现中看到的那样,基础设施 不应该依赖于应用层。

    这根本不是事实。基础设施依赖于应用层。请看 Vaughn Vernon 的红皮书 IDDD 的图 4.3(第 124 页)。

    例如,在应用层定义横切服务(认证和授权、事务等),在基础设施上实现。

    那么我需要从存储库返回什么?如果 DTO(读取模型, 查看模型,实际上并不重要)是应用程序关注的问题。 将它们放在基础设施层上会产生循环依赖 从应用程序到基础架构,反之亦然。但实施 查询逻辑(如果我使用 Orm 通过编写原始 SQL 进行查询)是不好的 方法,因为为此我们创建了存储库 基础设施

    如果您使用的是 CQRS,则您有不同的查询模型。存储库是命令模型的一部分。在 Q 模型中,您在应用层定义您需要的查询,返回客户端所需的对象(例如视图)。查询的实现在基础设施层,直接使用SQL。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-18
      • 2010-12-12
      • 2010-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-01
      • 1970-01-01
      相关资源
      最近更新 更多