从需求讨论到 DDD 落地:业务分析、领域边界与公共能力识别

从需求讨论到 DDD 落地:业务分析、领域边界与架构资产沉淀

前言:DDD 不应该从代码分层开始,而应该从需求讨论开始。需求讨论很重要,但我们也要思考“怎么讨论、产出什么、谁来评审、如何落到架构和代码”,让 DDD 思想有更全面的实践。

一、DDD 的起点应前置到需求讨论

很多团队在实践 DDD 时,容易从代码结构开始切入。例如,在工程中划分 domainapplicationinfrastructure,在代码中使用实体、值对象、仓储、领域服务等概念。这些做法本身有价值,但它们属于战术设计和工程实现层面的内容。如果需求阶段没有形成清晰的业务认知,代码结构再规范,也很难真正表达业务。

DDD 的核心不是目录命名,而是让软件模型能够准确反映业务模型。

业务模型的形成,不能等到研发实现阶段才开始。它应当在需求讨论阶段就被识别、澄清和沉淀。可以将一个需求从提出到落地的过程拆成三个阶段:

DDD 阶段 项目环节 核心任务 主要产物
业务分析 需求讨论 识别业务目标、统一语言、业务对象、领域事件、流程状态和业务边界 术语表、事件清单、用例、状态机、规则表
战略设计 技术方案 划分领域、识别限界上下文、区分核心域、支撑域和通用域 上下文边界、领域模型、系统边界、集成关系
战术设计 研发实现 设计聚合、实体、值对象、领域服务、接口、事件和数据模型 代码模型、接口契约、事件契约、表结构、测试用例

这三个阶段不是彼此割裂的流程,而是连续传递的建模链路。业务分析质量不足,战略设计就缺少依据;战略设计不清晰,战术设计就容易退化为围绕数据库表和过程脚本的实现。

因此,需求讨论不应只是确认“要做哪些功能”,而应承担业务建模的职责。

对应的流程应该是这样子:
需求生命周期

二、需求讨论的核心目标

需求讨论的目标不是让产品讲完需求,也不是让研发当场评估工作量,而是让团队对业务事实形成一致认知。

一个有效的 DDD 风格需求讨论,至少应完成四类工作。

1. 明确业务目标

任何建模活动都应从业务目标开始。

需求讨论首先需要回答:

  • 该需求解决什么业务问题;
  • 目标用户或业务角色是谁;
  • 成功标准是什么;
  • 如果不做,会产生什么业务影响;
  • 本期需求与后续规划之间的边界是什么。

如果业务目标不明确,后续讨论很容易陷入页面字段、按钮交互和局部实现细节。DDD 关注模型,但模型必须服务于业务目标,而不是独立存在。

2. 建立统一语言

统一语言是 DDD 落地的基础。

统一语言不仅是会议中的口头约定,还应进入需求文档、原型、接口字段、数据库字段、日志、测试用例和报表指标。否则,同一个业务概念可能在不同角色之间产生多个名称:产品称为“关闭订单”,研发称为“取消订单”,运营称为“作废订单”,数据库中则可能表现为 status = 9

这种语言不一致会持续放大沟通成本,并最终进入代码和数据结构,形成长期维护负担。

统一语言表可以采用简单结构:

名词 定义 别名或禁用叫法 所属上下文 备注
订单 用户一次购买行为形成的业务单据 不等于支付单 订单上下文 描述履约主流程
取消 订单进入终止履约流程 不等于退款完成 订单上下文 可能触发库存、支付、营销联动
退款 支付系统将资金退回用户 不等于取消 支付上下文 由支付系统负责
释放库存 将库存恢复为可售数量 不等于取消成功 库存上下文 依赖订单取消结果
退券 优惠券恢复可用或作废 不等于退款 营销上下文 取决于优惠规则

统一语言表不需要复杂,但必须明确,并且需要在后续设计和实现中持续使用。

3. 识别业务事件

领域事件是连接需求讨论与领域建模的重要抓手。

领域事件描述的是业务中已经发生、且对其他对象或系统产生影响的事实。通过事件识别,团队可以发现业务流程、对象生命周期、系统协作关系和潜在边界。

以订单取消为例,可能存在以下领域事件:

