我目前正在研究是否可以在构建特定系统时应用 CQRS,并且有一些我无法轻易找到答案的问题。
命令可用性/验证
用户可以对特定实体做什么通常不仅与用户的角色相关,还与该特定用户与该实体的关系(例如作者)和该实体的状态(公共、存档等)相关。
在我看来,在 CQRS 中,用户操作映射到负责处理它们的命令,但不清楚如何确定哪些操作以及命令可用。
返回每个读取模型的可用命令列表似乎是不合适的,因为由于需要一致性,我们必须检查仅与用户角色相关的命令(例如菜单项)。
当然,命令必须在事务中再次进行验证,以防另一个用户更改状态使命令无效)。
抵抗需求变化
以我的经验,维护一个逻辑冗长且与特定业务对象相关的类/表过多的系统是一场噩梦。
在 CQRS 中,一个特定的业务实体可能有多个读取模型。当需要更改该实体时,也应修改所有相关的读取模型。
为了可维护性,有必要以某种方式将它们关联起来,以便在重构时很容易看出。
在相关说明中,有很多过于具体的命令也会导致可维护性问题 - 我假设每个用例一个命令应该最有效是正确的吗?
读取模型和不修改域模型的命令
在 CQRS 中,命令应该更新读取模型,同时用户可以访问它的旧版本。
在我看来,有两种特殊情况会导致问题。
首先,有些命令不会修改域模型本身(可能只是状态),而是执行一些涉及第三方系统/框架/电子邮件等的操作,在某些情况下,这些命令可能需要相当长的时间才能运行。
正如我在这里看到的,我们需要一个将域模型与命令执行状态相结合的读取模型。此读取模型可用作当前正在处理的项目的历史记录或列表。
其次,一些命令会产生结果。当命令成功完成时,需要向用户显示此结果,并且在某些情况下必须在一段时间后丢弃,甚至是文件。因此,必须有一种方法将这些命令的结果存储在数据库中,并将它们与特定的命令实例相关联。换句话说,有一个临时读取模型。
读取模型表与内存缓存
另外我的想法是正确的,使用二级 ORM 缓存(用于查询结果),不需要为读取模型提供数据库表,而是 ORM 可以在第一次执行查询时生成它们,缓存结果并使其无效当模型实体改变时它们会自动出现。这种方法似乎是一个很好的起点,可以强制执行 CQRS 接口/模式,但可以更改并且作为奖励可以支持动态投影(当用户选择要查看的列等时)。