DDDD:值对象中可以有列表吗?
-
10-07-2019 - |
题
我不太熟悉领域驱动设计,最近我开始为项目创建领域模型。我还没有决定使用 ORM(尽管我可能会选择 NHibernate),并且我目前正在努力确保我的值对象应该就是这样。
我有一些 VO 除了封装“类似”术语之外几乎没有任何行为,例如:
public class Referral {
public Case Case { get; set; } // this is the a reference to the aggregate root
public ReferralType ReferralType { get; set; } // this is an enum
public string ReferralTypeOther { get; set; }
} // etc, etc.
这个特定的类有一个对“案例”的引用,它是两个级别的,所以如果说我要访问推荐,我可以去:case.social.referral(Case、Social 和 Referral 都是类,Case 内有一个 Social,Social 内有一个 Referral)。现在,我在输入时查看它,我认为我不需要推荐中的案例,因为它可以通过社交实体访问,对吗?
现在,毫无疑问,我认为这应该是一个 VO,并且我计划用来将其持久保存到数据库的方法是让 NHibernate 为其分配一个代理标识符(我仍然不太清楚) ,如果有人也能详细说明这一点,它会对我有所帮助,因为我不知道代理标识符是否要求我在 VO 中已有一个 Id,或者它是否可以在没有 Id 的情况下运行)和/或受保护的 Id 属性不会暴露在 Referral 类之外(仅用于持久化到数据库的目的)。
现在回答我的标题问题:VO 中是否应该有一个集合(在我的例子中是一个列表)?我只能将其视为数据库中的一对多关系,但由于没有标识,因此似乎不足以使该类成为一个实体。下面是代码:
public class LivingSituation {
private IList<AdultAtHome> AdultsAtHome { get; set; }
public ResidingWith CurrentlyResidingWith { get; set } // this is an enum
} // etc, etc.
该类当前没有 Id,而 AdultsAtHome 类只有内在类型(字符串、整数)。所以我不确定这是否应该是一个实体,或者它是否可以保留为 VO,我只需要配置我的 ORM 以使用它们自己的表和私有/受保护的 Id 字段来使用 1:m 关系,以便ORM可以持久化到DB。
另外,我是否应该为每个班级使用标准化表格?我认为当有可能将类的多个实例分配给实体或值对象和/或有可能与其中一些对象建立 1:m 关系时,我只需要为每个类使用一个表。我对某些具有内在类型的值对象使用单个表没有问题,但对于嵌套类型,我认为使用规范化表会更有利。对此还有什么建议吗?
抱歉,我对多个问题如此冗长:
1) 我的值对象是否需要一个代理标识符(例如 NHibernate)?
2)如果#1是肯定的,那么这是否需要私有/受保护,以便我的值对象在概念上“仍然是”值对象?
3)一个值对象可以有其他值对象(例如,一个列表)或者它会构成一个实体吗?(我认为答案是否定的,但我更愿意在继续下一步之前确定一下。)
4) 我是否需要从比聚合根低几级的值对象引用聚合根?(我不认为我这样做,这可能是我在编写模型时的疏忽,有人同意吗?)
5) 在让 ORM 为更简单的值对象进行映射的同时,是否可以对某些事物使用规范化表(例如嵌套类型和/或以集合作为属性的类型,无论如何都需要它们自己的表来实现 1:m 关系)属于我的实体的同一张表?
再次感谢。
解决方案
1) 是的 - 如果 您将 VO 存储在它们自己的表中
2) 如果您可以使用私有/受保护的 ID 属性,那就太好了。或者,您可以使用显式接口来“隐藏”ID 属性。
但是,仔细阅读您的问题,您是否建议看到 ID 属性的开发人员会自动假设该对象是一个实体?如果是这样,他们需要(重新)培训。
3) 是的,可以,但有以下限制:
- 应该是比较少见的
- 它应该只引用其他 VO
另外,请考虑一下:VO 不应该 停在附近。每次需要时重新创建整个 VO 是否容易/高效?如果没有,请将其设为实体。
4) 取决于您想要如何实施 聚合锁定. 。如果你想使用 阿延德的解决方案, ,答案是肯定的。否则,您将需要一种机制来将对象图遍历回聚合根。
5) 是的。不要忘记 DDD 是 执着无知 (在理想的世界中!)。
然而...
我相信推荐应该是 实体. 。想象一下这些对话:
对话1:
- 汤姆:“嘿乔!你能给我大卫·琼斯的推荐吗?”
- 乔:“哪一个?”
- 汤姆:“抱歉,我是说推荐号 123”
对话2:
- 汤姆:“嘿乔!你能给我大卫·琼斯的推荐吗?”
- 乔:“哪一个?”
- 汤姆:“我不在乎——给我一个就行了”
对话 1 表明推荐是 实体, ,而对话 2 表明它是一个 VO。
还有一件事:做 Referral.ReferralType
在它的生命周期中发生变化(还有另一个暗示它应该是一个实体)?如果它 不 改变的话,考虑使用多态性,让NH来处理。
希望有帮助!