领域事件 触发者 前置条件 后置结果 失败处理
用户申请取消订单 用户 订单未发货 订单进入取消中 返回不可取消原因
订单取消审核通过 订单系统 订单处于取消中 触发库存释放、退款 写入审计日志
库存释放成功 库存系统 订单取消通过 库存恢复可售 失败进入补偿队列
退款发起成功 支付系统 已支付订单 订单进入退款中 记录失败原因并重试
退款完成 支付系统 退款处理中 订单进入已退款 通知用户

事件一旦被梳理出来,系统边界通常会更加清晰。订单、库存、支付、营销并不是同一个模型,它们拥有各自的语言、状态和规则。

4. 明确流程、状态和边界

需求讨论不能只停留在主流程,还要覆盖状态流转、异常路径和系统边界。

只要核心业务对象存在生命周期,就应梳理状态机。仍以订单取消为例:

stateDiagram-v2 [*] --> PendingPay: 创建订单 PendingPay --> Paid: 支付成功 PendingPay --> Cancelled: 超时未支付 Paid --> Cancelling: 申请取消 Cancelling --> Refunding: 取消审核通过 Refunding --> Refunded: 退款成功 Refunding --> RefundFailed: 退款失败 RefundFailed --> Refunding: 重试退款

状态机的价值不在于图形本身,而在于促使团队提前回答以下问题:

  • 哪些状态允许取消;
  • 哪些状态是终态;
  • 失败状态是否允许人工处理;
  • 重复操作如何处理;
  • 支付回调晚到时,如何避免状态被错误覆盖;
  • 状态变化是否需要审计。

这些问题如果不在需求阶段讨论,后续会在技术方案、开发、测试甚至上线后以更高成本重新出现。

三、需求质量应形成明确产物

需求讨论如果只留下会议纪要,很难支撑后续架构设计和研发实现。

建议将需求讨论产物固定为以下几类:

产物 说明 后续用途
统一语言表 核心业务名词、定义、别名、禁用叫法 统一需求、接口、代码、数据字段命名
领域事件清单 事件名称、触发条件、前置状态、后置结果 支撑事件风暴、异步消息、审计日志设计
用例清单 参与者、主流程、异常流程、验收标准 支撑测试用例和接口设计
状态机 核心对象状态和流转规则 支撑并发控制、幂等、索引和权限设计
业务规则表 规则、条件、例外、优先级 支撑领域服务、规则组件或规则引擎设计
边界说明 本系统负责什么,不负责什么 支撑限界上下文和服务边界划分
非功能清单 性能、安全、审计、合规、可观测性 支撑架构设计和上线准入

这些产物并不是为了增加流程负担,而是为了减少后续反复确认和理解偏差。

从研发和测试视角看,需求质量至少应覆盖以下维度:

  • 交互是否明确;
  • 用例是否完整;
  • 主流程和异常流程是否清晰;
  • 状态机是否完整;
  • 功能边界是否明确;
  • 需求粒度是否适合进入开发;
  • 验收标准是否可测试。

对于简单 CRUD 或低风险需求,可以使用轻量 checklist;对于核心域、跨系统、强一致、资金、权限、审计、合规类需求,则应采用完整的业务分析和架构评审流程。

四、从业务分析进入战略设计

业务分析完成后,需要进入战略设计阶段。

战略设计关注的不是接口如何定义,也不是数据库表如何创建,而是领域如何划分、模型边界如何确定、不同上下文之间如何协作。

1. 识别限界上下文

限界上下文是模型边界。

在同一个限界上下文内,术语、规则和模型应保持一致;在不同限界上下文之间,相同词语可能具有不同含义,也可能由不同系统承担责任。

以订单取消为例:

上下文 关注对象 主要职责
订单上下文 订单、订单状态、取消申请 管理订单生命周期和取消流程
库存上下文 库存、占用、释放 管理库存数量和可售状态
支付上下文 支付单、退款单、支付回调 管理资金流转和退款状态
营销上下文 优惠券、积分、活动资格 管理优惠权益的恢复或作废

通过这样的划分,可以避免把所有规则都塞进一个“大订单模型”中。

2. 区分核心域、支撑域和通用域

不是所有领域都具有相同战略价值。

  • 核心域:直接形成业务差异化,需要重点建模和持续演进;
  • 支撑域:支撑核心业务运行,复杂度较高,但不一定形成差异化;
  • 通用域:行业中较通用的能力,可以采购、复用或平台化。

这种区分有助于决定团队投入重点。核心域应尽量保持模型清晰和演进能力;支撑域应关注稳定性和集成效率;通用域应优先考虑复用、标准化和成本控制。

3. 澄清限界上下文与微服务的关系

