ddd - 如何正确识别值对象?

ddd - How to properly identify Value Objects?

我正在为我的实体建模,并且为此苦苦挣扎了很长时间。这是我的 Person 实体:

Person
    ID
    Name
    Email
    Password
    City
    Phone
    Biography
    Rating
    Description

我曾尝试将这些属性划分为值对象,但到目前为止我只能将它们转换为 VO(例如,City 是一个由城市名称和国家名称组成的 VO)。

我是否应该尝试创建更大的 VO,例如,将 EmailPassword 组合成一个 Credentials VO?我是否在 VO 的分离中走得太深了?

非常感谢任何帮助

[编辑]

经过一些讨论,最好的解决方案似乎是将每个 属性 保留在它自己的 VO 中,除了电子邮件和密码应该分组在 "Credentials" VO 中。

值对象是值唯一标识它们的事物,即相等是由值完成的,而不是通过显式 属性(如 ID)来提供唯一性。如果两个值对象的所有字段都相等,则两个值对象相等

在尝试识别它们时,请遵循领域专家使用的语言。他们在讨论人时使用什么词?他们指的是凭据,还是电子邮件和密码?

还要找出始终一起使用的属性组。例如,如果 Password 总是与 Email 一起使用,那么将它们分组到 Credentials 对象中是有意义的,因为您可以将行为推送到那里(即 Credentials.Validate())

[更新]

以下所有属性都是值对象的候选者取决于您需要强制执行的不变量

姓名

  • 名称有最小值/最大值吗?
  • 是否有不允许的字符?

电子邮件

  • 它是有效的电子邮件地址吗
  • 两个人可以有相同的电子邮件地址吗?

密码

  • 最小/最大长度?
  • 需要字符吗?
  • 无效字符?

Phone

  • 它是有效的 phone 号码吗?
  • 你们是怎么处理国际区号的?

评分

  • 评级是否有最小值和最大值?
  • 如何计算? (计算出来了吗?)

描述

简历

城市

等....

如果您为上述概念创建值对象而不是使用 int 或 string 等原始值,则可以将业务规则封装在值对象中。

如果您同时使用这两个东西,您可能希望将电子邮件和密码合并到一个凭据值对象中。即使用凭据等登录...如果您需要在凭据对象之外使用电子邮件,您仍然可以访问 Credentials.Email。

你那里的东西看起来像是一个数据结构 (CRUD)。在适当的 DDD 中,您从 "Create Person" 等业务案例开始,然后找到代表 人 概念 .[=12 的 模型=]

该模型由一组组件和业务规则定义。您的组件通常是 VO,因为它们是表示次要概念的模型,可以表示为没有明确标识的简单值或复合值,并且它们封装了特定的业务约束。例如,Email VO 确保您拥有有效的电子邮件值。

你应该让域告诉你创建更大的 VO 是否有意义;通常您从一个 VO 开始,然后您 发现 它是由其他 VO 组成的。通常,我们从上到下。您可以 see here 建模示例。

当您没有领域专家时很难,但您仍然可以尝试从业务案例中思考并为每个案例确定任何特定模型。如果你最终得到的主要是简单的结构和一些数据验证规则,也许你有一个足够简单的域来使用 CRUD 方法。

不要试图强加特定的领域模型结构,您需要从用例的角度进行领域建模。

Should I try to create larger VOs, by putting together, for example, Email and Password into a Credentials VO ?

只有当两者经常一起使用时才应该这样做。如果他们不这样做,留下他们就好了。

请注意,有时将单个 属性 提取到它自己的值对象中是有意义的,如果它需要支持的不变量数量足够多以证明引入新概念是合理的。查看 this article 了解更多详情。

在您的领域中并不总是清楚概念是值对象还是实体,不幸的是,没有 objective 属性可用于了解概念是否完全是值对象它取决于问题域,一个概念可以是一个域模型中的实体或另一个域模型中的值对象。大多数时候,金钱 class 是一个价值对象,但并非所有金钱对象都是价值对象。你如何找到一个值对象?首先,您应该检查身份的概念是否在结构上相等(这意味着如果对象值相同,则两个对象相同,而不是对象的 ID),您可以安全地替换具有相同集合的 class 的实例的属性。这是一个好兆头,这个概念是一个值对象。

思考值对象的一个​​好方法是思考如果它是一个整数,你真的关心整数 5 是否与你在其他函数中使用的 5 相同?绝对不是您应用程序中的所有 5 个都相同,无论它们是如何实例化的。这使得整数本质上是一个值对象,现在问问你自己,你域中的对象就像一个整数?如果答案是肯定的,那么它就是一个值对象。此外,值对象是不可变的,并且作为实体更轻。