Domain driven design 在六边形体系结构中显示UI上的数据

Domain driven design 在六边形体系结构中显示UI上的数据,domain-driven-design,hexagonal-architecture,Domain Driven Design,Hexagonal Architecture,我正在学习DDD和六边形架构,我想我已经掌握了基础知识。然而,有一件事我不知道如何解决:我如何向用户显示数据 例如,我得到了一个简单的域,其中包含一个具有某些功能的Worker实体(某些方法会导致实体发生更改)和一个WorkerRepository,这样我就可以持久化Workers。我得到了一个应用层,其中包含一些命令和命令总线来操作域(比如创建工人并更新他们的工作时间,持久化更改),还有一个基础结构层,它实现了WorkerRepository和一个GUI应用程序 在这个应用程序中,我想向所有工

我正在学习DDD和六边形架构,我想我已经掌握了基础知识。然而,有一件事我不知道如何解决:我如何向用户显示数据

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

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

  • 我可以为WorkerRepository的实现提供参考。 我认为这不是一个好的解决方案,因为这样我可以跳过命令总线在存储库中插入新的工作人员。我希望所有更改都通过命令总线进行
  • 好吧,那么,我将WorkerRepository分为WorkerQueryRepository和WorkerCommandRepository(根据CQRS),并且只引用WorkerQueryRepository。这仍然不是一个好的解决方案,因为回购协议会返回具有更改方法的工作实体,这些更改将如何持久化
  • 我应该创建两种类型的存储库吗?一个用于域和应用层,另一个仅用于向外部世界提供数据。第二种方法不会返回完整的工作实体,只返回只包含GUI所需数据的Workerdto。这样,GUI就没有其他方法来更改工作人员,只能通过命令总线
  • 第三种方法正确吗?或者我强迫更改必须通过命令总线是错误的

    我应该创建两种类型的存储库吗?一个用于域和应用层,另一个仅用于向外部世界提供数据。第二种方法不会返回完整的工作实体,只返回只包含GUI所需数据的Workerdto

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

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

    你提议的工人的当前术语是“投影”。你经常会有不止一个;也就是说,您可以在GUI中为worker的每个视图创建单独的投影。(这样做的副作用是使视图更容易——它不需要考虑所提供的数据,因为数据已经被有效地格式化了)


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


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

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

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


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

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

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

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


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

    我现在意识到我对CQR有点误解,但你的回答澄清了这一点。谢谢你用投影和阅读模型工厂把我推向正确的方向!“您正在从记录簿(通过存储库)读取当前状态”。。。这根本不是CQRS的含义。CQRS表示独立的读写模式。如果您没有完全绕过域模型进行查询,那么这两个模型是绑定的,不能完全独立于彼此进行演化。我并不是说从域模型构建DTO一定是不好的,但是你不能说你正在使用CQRS体系结构。“读取模型不需要保存”是不正确的。读写模型必须是独立的。事件被投射到读取模型上,导致突变,因此必须在每个事件上保存它。当然,您每次都可以将整个事件流投射到读取模型上,但这不是CQR,对于大多数用例来说速度不够快。