跳转至

CleanDDD 的定义

什么是 CleanDDD?

CleanDDD 即 Clean Domain-Driven Design,是基于领域驱动设计(DDD)的核心理念,经过概念简化和重构,形成的一套实用的软件工程指南,它包含四个重要组成部分:

  • 一个价值取向
  • 一组概念定义
  • 一种建模方法
  • 一套代码规范

CleanDDD 的目标

通过明确的概念和易于遵守的原则,避免代码快速腐化陷入混乱不可维护的困境,帮助开发者掌控复杂的软件系统,保持对软件系统和代码的掌控力,从而实现可持续的快速迭代和交付能力。

CleanDDD 的价值取向

保持边界明确是最重要的事。

CleanDDD Skills(AI Agent 支持)

我们提供了 cleanddd-skills 项目,面向 AI Agent 提供 CleanDDD 的能力支持与可复用技能集,便于在自动化场景中调用。

项目地址:

  • https://github.com/netcorepal/cleanddd-skills

CleanDDD 的概念定义

  • 聚合:负责独立维护业务核心数据和行为的对象集合,具有明确的边界和一致性规则。
  • 领域事件:由聚合行为产生的、反映业务事件发生的对象,通常以过去式命名。
  • 领域事件处理器:负责基于领域事件创建并发出相应的命令。
  • 命令:由用户操作或系统事件触发的、请求修改聚合状态的对象。
  • 命令处理器:负责操作聚合以实现业务需求。
  • 查询与查询处理器:负责从聚合中获取数据以满足用户的查询需求。
  • 定时任务:在特定时间或周期性地执行某些操作的任务,通常用于发出命令修改聚合状态。
  • 集成事件:在不同系统之间传递信息的事件,通常由领域事件转化而来,并在 MQ 等消息中间件中传递。
  • 集成事件处理器:处理集成事件并发出相应命令的组件,通常位于接收系统中。

CleanDDD 的建模方法

  • 识别聚合
    • 当识别到“创建 x”的需求时,很可能 x 就是一个聚合。
    • 当发现 x 无法独立存在,需要依附到另一个实体时,x 可以定义为该实体的子实体。
  • 识别命令与命令处理器
    • 当某个操作需要修改聚合状态时,这个操作就可以定义为一个命令。
    • 命令通常由以下情形触发:
      • 用户操作(如通过 UI 提交表单)
      • 领域事件处理器
      • 定时任务
  • 识别领域事件
    • 领域事件通常以过去式命名,表示某个重要业务事件已经发生。
    • 命名应反映业务含义,例如 OrderCreatedCustomerAddressUpdated
  • 识别领域事件处理器
    • 当识别到“当做 x 操作后,要做 y 操作”的需求时,y 操作应由领域事件处理器触发。
    • 每个领域事件处理器应专注于处理单一领域事件,确保职责清晰。
  • 识别查询
    • 当用户需要查看聚合数据时,这个操作就可以定义为查询。
    • 当业务规则判断需要基于聚合数据时,这个操作也可以定义为查询。

CleanDDD 的代码规范

  • 聚合
    • 聚合之间不允许直接相互引用。
    • 聚合之间不共享实体,即不允许通过子实体对象引用其他聚合。
    • 聚合内对象只能通过聚合根或其子实体的方法进行修改。
    • 聚合属性变更必须通过聚合的行为(方法)来完成。
  • 领域事件
    • 领域事件必须由聚合的行为产生。
  • 命令处理器
    • 命令处理器只能修改单个聚合。
  • 事件处理器
    • 一个事件处理器只能处理单个领域事件。
  • 查询
    • 不允许跨聚合的 Join 查询。

Q&A

CleanDDD 与 Clean Architecture 关系是怎样的?

CleanDDD 与 Clean Architecture 并无直接关系,在代码组织方式上有一定相似性,但两者的关注点和目标不同,涉及的分层概念也不完全相同。CleanDDD 的 Clean 更强调对复杂概念的简化与实践便捷性,而不是指代某种特定架构风格。

基于 CleanDDD 开发的软件,性能会不会很差?

不会。大部分业务系统是 I/O 密集且读多写少的场景。CleanDDD 强调聚合边界明确,不允许跨聚合直接引用和操作,会带来一定的信息冗余,从而减少跨聚合数据访问需求,反而提升整体性能。