SuperAPI AI 工具集

ddd-entity

编程与开发

查看项目

更新于 10-16 17:26

技能介绍

用途

ddd-entity 用于在领域驱动设计(DDD)中识别和建模“实体”(Entity)。它的核心判断标准是:一个概念是由“它是谁”来标识,而不是由“它包含什么”来标识。实体的身份在属性变化和时间推移中保持稳定。

主要能力

  • 判断适用性:帮助确定某个领域概念应建模为实体还是值对象。
  • 身份建模:身份是被赋予的(常见为 UUID、客户编号等业务标识或自然键),并且稳定——属性改变时身份不变。相等性按身份判断:两个实体当且仅当标识符匹配时相等,与其他任何字段无关。
  • 生命周期管理:实体有生命周期,被创建(常通过工厂)、通过维护不变量的方法被修改、可能被归档、也可能被删除,整个生命周期中身份保持不变。
  • 行为暴露:实体暴露行为而非仅数据。例如 Customer 实体可能有 changeAddress、closeAccount、deactivate 等方法,每个方法负责维护实体的不变量,使客户状态永不处于不一致状态。

使用方式 / 决策启发式

  • 如果需要跟踪其历史,或以后要指代“同一个”,用实体。
  • 如果可以愉快地用另一个相同属性的实例替换它,用值对象。
  • 如果候选概念是实体但除 getter/setter 外没有行为,应提出质疑:要么是贫血实体(应补充行为),要么是分类错误(可能实际是值对象)。
  • 身份是被赋予的,不是从属性推导的。如果发现自己在从字段推导身份,很可能是在建模值对象。

适用场景

  • 对某事物进行长期跟踪:Customer、Order、Account、Shipment、Subscription。
  • 两个属性完全相同的实例仍是不同事物(“两个叫 John Smith 的客户不是同一个客户”)。
  • 一个概念具有生命周期——创建、修改、归档、删除——且同一概念实例在这些状态间持续存在。

限制 / 何时不使用

  • 概念完全由属性描述、没有身份 → 使用 ddd-value-object。
  • 所谓“身份”只是数据库自增且没有领域含义 → 这暗示该概念可能实际是值对象,只是持久化层为存储目的给它做了标识。
  • 概念只存在于单个聚合内部且从外部从不引用 → 它可能仍是实体,但应重新考虑是否需要单独建模。

反模式

  • 把每个领域对象都建模为实体,包括没有固有身份的对象(“实体爆炸”)。
  • 没有行为的实体——只有字段和 getter 的“贫血实体”。
  • 用属性相等替代身份相等(语言适配器陷阱——Kotlin data class 默认如此)。
  • 把数据库行的自增 ID 当作领域身份。

相关概念

ddd-value-object(相反情况,无身份的概念)、ddd-aggregate(实体常作为聚合根)、ddd-factory(用于创建构造复杂的实体)、ddd-repository(按身份加载和保存实体)、ddd-anti-patterns(贫血实体、标识符中的基本类型偏执)。

参考

Evans, Domain-Driven Design (2003), Ch. 5 (A Model Expressed in Software)。