我从领域驱动开发开始,经过大量阅读,我正在尝试以DDD的方式重构应用程序。但我面临着一个根本性的问题,不知道如何解决。
作为介绍,我的应用程序应该做一些简化的任务。这是一个课程预订应用程序:
- 课程由类别、日期时间、描述和地点组成
- 可以从下拉框中选择类别和位置
- 一个特殊的设置部分为用户提供了添加和更改类别和位置
我对对象的不可变状态有点困惑。首先,我认为lcoation必须是一个实体对象,因为它有一个标识。当然,在范围内,位置本身是不可变的,不能改变。
我真的很困惑。有人能帮我澄清一下吗?
Category和Location是Vaughn Vernon在其著作《实现领域驱动设计》中所称的标准类型的示例。尽管书中的讨论在第6章-价值对象中,但他建议标准类型应该是其原生BC中的一个实体,并且我们应该尝试将它们视为消费BC:中的VO
我们可能会把它们看作实体,因为它们在一个专门的、原生的、有边界的环境中有自己的生活。无论它们是如何由任何类型的标准机构创建和维护的,如果可能的话,我们都应该努力将它们视为我们消费环境中的价值观。[…]
为了便于维护,标准类型通常与使用它们的模型单独存在于一个上下文中。在那里,它们是实体,具有持久的生命周期,具有身份、名称和描述等属性。
(顺便说一句,Vernon提到,他称之为标准类型的这种对象也称为查找和类型代码。)
如果位置可以独立于课程进行管理(添加、编辑、删除等),那么位置很可能是一个独立的聚合根。您可以更改课程以引用其位置的id,而不是包含位置。
我会这么做,因为位置是有限的,你可能想把它们建模为实体(即,它们是你想要存储和放置id的东西,而不是像学生的家庭地址这样的东西,因为它们没有可变性或可重用性,很可能总是有值对象),位置是聚合根,每个位置都有一个地址属性,该属性将是一个值对象(如果您使用SQL,则可以对地址进行非规范化,并将其与位置数据一起存储在行中)。
如果你不希望开发人员能够修改一个位置的任何属性,那么你可以设计你的类来防止修改。
决策基于您如何识别它们。(不适用)
Location通常是一个实体。但在某些情况下,如果只关心标识符,值对象也可以。
@Entity
Location {
@Identifier private String code;
//many other mutable properties
}
@ValueObject
Location {
private String code;//the only property
}
DDD不擅长产品信息或其他面向内容管理的领域。我宁愿保留原来的结构,但找一个小子域来重构,比如库存或定价。