DDD实践:我应该为价值对象创建一个存储库吗

本文关键字:一个 存储 创建 我应该 实践 对象 DDD | 更新日期: 2023-09-27 18:26:48

我一直在努力理解DDD。这是一个让我难以置信的场景。假设我们有一个实体基金,它有价值对象分配/持有和历史价格。如果一项服务只想分配一笔特定的资金,该怎么办?我们应该返回分配对象列表还是返回包含分配列表的基金实体?如果我们采用第一种方法,我们需要创建一个分配存储库。第二种方法看起来有点奇怪,因为实体被修改为只向服务返回某些值对象。在对该实体了解不多的情况下,该服务难道不应该拥有所有可访问的基金领域吗?

我的描述可能不准确。如果我需要澄清我的帖子,请告诉我。

class Fund
{
   int fundId;
   List<Allocation> allocations;
   List<Holding> holdings;
}
class Allocation
{
   string type;
   string percentage;
}

DDD实践:我应该为价值对象创建一个存储库吗

要回答标题中的问题,不,您不应该回答。只有当存储库中的项目具有标识时,存储库模式才有效。如果一个对象具有标识,那么它就是一个实体,而不是一个值对象。

值对象应该是全有或全无,例如,更改值对象的一个属性将替换整个对象。因此,值对象在创建后是不可变的。

这并不是说存储库内部的值对象的版本不能具有标识,但您不应该让持久性问题改变您的域。

根据你的描述,Allocation实际上听起来像是一个实体,因为它是可微分的,因此具有同一性。

假设Allocation是一个实体,那么我要问的问题是Allocation是否应该是它自己的聚合。

存储库实现有多种变体,但我不介意返回Allocation IF和ONLY IF的列表,Allocation从来都不是单独管理的。

换言之,如果你在某个时候想要获得有关分配的信息,无论它属于哪个基金,那么你都需要一个用于分配的存储库,如果你正在创建这样的存储库的话,那么你应该有一个像getAllocationsbyFundId(int id)或类似的方法。如果在不知道拨款来自哪个基金的情况下单独查看拨款是没有意义的,那么拨款实际上是基金的一部分,在基金存储库中有一个方法来返回特定基金的拨款是完全有意义的。

然而,如果您最终在基金存储库中使用了GetAllAllocation()方法,那么您就脱离了干净的模式。

我可能不太了解您的域,所以如果我弄错了,请告诉我。当我们采用Order/OrderLine场景时,我们可以将OrderLine建模为VO(很像您的Fund/Allocation)。为什么我们要查询一个服务,只返回OrderOrderLine对象列表?:)

但是,如果确实需要这样做,则应该加载Fund实例并使用其包含的Allocations列表。然而,查询您的域模型通常会导致问题(延迟加载、获取策略和远离"告诉不要")。如果确实需要查询,可以考虑创建一个执行此功能的轻量级查询模型(有些人称之为读取模型)。

因此,我同意Mgetz的观点,即您应该拥有一个VOs存储库。如果你有一个固定的VOs列表,那么你可以使用一种类型的enum结构。在C#中,您可以使用readonly类实例来完成此操作。Vaughn Vernon称之为"标准类型"(如果内存可用的话)。不过,我不认为你有那种的场景。