关于 ddd-factory
ddd-factory 是用于设计 DDD 工厂的技能,适合对象创建复杂或具有领域含义的场景,可生成完整且有效的聚合或值对象。它帮助开发者在构造函数、实体创建方法、独立工厂和构建器之间做选择,并将持久化留给仓储。
主要功能
- 01三种工厂形式的设计指导
- 02选择创建方式的判断标准
- 03使用领域语言命名的方法
- 04创建时验证对象有效性
- 05区分对象创建与持久化
适用场景
- 01根据多个输入创建聚合
- 02在对象创建时维护不变量
- 03判断是否需要独立工厂类
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ yonatankarp/ software-design-skills --skill ddd-factory安装后在 Claude Code 中输入/ddd-factory确认已加载。
详细介绍
一句话概述
当构造过程本身复杂或具有领域含义时,工厂会封装创建完整且有效的聚合或值对象所需的知识。
何时使用此技能
- 创建对象需要组装多个子对象(新
Order创建时包含明细项、初始状态和创建时间戳)。 - 创建过程必须确保超出简单字段验证范围的不变量(新
Subscription必须关联有效的Plan和未取消的Customer)。 - 创建行为在通用语言中有具有领域含义的名称(
Order.placeFor(customer, items)、Account.openFor(applicant)),而不只是new Order(...)。
何时不使用此技能
- 构造函数已能完整处理创建工作的简单对象。
- 实体上的静态创建方法已经足够——只有当创建逻辑不属于生成的对象,或创建过程中有多个聚合协作时,才将其提升为独立的工厂类。
- 如果你想编写的“工厂”只会调用
new,那只是形式主义,并非封装。
核心内容
以下是三种常见形式,仪式感从少到多:
实体上的静态创建方法。 Order.placeFor(customer, items)。当创建逻辑自然属于生成的类型时,优先采用这种方式。方法名使用通用语言。它能封装所需的构造工作,无须引入新类。
专用工厂类。 包含 createFor(applicant, plan, paymentMethod) 方法的 SubscriptionFactory。当创建过程涉及不属于生成实体的编排时使用,例如调用其他聚合、查询引用数据或协调多个输入。
构建器。 用于增量构造的流式构建器。谨慎使用;当聚合有许多可选字段,且必须在最终的 build() 步骤执行验证时,构建器最能发挥作用。确保构建器不会返回无效的中间状态——build() 要么返回经过完整验证的聚合,要么失败。
工厂的职责到返回有效聚合为止。持久化是仓储的工作。将创建和持久化混在一个工厂中会模糊各层的边界。
决策启发
- 从构造函数或静态方法开始。只有当工作对实体来说过于复杂,或涉及多个协作者时,才将其提升为工厂类。
- 工厂的方法名应使用通用语言——
placeOrder、openAccount、issueRefund,而不是create、make、instantiate。 - 如果工厂需要读取或持久化数据,就说明职责混杂了——工厂可能应该放在应用层,或者应该接收已加载的输入。
反模式
- 同时负责持久化的工厂——这会混淆创建职责与生命周期管理。
- 每个实体都机械地对应一个
FooFactory类,即便其create()做的事构造函数也能完成。 - “FactoryFactory”间接层——这几乎总是代码库过度设计的迹象。
- 会交付中间状态的构建器——调用方可以持有尚未构建完成的
Order并调用其方法。
另请参阅
ddd-entity— 工厂通常创建的对象。ddd-aggregate— 工厂创建完整聚合,而非不完整的聚合。ddd-repository— 边界所在;工厂负责创建,仓储负责持久化。
参考资料
- Evans,《领域驱动设计》(2003),第 6 章(领域对象的生命周期)。
评论
支持 Markdown