9

我不精通领域驱动设计,最近我开始为一个项目创建领域模型。我还没有决定使用 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(案例、社交和推荐都是类,有一个社交在一个案例中,并且在一个社交中只有一个推荐)。现在我在输入时正在查看它,我认为我不需要推荐中的案例,因为它可以通过社交实体访问,对吗?

现在,毫无疑问,在我看来这应该是一个 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,我只需要使用他们自己的表和一个私有/受保护的 Id 字段来配置我的 ORM 以使用 1:m 关系,以便ORM 可以持久化到数据库。

另外,我是否应该为每个班级使用标准化表格?我认为,当有可能将类的多个实例分配给实体或值对象和/或有可能与其中一些对象建立 1:m 关系时,我只需要为每个类使用一个表. 对于具有固有类型但嵌套类型的某些值对象使用单个表我没有问题,我认为使用规范化表将是有利的。对此也有什么建议吗?

很抱歉对多个问题如此冗长:

1)我的值对象是否需要一个代理标识符(比如 NHibernate)?

2)如果#1是肯定的,那么这是否需要私有/受保护,以便我的值对象在概念上“仍然”是一个值对象?

3)一个值对象可以有其他值对象(比如一个列表)还是构成一个实体?(我认为这个问题的答案是否定的,但我更愿意在继续之前确定。)

4) 我是否需要从聚合根向下几级的值对象引用聚合根?(我不认为我这样做,这可能是我在编写模型时的疏忽,有人同意吗?)

5) 在让 ORM 为更简单的值对象进行映射的同时,是否可以对某些事物使用规范化表(例如嵌套类型和/或具有集合作为属性的类型,这些属性无论如何都需要它们自己的表来实现 1:m 关系)到属于我的实体的同一张表?

再次感谢。

4

1 回答 1

12

在此处此处查看相关问题的答案


1)是 -如果您将 VO 存储在他们自己的表中

2)如果您可以使用私有/受保护的 ID 属性,那就太好了。或者,您可以使用显式接口来“隐藏” ID 属性。

但是,阅读您的问题,您是否建议看到 ID 属性的开发人员会自动假定该对象是一个实体?如果是这样,他们需要(重新)培训。

3)可以,但有以下限制:

  • 应该很少见
  • 它应该只引用其他 VO

另外,请考虑一下:VO不应该留下来。每次需要时重新创建整个 VO 是否容易/高效?如果没有,请将其设为实体。

4)取决于你想如何实现你的Aggregate Locking。如果你想使用Ayende 的解决方案,答案是肯定的。否则,您将需要一种机制来将对象图遍历回聚合根。

5)是的。不要忘记 DDD 是Persistence Ignorant(在理想世界中!)。


然而...

我相信 Referral 应该是一个Entity。想象一下这些对话:

对话一:

  • 汤姆:“嘿乔!你能给我大卫·琼斯的推荐信吗?”
  • 乔:“哪一个?”
  • 汤姆:“抱歉,我是指第 123 号推荐人”

对话2:

  • 汤姆:“嘿乔!你能给我大卫·琼斯的推荐信吗?”
  • 乔:“哪一个?”
  • 汤姆:“我不在乎——只要给我”

对话 1 表明 Referral 是一个Entity,而对话 2 表明它是一个 VO。

还有一件事:Referral.ReferralType在它的生命周期内是否会发生变化(还有另一个暗示它应该是一个实体)?如果它没有改变,请考虑使用多态性并让 NH 处理它。

希望有帮助!

于 2009-11-30T08:23:46.117 回答