从需求讨论到 DDD 落地:业务分析、领域边界与公共能力识别
从需求讨论到 DDD 落地:业务分析、领域边界与架构资产沉淀
前言:DDD 不应该从代码分层开始,而应该从需求讨论开始。需求讨论很重要,但我们也要思考“怎么讨论、产出什么、谁来评审、如何落到架构和代码”,让 DDD 思想有更全面的实践。
一、DDD 的起点应前置到需求讨论
很多团队在实践 DDD 时,容易从代码结构开始切入。例如,在工程中划分 domain、application、infrastructure,在代码中使用实体、值对象、仓储、领域服务等概念。这些做法本身有价值,但它们属于战术设计和工程实现层面的内容。如果需求阶段没有形成清晰的业务认知,代码结构再规范,也很难真正表达业务。
DDD 的核心不是目录命名,而是让软件模型能够准确反映业务模型。
业务模型的形成,不能等到研发实现阶段才开始。它应当在需求讨论阶段就被识别、澄清和沉淀。可以将一个需求从提出到落地的过程拆成三个阶段:
| DDD 阶段 | 项目环节 | 核心任务 | 主要产物 |
|---|---|---|---|
| 业务分析 | 需求讨论 | 识别业务目标、统一语言、业务对象、领域事件、流程状态和业务边界 | 术语表、事件清单、用例、状态机、规则表 |
| 战略设计 | 技术方案 | 划分领域、识别限界上下文、区分核心域、支撑域和通用域 | 上下文边界、领域模型、系统边界、集成关系 |
| 战术设计 | 研发实现 | 设计聚合、实体、值对象、领域服务、接口、事件和数据模型 | 代码模型、接口契约、事件契约、表结构、测试用例 |
这三个阶段不是彼此割裂的流程,而是连续传递的建模链路。业务分析质量不足,战略设计就缺少依据;战略设计不清晰,战术设计就容易退化为围绕数据库表和过程脚本的实现。
因此,需求讨论不应只是确认“要做哪些功能”,而应承担业务建模的职责。
对应的流程应该是这样子:

二、需求讨论的核心目标
需求讨论的目标不是让产品讲完需求,也不是让研发当场评估工作量,而是让团队对业务事实形成一致认知。
一个有效的 DDD 风格需求讨论,至少应完成四类工作。
1. 明确业务目标
任何建模活动都应从业务目标开始。
需求讨论首先需要回答:
- 该需求解决什么业务问题;
- 目标用户或业务角色是谁;
- 成功标准是什么;
- 如果不做,会产生什么业务影响;
- 本期需求与后续规划之间的边界是什么。
如果业务目标不明确,后续讨论很容易陷入页面字段、按钮交互和局部实现细节。DDD 关注模型,但模型必须服务于业务目标,而不是独立存在。
2. 建立统一语言
统一语言是 DDD 落地的基础。
统一语言不仅是会议中的口头约定,还应进入需求文档、原型、接口字段、数据库字段、日志、测试用例和报表指标。否则,同一个业务概念可能在不同角色之间产生多个名称:产品称为“关闭订单”,研发称为“取消订单”,运营称为“作废订单”,数据库中则可能表现为 status = 9。
这种语言不一致会持续放大沟通成本,并最终进入代码和数据结构,形成长期维护负担。
统一语言表可以采用简单结构:
| 名词 | 定义 | 别名或禁用叫法 | 所属上下文 | 备注 |
|---|---|---|---|---|
| 订单 | 用户一次购买行为形成的业务单据 | 不等于支付单 | 订单上下文 | 描述履约主流程 |
| 取消 | 订单进入终止履约流程 | 不等于退款完成 | 订单上下文 | 可能触发库存、支付、营销联动 |
| 退款 | 支付系统将资金退回用户 | 不等于取消 | 支付上下文 | 由支付系统负责 |
| 释放库存 | 将库存恢复为可售数量 | 不等于取消成功 | 库存上下文 | 依赖订单取消结果 |
| 退券 | 优惠券恢复可用或作废 | 不等于退款 | 营销上下文 | 取决于优惠规则 |
统一语言表不需要复杂,但必须明确,并且需要在后续设计和实现中持续使用。
3. 识别业务事件
领域事件是连接需求讨论与领域建模的重要抓手。
领域事件描述的是业务中已经发生、且对其他对象或系统产生影响的事实。通过事件识别,团队可以发现业务流程、对象生命周期、系统协作关系和潜在边界。
以订单取消为例,可能存在以下领域事件:
| 领域事件 | 触发者 | 前置条件 | 后置结果 | 失败处理 |
|---|---|---|---|---|
| 用户申请取消订单 | 用户 | 订单未发货 | 订单进入取消中 | 返回不可取消原因 |
| 订单取消审核通过 | 订单系统 | 订单处于取消中 | 触发库存释放、退款 | 写入审计日志 |
| 库存释放成功 | 库存系统 | 订单取消通过 | 库存恢复可售 | 失败进入补偿队列 |
| 退款发起成功 | 支付系统 | 已支付订单 | 订单进入退款中 | 记录失败原因并重试 |
| 退款完成 | 支付系统 | 退款处理中 | 订单进入已退款 | 通知用户 |
事件一旦被梳理出来,系统边界通常会更加清晰。订单、库存、支付、营销并不是同一个模型,它们拥有各自的语言、状态和规则。
4. 明确流程、状态和边界
需求讨论不能只停留在主流程,还要覆盖状态流转、异常路径和系统边界。
只要核心业务对象存在生命周期,就应梳理状态机。仍以订单取消为例:
状态机的价值不在于图形本身,而在于促使团队提前回答以下问题:
- 哪些状态允许取消;
- 哪些状态是终态;
- 失败状态是否允许人工处理;
- 重复操作如何处理;
- 支付回调晚到时,如何避免状态被错误覆盖;
- 状态变化是否需要审计。
这些问题如果不在需求阶段讨论,后续会在技术方案、开发、测试甚至上线后以更高成本重新出现。
三、需求质量应形成明确产物
需求讨论如果只留下会议纪要,很难支撑后续架构设计和研发实现。
建议将需求讨论产物固定为以下几类:
| 产物 | 说明 | 后续用途 |
|---|---|---|
| 统一语言表 | 核心业务名词、定义、别名、禁用叫法 | 统一需求、接口、代码、数据字段命名 |
| 领域事件清单 | 事件名称、触发条件、前置状态、后置结果 | 支撑事件风暴、异步消息、审计日志设计 |
| 用例清单 | 参与者、主流程、异常流程、验收标准 | 支撑测试用例和接口设计 |
| 状态机 | 核心对象状态和流转规则 | 支撑并发控制、幂等、索引和权限设计 |
| 业务规则表 | 规则、条件、例外、优先级 | 支撑领域服务、规则组件或规则引擎设计 |
| 边界说明 | 本系统负责什么,不负责什么 | 支撑限界上下文和服务边界划分 |
| 非功能清单 | 性能、安全、审计、合规、可观测性 | 支撑架构设计和上线准入 |
这些产物并不是为了增加流程负担,而是为了减少后续反复确认和理解偏差。
从研发和测试视角看,需求质量至少应覆盖以下维度:
- 交互是否明确;
- 用例是否完整;
- 主流程和异常流程是否清晰;
- 状态机是否完整;
- 功能边界是否明确;
- 需求粒度是否适合进入开发;
- 验收标准是否可测试。
对于简单 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 风格的需求讨论不是额外流程,而是一种降低理解偏差、提前暴露风险、沉淀架构资产的方法。它既服务于当前需求交付,也服务于长期系统演进。

浙公网安备 33010602011771号