如何在 CQRS 中构建分离和命名空间?

How to structure separation and namespaces in CQRS?

我正在寻找有关如何在 CQRS 结构化应用程序中构建命名空间的建议。

目前命令端和查询端在每个限界上下文中都在同一个命名空间中,但随着复杂性的增加,它开始产生问题。

当前该结构有以下文件夹,每个文件夹都包含实现:

Application
+ Api
+ Cli
+ Web
Domain
+ Action (Command and Command Handlers in one - we are not using a CommandBus) 
+ Event
+ Model
+-- Project
  |-- Project.file
  |-- ProjectRepository.file
Infrastructure
+ Consumer (Projections and ProcessManagers)
+ EventStore
+ Persistance (Denormalized read side)
+-- Project
  |-- SqlProjectRepository.file
Common (Supporting namespace)

现在的问题是领域模型当前同时包含实体和事件源聚合根,它们基本上分别只是查询端和命令端的一部分。

查询端和命令端的聚合没有重叠。

重构到分离,应该在哪里做分片?

建议 1

一个完整的切片导致一个查询和一个命令端,这意味着即使应用层也有读写端。

建议 2

仅在域层上制作的切片,以便查询端包含读取模型的(非常贫血的)实体,而命令端保存事件、事件源聚合根等。

如果我的不适用,请提出第三个建议。谢谢

Currently the structure has the following folders which each contains the implementation...

真不幸。

如果您安排名称空间以使一起更改的事物更靠近在一起,您可能会更愿意承担维护负担。您的 FrobMarbleRepository 属于 frobmarble 命名空间,而不属于 repository 命名空间。

我认为我不同意 Jimmy Bogard 在这里的完整分析,但是关注特征的教训很重要

https://jimmybogard.com/vertical-slice-architecture/

如果您碰巧需要在单个功能中为两个不同的想法使用相同的名称,那么您最终可能将该功能拆分为两个或更多名称空间;另一方面,需要重复使用一个名称可能表明您实际上正在处理多个功能。

这是我采用的方法 - 基于 CQRS 和 DDD,注意到我们的 DDD 扩展到具有单独的解决方案(.NET - 用于不同域限界上下文的 Web API)。

其次,我们所有的基础设施代码、授权处理和共享代码都是在私有包管理器中完成的,这消除了单个解决方案的一些混乱,我们在启动 (DI) 中对其进行 DI。另请注意,我们使用 EntityFramework 作为我们的数据库实现。

但是,考虑到这一点,我和我的团队是这样区分 CQRS 和 DDD 的。

+ App
+- Command
+-- Application.Command
+-- Data.Command.EntityFramework
+-- Domain.Command

+- Query
+-- Application.Query
+-- Data.Query.EntityFramework
+-- Domain.Query

+ Build
+- Pipeline

+ Database
+- Data.Database.EntityFramework
+- Data.Database.Model

+ Test

Api (API app)
Cli