关于 ddd-entity
ddd-entity 是介绍领域驱动设计中实体建模的技能,面向设计领域模型的开发者。它强调稳定身份、生命周期和维护不变量的行为,并与值对象等概念作出区分。
主要功能
- 01说明实体身份与相等性
- 02介绍实体生命周期
- 03强调通过行为维护不变量
- 04提供实体和值对象的判断依据
- 05指出贫血实体等反模式
适用场景
- 01建模需要持续追踪的客户或订单
- 02区分属性相同但身份不同的对象
- 03判断领域概念应建模为实体还是值对象
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill ddd-entity安装后在 Claude Code 中输入/ddd-entity确认已加载。
详细介绍
单行概述
实体是一种领域对象,它由自身身份而非所包含的内容来识别——即使属性发生变化、时间流逝,其身份仍保持不变。
何时使用此技能
- 建模需要随时间跟踪的对象:
Customer、Order、Account、Shipment、Subscription。 - 两个属性完全相同的实例仍然是不同的事物(“两个名叫 John Smith 的客户并不是同一个客户”)。
- 某个概念具有生命周期——创建、修改、归档、删除——且同一个概念实例会在这些状态间持续存在。
何时不使用此技能
- 某个概念完全由其属性描述,且没有身份 → 使用
ddd-value-object。 - “身份”只是没有领域含义的数据库自增 ID → 这表明该概念或许其实是值对象,只是持久化层为了存储而为其标识了身份。
- 某个概念只存在于单个聚合内部,从未在外部被引用 → 它仍可能是实体,但请重新考虑是否需要将其单独建模。
核心内容
身份是实体的区分特征。实体的身份是分配的(通常是 UUID、客户编号之类的业务标识符,或自然键),且稳定不变——属性发生变化时,身份不会改变。相等性由身份决定:当且仅当两个实体的标识符相同时,它们才相等,与其他所有字段无关。
实体具有生命周期。它们会被创建(通常通过工厂)、通过能够维护不变量的方法进行修改,也可能被归档或删除。在整个生命周期中,身份保持不变。
实体应体现行为,而不只是数据。Customer 实体可能包含 changeAddress、closeAccount、deactivate 等方法。每个方法都负责维护实体的不变量——客户的状态绝不会不一致。
判断启发
- 如果需要跟踪某个对象的历史,或日后引用“同一个对象”,它就是实体。
- 如果可以轻松地用另一个属性相同的实例替换它,它就是值对象。
- 如果某个候选概念是实体,但除了 getter/setter 之外没有任何行为,请提出质疑:这个实体要么是贫血实体(应添加行为),要么分类有误(它可能其实是值对象)。
- 身份是分配的,而非从属性推导得出。如果你发现自己在通过字段推导身份,那你很可能是在建模值对象。
反模式
- 将每个领域对象都建模为实体,包括那些没有固有身份的对象(“实体泛滥”)。
- 没有行为的实体——仅包含字段和 getter 的“贫血实体”。参见
ddd-anti-patterns。 - 用属性相等性取代身份相等性(语言适配器的常见陷阱——Kotlin 的
data class默认如此)。 - 将数据库行的自增 ID 当作领域身份。
另请参阅
ddd-value-object— 相反的情况:没有身份的概念。ddd-aggregate— 实体通常充当聚合根。ddd-factory— 用于创建构造过程较复杂的实体。ddd-repository— 用于按身份加载和保存实体。ddd-anti-patterns— 贫血实体、标识符中的原始类型迷恋。
参考资料
- Evans,《领域驱动设计》(2003),第 5 章(以软件表达的模型)。
评论
支持 Markdown