3

我对领域驱动设计(DDD)相当陌生,但我的理解是您与应用程序服务交谈,这是您的“模型”的入口。该服务可以与使用源(文件、数据库等)获取数据的存储库通信。存储库返回一个实体。

这就是我得到的全球理念。该服务知道存储库但不知道实体等。

现在我有以下问题。

我有一个实体用户,类似于以下内容(只是一个示例)

<?php    
class User
{
    protected $name;
    protected $city_id;

    public function getCity()
    {
         // return $city_entity;
    }
}

getCity() 函数返回城市实体。我希望此函数使用延迟加载,因此在使用用户存储库时注入 CityEntity 并不是真正的延迟加载。

我为这个问题提供了两种解决方案。但我觉得两者都反对 DDD 原则。

我想出的第一个解决方案是在用户实体中注入城市存储库,它有缺点:如果您需要更多存储库,则必须将它们全部加载到实体中。它看起来像答案,但对我来说只是存储库的包装器。那么为什么不直接注入存储库呢?

第二种解决方案,您给实体一个服务定位器。这样做的缺点是,除非您阅读代码,否则您不再知道需要哪些存储库。

那么现在的问题是,在保持 DDD 主体完整的同时,提供延迟加载灵活性的最佳方式是什么?

4

1 回答 1

15

DDD 的要点之一是您的领域模型应该只表达有界上下文的普遍语言来处理业务规则。

因此,在 DDD 实体中,延迟加载是一种反模式。有一些原因:

  1. 如果聚合仅包含确保业务不变性所需的数据,则它需要所有数据并且它们很少,因此预加载效果更好。
  2. 如果您延迟加载数据,您的客户必须处理比业务相关的更多异常路径
  3. 您可以使用共享标识符来处理聚合之间的引用
  4. 将专用查询用于投影目的很便宜(通常称为read-model

恕我直言,您永远不应该将 DDD 实体用作数据访问技术:为此使用 DTO。

有关更多信息,您可以查看 Vaughn Vernon 的Effective Aggregate Design

于 2013-04-06T14:23:08.093 回答