3

我正在学习 DDD 和 Hexagonal 架构,我想我已经掌握了基础知识。但是,我不确定如何解决一件事:我如何向用户显示数据?

因此,例如,我有一个简单的域,其中包含一个具有某些功能的 Worker 实体(某些方法会导致实体发生更改)和一个 WorkerRepository,以便我可以持久化 Worker。我得到了一个应用层,其中包含一些命令和命令总线来操作域(例如创建 Worker 并更新他们的工作时间,持久化更改),以及一个具有 WorkerRepository 和 GUI 应用程序实现的基础设施层。

在这个应用程序中,我想向所有工作人员展示他们的一些数据,并准备修改它们。如何显示数据?

  1. 我可以给它一个 WorkerRepository 的实现的参考。我认为这不是一个好的解决方案,因为这样我可以在存储库中插入新的工人而跳过命令总线。我希望所有更改都通过命令总线。
  2. 好的,我将 WorkerRepository 拆分为 WorkerQueryRepository 和 WorkerCommandRepository(根据 CQRS),并且只提供对 WorkerQueryRepository 的引用。这仍然不是一个好的解决方案,因为 repo 会返回具有更改它们的方法的 Worker 实体,这些更改将如何持久化?
  3. 我应该创建两种类型的存储库吗?一种用于域和应用层,另一种仅用于向外界提供数据。第二个不会返回成熟的 Worker 实体,只有 WorkerDTO 只包含 GUI 需要的数据。这样,GUI 就没有其他方法可以改变 Workers,只能通过命令总线。

第三种方法是正确的方法吗?还是我错误地强迫更改必须通过命令总线?

4

1 回答 1

2

我应该创建两种类型的存储库吗?一种用于域和应用层,另一种仅用于向外界提供数据。第二个不会返回成熟的 Worker 实体,只有 WorkerDTO 只包含 GUI 需要的数据。

这就是 CQRS 方法;它工作得很好。

格雷格·杨 (2010)

CQRS 只是在以前只有一个对象的情况下创建两个对象。分离基于方法是命令还是查询(与 Meyer 在命令和查询分离中使用的定义相同,命令是改变状态的任何方法,查询是返回值的任何方法)。

您建议的 WorkerDTO 的当前术语是“投影”。您通常会拥有不止一个;也就是说,您可以在 GUI 中为工作人员的每个视图进行单独的投影。(这具有使视图更容易的巧妙副作用——它不需要考虑给定的数据,因为数据已经被有效地格式化了)。

另一种思考方式是,您有一个“只写”表示(聚合)和“只读”表示(投影)。在这两种情况下,您都是从记录簿中读取当前状态(通过存储库),然后使用该状态来构建您需要的表示。

由于不需要保存读取模型,因此您最好在读取端考虑factory而不是存储库。(2009 年,出于同样的原因,Greg Young 使用了“provider”。)

一旦您迈出了分离这两个对象的第一步,您就可以开始独立处理它们的不同用例。

例如,如果您需要扩展读取性能,您可以选择将记录簿复制到一堆从属副本,并让您的投影工厂从从属而不是主控加载。或者开始探索不同的持久性存储(键值存储、图形数据库、全文索引器)是否更合适。Udi Dahan 在 CQRS 中回顾了其中的一些想法——但有所不同(2015 年)。

“读取模型不需要保存”是不正确的。

它是正确的; 但它可能并不像它可能的那样清晰和具体。

我们不需要创建读取模型的持久表示,因为描述读取模型实例之间差异的所有信息都已被我们的写入捕获。

我们经常希望缓存读取模型(或它的表示),以便我们可以在许多查询中分摊创建读取模型的工作。并且各种权衡可能表明缓存的表示应该被持久存储。

但是,如果流星出现并破坏了我们的读取模型缓存,我们就会失去工作投资,但我们不会丢失信息。

于 2016-05-04T00:07:08.867 回答