限界上下文不等于微服务。

限界上下文是模型边界,微服务是部署边界。两者可以一致,但并不必然一致。

在业务尚不稳定、团队规模较小、调用链尚未验证时,可以先在单体或单个服务内部建立模块化边界。是否拆分为微服务,需要综合考虑:

  • 数据归属;
  • 事务一致性;
  • 调用频率;
  • 团队边界;
  • 发布节奏;
  • 运维成本;
  • 故障隔离要求。

如果机械地按限界上下文拆分服务,可能会过早引入分布式事务、链路追踪、服务治理和发布协调成本。

五、从战略设计进入战术设计

战术设计负责将领域模型落到代码、接口、事件和数据结构中。

在这一阶段,团队需要围绕聚合、实体、值对象、领域服务、仓储、应用服务、事件和接口契约进行设计。

以订单取消为例,可以形成如下映射:

业务分析输入 战略设计结果 战术设计动作
用户申请取消订单 订单上下文 设计取消申请命令、订单状态保护、取消规则校验
库存释放成功 库存上下文 设计库存释放事件、库存释放幂等键、补偿任务
退款完成 支付上下文 设计退款事件、支付回调处理、退款状态机
重复取消不能重复退款 跨上下文一致性要求 设计幂等键、唯一约束、状态前置条件
取消和退款必须留痕 审计要求 设计审计日志、操作记录、事件追踪

这类映射可以防止技术方案与需求讨论脱节。

战术设计中还需要明确应用服务与领域模型的职责边界。应用服务负责用例编排、事务边界和外部协作;领域模型负责表达业务规则和状态变化。若所有规则都写在应用服务中,系统仍然容易退化为事务脚本。

从战略设计进入战术设计

六、非功能需求也是需求

需求讨论不能只覆盖功能路径。

从后端开发和 DBA 视角看,很多线上事故并不是因为主流程没有实现,而是因为非功能需求没有被提前识别。

问题 影响
请求是否可能重复提交 决定接口幂等设计
外部回调是否可能重复到达 决定消息去重和状态保护
哪些异常可以重试 决定错误分类和补偿机制
哪些流程必须强一致 决定事务边界
哪些流程可以最终一致 决定事件驱动和补偿任务
是否存在并发修改 决定锁、版本号、状态条件更新
哪些操作需要审计 决定日志和审计表设计
哪些字段属于敏感字段 决定脱敏、权限和合规策略
查询量和数据量规模如何 决定索引、缓存和读模型
是否需要指标和告警 决定可观测性方案

这些内容如果在需求讨论中缺失,后续代码实现即使结构清晰,也很难保证系统可靠性。

公共架构框架应尽量将常见非功能能力沉淀为默认路径,例如:

  • 幂等组件;
  • 事务消息模板;
  • 审计日志 starter;
  • 脱敏注解;
  • 慢 SQL 采集;
  • traceId 传递;
  • 统一异常和错误码;
  • MQ 消费重试和死信处理模板。

这些能力不应依赖每个项目临时补充,而应成为工程基线。

七、DDD 最终需要落到数据层

领域对象不等于数据库表,但领域模型一定会影响数据模型。

领域事件不等于消息表,但会影响审计、消息投递和同步机制。限界上下文不等于数据库 schema,但应帮助团队明确数据所有权。

从 DBA 视角看,需求讨论阶段至少需要明确以下问题:

  • 数据量规模和增长速度;
  • 高频查询条件;
  • 是否存在复杂排序、模糊查询、统计报表;
  • 状态流转是否存在并发修改;
  • 数据保存周期和归档策略;
  • 是否包含敏感字段;
  • 是否需要审计和追溯;
  • 是否存在跨系统共享数据;
  • 是否需要唯一约束防止重复业务动作。

以订单取消为例,如果没有业务唯一键和唯一索引,重复退款就缺少数据库层约束。如果没有状态字段和状态条件更新,并发取消和支付回调可能造成状态覆盖。如果没有审计记录,后续账务核对和问题追溯都会缺少依据。

因此,数据评审应前置到需求讨论或技术方案早期,而不是等表结构设计完成后再补充。

八、从需求中识别公共能力

DDD 风格需求讨论不仅服务于当前需求交付,也可以帮助团队识别可复用、可治理、可沉淀的公共能力。

公共能力至少可以分为三类。

1. 公共组件:横切技术能力

公共组件解决多个系统都会遇到的技术问题,通常业务语义较低,复用价值较高。

