mcpField
D
ddd-factory

ddd-factory

github.com/yonatankarp开发144 次安装23 周前更新
代码仓库

关于 ddd-factory

ddd-factory 是用于设计 DDD 工厂的技能,适合对象创建复杂或具有领域含义的场景,可生成完整且有效的聚合或值对象。它帮助开发者在构造函数、实体创建方法、独立工厂和构建器之间做选择,并将持久化留给仓储。

主要功能

  1. 01三种工厂形式的设计指导
  2. 02选择创建方式的判断标准
  3. 03使用领域语言命名的方法
  4. 04创建时验证对象有效性
  5. 05区分对象创建与持久化

适用场景

  1. 01根据多个输入创建聚合
  2. 02在对象创建时维护不变量
  3. 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