为什么不使用存储库返回部分领域模型结果?

9
我看过一些文章,声称仓库应该只返回针对方法调用的完整领域模型,例如GetAll()。但是,如果我只需要一个列表,其中每个项目仅由具有30个属性的领域模型中的2个属性组成怎么办?我想显示一个只显示部门名称和位置的部门列表。从该列表中,用户可以选择一个部门并请求其详细信息。然后,我可以进行另一个仓库调用来返回所选内容的完整领域模型,并允许进行典型的crud操作。
然而,如果我不应该使用仓库来返回完整领域模型的子集,那么建议的方法是什么?我想我可以只返回完整的领域模型列表,但这似乎浪费了网络带宽,因为我不会使用那么多数据。如果我创建另一个模型来表示感兴趣的2个属性,那么似乎又要做大量的工作,因为我拥有的每个模型都有自己的仓库和服务模块以供仓库访问。
如何检索仓库中完整领域模型的子集是建议的方法?此外,如果我违反了仅拉取完整模型的规则,同时还拉取了部分模型数据用于选择列表,我将看不出会发生什么。
1个回答

9
根据我的看法,这可以被视为高度主观的问题... 我的建议基于DDD实践。
DDD的背景下,存储库应始终返回一个域对象(即Aggregate)。聚合是数据存储传输的基本元素 - 您请求加载或保存整个聚合。将数据转换为对视图有意义的模型/DTO是由应用程序层处理的。
为了解决您的问题:
  1. 您所描述的选取列表示例非常适合使用DTO。如果您创建一个DTO来表示两个属性以支持视图,那么您正在创建一个POCO对象。此对象轻量且创建成本低廉。您可以使用诸如AutoMapper之类的工具来协助DTO与域模型之间的映射。当需要更改视图时,您的更改通常仅限于DTO对象及其映射。您没有将视图的概念从应用程序层泄漏到域层。

  2. DTO将减少请求客户端的带宽成本(即,您不会返回具有30个属性并在公共场合显示实体的域实体)

  3. 您可以使用单个存储库来支持部门选取列表视图和部门实体的CRUD操作。

  4. 使用一个域模型。但是,根据需要创建尽可能多的DTO来支持该域模型或模型的视图。

归根结底,DDD不便宜,也不是万能解决方案。

如果您需要解决简单问题,请使用对您有意义的简单CRUD模型。这些只是指导方针...

DDD(领域驱动设计)适用于开发极其复杂(具有许多相关业务规则)的软件和/或具有明确未来的软件,在这种情况下,领域模型可以超越基础设施存在,或者业务需求变化快速。在其他情况下,DDD可能会带来更多的偶然复杂性而不是解决问题。


值得一提的是,下面是有关DDD概念的一些补充说明,希望能对您有所帮助:
用例最优存储库查询:
Vaughn Vernon描述了一个模式“Use Case optimal Repository Queries”,即... 与其读取各种类型的多个整个聚合实例,然后以编程方式将它们组合成单个容器(DTO或DPO),您可能更想使用所谓的用例最适宜查询。这是指通过使用查找查询方法设计你的存储库来组成一个定制对象,作为一个或多个聚合实例的超集。查询动态地将结果放置到特定于用例需求的值对象(DDD)中。
引用:
你设计一个值对象而不是DTO,因为查询是领域特定的,而不是应用程序特定的(例如DTO)。然后,视图渲染直接使用自定义用例最优值对象进行消耗。
这类似于使用CQRS的方法;但是,存储库是在统一的领域模型存储上执行,而不是在专门用于支持只读视图的数据库上执行。Vaughn Vernon还指出:
如果你发现必须为多个存储库支持使用案例最优查询而创建许多查找方法,那么这可能是一种代码异味。这可能是因为您误判了聚合边界并忽略了设计一个或多个不同类型的聚合的机会。Vaughn将此代码异味描述为:存储库掩盖了聚合物的错误设计。这也可能指向需要考虑使用CQRS。DDD查询模型(也称为读取模型)。查询模型是一种非规范化数据模型。它仅用于显示数据,而不用于提供领域行为。Vaughn Vernon说:如果这种数据模型是SQL数据库,则每个表都将保存单个客户端视图(显示)的数据。表可以有许多列,甚至可以是任何给定用户界面显示视图所需的子集。表视图可以从表中创建,每个表用作整个逻辑子集的一部分。
他还提到要为所需的多个视图创建支持。值得注意的是,基于 CQRS 的视图可以既便宜又可丢弃(用于开发和维护)。使用事件溯源,可以很好地配合这种方法。
DDD DTO:
一种方法是让应用程序层组装 DTO。DTO 将是一个投影,它是您的域实体或实体的子集,以满足您的视图。
Vaughn Vernon 简单地指出 -
DTO 的设计目的是保存需要在视图中显示的所有属性
DDD Repository
Martin Fowler 将仓储模式描述为:
通过使用类似集合的接口来访问域对象,介于域和数据映射层之间的中介。
请参考这些 SO 问题:

我可以查看Vaughn Vernon的哪些书来了解您上面提到的参考点? - Robertcode
@Robertcode 请查看以下内容: Vaughn Vernon的《实现领域驱动设计》和Eric Evans的《领域驱动设计:软件核心复杂性的应对之道》。 - Brennan Mann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接