典型能力包括:

  • 统一异常和错误码;
  • 日志、链路追踪、指标;
  • 鉴权上下文、租户上下文;
  • 幂等、重试、限流、分布式锁;
  • MQ 发送和消费模板;
  • 数据脱敏、审计埋点;
  • 缓存封装、配置读取。

公共组件应保持能力边界清晰、行为稳定、版本可控,并具备 owner、测试、示例和观测指标。不能将所有重复代码都放入 common 包,否则公共组件会逐渐演变为新的维护负担。

2. 通用组件:跨业务的业务能力

通用组件带有明确业务语义,通常不适合简单封装为工具包。

典型能力包括:

  • 审批流;
  • 通知中心;
  • 文件中心;
  • 规则引擎;
  • 任务编排;
  • 权限中心;
  • 审计平台。

这类能力更接近内部产品,需要具备 owner、SLA、接入文档、权限模型、审计能力、运营指标和版本策略。

以审批流为例,它需要回答审批单、节点、任务、参与人、动作分别是什么,同意、拒绝、撤回、转交、加签如何流转,回调业务方是否需要幂等,审批记录保存多久,不同业务线差异是配置还是扩展点。

这些问题本质上仍然是领域建模问题。

3. 公共架构框架:工程治理体系

公共架构框架不是更大的公共组件,而是工程一致性和治理体系。

它通常包括:

  • parent / BOM:统一 Java 版本、依赖版本、插件版本;
  • 脚手架:统一新服务目录结构和基础能力;
  • starter:沉淀日志、异常、链路、幂等、脱敏等横切能力;
  • 架构约束:依赖方向、模块边界、禁止跨层调用;
  • 契约规范:API、DTO、错误码、事件模型、版本兼容;
  • 数据规范:DTO/PO 隔离、事务边界、审计、脱敏;
  • 可观测基线:日志、指标、trace、告警;
  • 治理机制:准入、升级、废弃、例外审批。

公共架构框架的目标不是让所有服务完全一致,而是在关键问题上保持一致:边界一致、契约一致、可靠性一致、合规一致、演进方式一致。

九、产研协作与组织落地

DDD 风格需求讨论不是技术团队单方面推动的活动,而是产品、研发、测试、架构、DBA 和领域专家共同参与的协作机制。

产品更理解业务目标、用户场景和价值判断;研发更理解系统边界、数据约束和技术风险;测试更容易发现异常路径和验收口径;架构师负责识别领域边界和演进方向;DBA 关注数据所有权、约束、索引、审计和归档。

因此,需求质量提升不能完全归责于某一方。更合理的方式是建立共同目标和共同产物。

从 技术管理视角看,DDD 需求讨论、公共组件、通用组件和公共架构框架都不是零成本能力。它们会增加前置沟通成本,也会消耗平台团队的建设和维护成本。因此,需要根据需求复杂度分级处理:

需求类型 建议方式
简单 CRUD、低风险、短生命周期 轻量评审,保留基本 checklist
核心域、高复杂度、多状态流 完整业务分析和战略设计
跨团队、跨系统、强一致要求 必须架构评审和数据评审
涉及资金、权限、合规、审计 必须补充非功能需求和风险评审
多业务重复出现的能力 评估是否沉淀为公共或通用能力

平台化同样需要评估投入产出,包括覆盖系统数量、减少重复开发程度、降低事故风险程度、升级成本、owner 机制和退出机制。

没有指标和治理机制的平台化,容易形成新的组织负担。

十、总结

DDD 不应只从代码结构开始,而应从需求讨论开始。

需求讨论承担业务分析职责,负责统一语言、识别业务事件、明确对象状态、梳理业务规则、划定系统边界,并补充非功能需求。业务分析形成的产物,应继续进入战略设计,用于识别领域、限界上下文、核心域、支撑域和通用域;再进入战术设计,落到聚合、实体、值对象、领域服务、接口、事件、数据模型和测试用例。

同时,需求讨论还应帮助团队识别公共能力。横切技术能力可以沉淀为公共组件,跨业务能力可以建设为通用组件,工程一致性和治理要求则应进入公共架构框架。

对于团队而言,DDD 风格的需求讨论不是额外流程,而是一种降低理解偏差、提前暴露风险、沉淀架构资产的方法。它既服务于当前需求交付,也服务于长期系统演进。

posted @ 2026-06-23 10:20  鱼007  阅读(12)  评论(0)    收藏  举报