domain-driven-design - 在六边形架构的 UI 上显示数据

标签 domain-driven-design hexagonal-architecture

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

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

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

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

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

最佳答案

Should I create two type of Repositories? One would be used in the domain and application layer, and the other would be used only for providing data to the outside world. The second one wouldn't return full-fledged Worker entities, only WorkerDTOs containing only the data the GUI needs.

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

Greg Young (2010)

CQRS is simply the creation of two objects where there was previously only one. The separation occurs based upon whether the methods are a command or a query (the same definition that is used by Meyer in Command and Query Separation, a command is any method that mutates state and a query is any method that returns a value).

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

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

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

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

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

"read models don't need to be saved" Is not correct.

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

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

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

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

关于domain-driven-design - 在六边形架构的 UI 上显示数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37015273/

相关文章:

email - CQRS 和电子邮件通知

c# - 实现领域驱动设计

exception-handling - 我的域异常应该从应用层抛出吗?

architecture - 六边形架构 : How to implement driver ports

design-patterns - 在哪里应用域级权限

php - DDD : Modelling a scraping app

java - 使用 DDD 的域服务和应用程序服务的命名约定

c# - 如何处理检索 i2c 缓冲区和设置模型/实体属性?

java - 复杂的多模块 Maven 项目构建失败