协调DDD、视图模型和性能



我开始了解DDD,并关注从持久性中检索实体对象,然后在UI的视图模型中重新构建它们的性能影响。

假设我有两个聚合根:

Person      Orders
------      -------
personId    orderId
name        personId

每个聚合根都有自己的存储库,负责整个聚合的基本CRUD操作。

假设UI需要以下列:

viewmodel
---------
personName
numberOfOrders

我可以想出两种方法来填充这个视图模型:

  1. 急切地加载所有个人实体,急切地加载基于personId的所有订单,将加载的实体重组到视图模型中
  2. 创建一个JOIN/COUNT(orderId)存储过程,并使数据库返回的数据与视图模型的结构相同

显然,选项1可能是相当昂贵的操作,因为可能会有多个人和多个订单导致多个数据库调用。选项2只需要一个数据库调用。

如果选项2是首选(性能)选项,那么我将这个"视图模型"和所谓的"数据库调用"存储在哪里?在我可以实现的存储库之上是否有一个单独的"数据服务层"?或者,就DDD的总体实施方式而言,这是一种反模式吗?

基本上,我如何协调复杂的DDD聚合和自定义UI视图模型,同时考虑性能?

更新

规范/查询对象

在与一位朋友的会谈中,他建议一种可能的解决方案是某种规范/查询对象模式。唯一的问题是,我们必须在存储库级别实现这一点,这需要我将人员和订单组合成一个大的集合。出于事务一致性的原因,我通常会避免这种情况。

您可以引入一个专用的值对象和一个存储库,该存储库将返回给定人员的统计信息:

// value object
class PersonStatistics {
    String PersonName
    Int NumberOfOrders
    Money AverageOrderAmount
}
// repository
interface PersonStatisticsProvider {
    PersonStatistics Get();
}

这类似于读取模型模式。

从性能的角度来看,我会选择选项2,但可能会将返回人员的查询与返回订单数量的查询分开。

您可以通过类似OrderRepository.GetOrderCountByPerson(personId)的方式使订单计数可用,即使它确实偏离了您对存储库的规范定义。

通常从域实体派生ViewModels。如果有一个服务直接查询数据库,从而返回与ViewModel完全匹配的数据结构,这似乎很奇怪。

最新更新