Architecture 协调DDD、viewmodels和性能

Architecture 协调DDD、viewmodels和性能,architecture,domain-driven-design,ddd-repositories,Architecture,Domain Driven Design,Ddd Repositories,我开始学习DDD,并关注从持久性中检索实体对象,然后在UI的viewmodel中重新构造它们的性能影响 假设我有两个聚合根: Person Orders ------ ------- personId orderId name personId 每个聚合根目录都有自己的存储库,负责整个聚合的基本CRUD操作 假设UI需要以下列: viewmodel --------- personName numberOfOrders 我可以想出两种填充此viewmo

我开始学习DDD,并关注从持久性中检索实体对象,然后在UI的viewmodel中重新构造它们的性能影响

假设我有两个聚合根:

Person      Orders
------      -------
personId    orderId
name        personId
每个聚合根目录都有自己的存储库,负责整个聚合的基本CRUD操作

假设UI需要以下列:

viewmodel
---------
personName
numberOfOrders
我可以想出两种填充此viewmodel的方法:

  • 急切地加载所有person实体,急切地加载基于personId的所有订单,将加载的实体重新构造到viewmodel中
  • 创建一个JOIN/COUNT(orderId)存储过程,并使数据库返回数据与viewmodel具有相同的结构
  • 显然,选项1可能是非常昂贵的操作,因为可能有多个人和多个订单导致多个数据库调用。选项2只需要一个数据库调用

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

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

    更新 规范/查询对象


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

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

    您可以通过类似于
    OrderRepository.GetOrderCountByPerson(personId)
    的方式使订单计数可用,即使它与存储库的规范定义有一点不同


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

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

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

    这类似于一种模式。

    这仍然会导致多次数据库访问,我正试图将其最小化。我同意你的看法,拥有一个直接查询数据库的特定于应用程序的服务有点奇怪。我想你的内存中可能已经有来自先前加载的Person聚合根的PersonName,所以这并不意味着我要多次访问数据库,NumberOfOrders只有一个。我们是在聚合级别还是在域级别实现提供者和值对象?由于此值对象可以分类为“人员”或“订单”集合。值对象与任何集合都没有直接关联(引用)。它只是一个“独立”类。每个聚合可以有多个存储库。