我对领域驱动设计(DDD)相当陌生,但我对它的理解是,您与应用程序服务对话,这是您的"模型"的入口。服务可以与使用源(文件、数据库等)获取数据的存储库对话。存储库返回一个实体。
这是我从中得到的全局概念。服务知道存储库,但不知道实体等。
现在我有以下问题。
我有一个实体用户,如下所示(只是一个示例)
<?php
class User
{
protected $name;
protected $city_id;
public function getCity()
{
// return $city_entity;
}
}
getCity()函数返回城市实体。我希望这个函数使用延迟加载,这样当您使用用户存储库时注入CityEntity并不是真正的延迟加载。
对于这个问题,我有两个解决方案。但我觉得两者都违背了DDD原则。我想到的第一个解决方案是在用户实体中注入城市存储库,这有缺点:如果你需要更多的存储库,你必须在实体中加载它们。它看起来像答案,但对我来说它只是一个存储库的包装器。那么为什么不直接注入存储库呢?
第二个解决方案,为实体提供服务定位器。这样做的缺点是,除非您阅读代码,否则您不知道需要哪些存储库。
那么,现在的问题是,在保持DDD主体完整的情况下,提供延迟加载灵活性的最佳方法是什么?DDD的一个要点是,您的域模型应该只表达有界上下文的通用语言来处理业务规则。
因此,在DDD实体中,延迟加载是一个反模式。原因如下:- 如果一个聚合只持有确保业务不变性所需的数据,那么它需要所有的数据,而且它们很少,因此迫切加载效果更好。
- 如果您延迟加载数据,您的客户端必须处理比业务术语中相关的异常路径多得多的异常路径
- 你可以使用共享标识符来处理聚合 之间的引用
- 为投射目的(通常称为读取模型)使用专用查询是便宜的
恕我直言,您永远不应该使用DDD实体作为数据访问技术:使用dto。
要了解更多信息,您可以查看Vaughn Vernon的有效聚合设计。