DDD,事件存储,UI

DDD, Event store, UI

我有一个项目是根据众所周知的 DDD 原则设计的,或者至少应该是根据众所周知的 DDD 原则设计的。

  1. 返回 - DDD + CQRS + 事件存储

  2. UI - ngrx/store

我有很多问题要问,但现在我会坚持这两个:

  1. 单次Command/Action执行后UI存储应该如何更新?

a) 订阅 response.ok

b) 监听域事件

c) 触发持有 created/updated/removed 对象的通用事件 ?

  1. 在每个命令/事件中传输整个聚合根 dto 及其所有实体是个好主意,还是最好有更细粒度的命令/事件,例如:只有一个 属性 ?

Is it a good idea to transfer the whole aggregate root dto with all its entities in each command / event or it is better to have more granular commands / events for ex.: with only a single property ?

的确,最好有细化的命令和事件。 命令和事件应该是不可变的、有表现力的对象,可以清楚地表达意图或过去的业务事件。如果对象恰好包含即将更改或已更改的数据,则此方法效果最佳。

How should the UI store be updated after a single Command/Action is executed ?

来自我的聚合的命令方法return 无效(尊重 CQS);因此,接收命令请求的 REST 端点仅响应 OK, command is accepted 之类的内容。那么,就看后端服务器内部如何处理命令了:

  • 如果命令是同步处理的那么一个简单的OK, command is accepted就足够了,因为UI会自行刷新并且新数据会在那里;
  • 如果命令是异步处理的那么事情会变得更复杂,某种命令 ID 应该是 returned,所以像 OK, command is accepted and it has the ID 1234-abcd-5678-efgh; please check later at this URI for command completion status 这样的响应

同时可以监听领域事件。我使用从后端发送到 UI 的 Server sent events 来执行此操作;如果 UI 是基于网络的,这很有用,因为可能有多个浏览器 windows 打开,数据将在页面后台更新;很好,客户很满意。

关于在命令响应中包含一些来自读取端的数据:这取决于您的具体情况;我避免它是因为它意味着在写的时候要读,这意味着我不能在更高的层次上将写和读分开;我喜欢能够独立地扩展写入部分和读取部分。因此,response.ok 是最干净的解决方案。此外,它暗示 command/write 端点对调用者做出了一些查询假设;为什么命令 handler/command 端点应该假设调用者需要什么数据?但是可能会有例外,例如,如果您想减少请求的数量,或者如果您使用 API 网关,该网关在命令发送到后端服务器后也会执行 READ。

Is it a good idea to transfer the whole aggregate root dto with all its entities in each command / event or it is better to have more granular commands / events for ex.: with only a single property ?

我在使用 CQRS 时从不发送整个聚合;您有读取模型,因此每个聚合在每个读取模型上都有不同的表示。所以,你应该为每个 UI 组件创建一个读取模型,这样你只保留和发送显示在 UI 上的数据,而不是包含任何人需要的任何东西的神一样的对象显示在任何地方。

命令基本上分为两类之一:创建命令和其余命令。

创建命令

使用创建命令,您通常希望取回刚刚创建的对象的句柄,否则您将一无所知,无处可去进一步操作它。

  • 我相信 CQS 和 CQRS 中的创建命令 可以 return 某种标识符或位置:参见 my answer here。命令处理程序可能会知道该标识符,它可以在其响应中 return 它。这很好地映射到 REST 中的 201 Created + Location header。

  • 你也可以有客户端generate the ID。在这种情况下,请参阅下文。

所有其他命令

客户端显然有object的地址。在从 HTTP 部分获得 OK 后,它可以简单地重新查询其位置。或者,您可以轮询该位置,直到有指示命令成功为止。它可以是资源版本 ID、Constantin 指出的状态、Atom feed

另请注意,命令处理程序 return 操作的成功状态可能更简单,这是否真的违反了 CQS 是有争议的(再次,请参见上面的答案)。