DDD 在社区里喊了十年,真正落地的团队屈指可数。问题不在理论本身,而在于大多数团队缺少一个把业务专家和工程师拉到同一面墙前的实操手段——事件风暴恰好填补了这个空缺。
一场 4 小时的事件风暴工作坊,能把三个月的需求分析压缩到半天。这不是夸张,是我在多个项目里反复验证过的事实。
为什么传统需求分析总是慢半拍
你肯定经历过这种场景:产品经理写了一份 50 页的 PRD,开发团队读完发现一堆模糊地带。来回沟通两周,终于开始写代码。上线后发现业务方想要的根本不是这个东西。
根因很简单。PRD 是单线程的信息传递,缺少反馈回路。业务专家脑子里的流程和工程师理解的流程之间,隔着一层厚厚的翻译损耗。
事件风暴把所有人关在一个房间里,用便利贴在一面长墙上共同建模。业务事件是唯一的沟通语言,歧义在产生的那一秒就被消除。
一个做过 20 多场工作坊的架构师说过:事件风暴最大的价值不是产出模型,而是让所有人在 4 小时内达成对业务的共识。模型只是共识的副产品。
4 小时工作坊的完整节奏
把 4 小时拆成 5 个阶段,每个阶段有明确的时间盒和产出物。节奏感很重要,拖沓的工作坊会让参与者失去耐心。
| 阶段 | 时长 | 核心活动 | 产出物 |
|---|---|---|---|
| 准备与热身 | 20 分钟 | 规则讲解、破冰 | 统一认知 |
| 事件发现 | 80 分钟 | 写领域事件、时间线排序 | 事件流 |
| 命令与角色识别 | 50 分钟 | 反推命令、标注角色和系统 | 命令-事件链 |
| 聚合与限界上下文 | 60 分钟 | 识别聚合根、划分边界 | 上下文地图 |
| 收敛与验证 | 30 分钟 | 走查流程、标注热点 | 待确认问题清单 |
中间安排 2 次 10 分钟休息,实际工作量大约 4.5 小时。
准备阶段:别在起跑线翻车
人员构成是成败关键
理想的参与者是 6-10 人。少了覆盖不全业务知识,多了容易失控。
必须有这几类人:
- 业务专家:真正干活的一线人员,不是只听汇报的管理层。一个做过订单履约的运营,比三个只看过报表的产品经理有用得多。
- 技术骨干:对系统现状有全局认知的架构师或资深开发。
- 引导者:熟悉事件风暴规则的 Facilitator,负责控场和推进节奏。
很多团队犯的错误是只叫产品经理来代表业务方。产品经理对业务的理解是二手的,细节经不起追问。一定要拉一线操作人员。
物理环境
一面至少 6 米长的墙(或白板),足够贴 200-300 张便利贴。
便利贴准备四种颜色:
| 颜色 | 用途 | 尺寸建议 |
|---|---|---|
| 橙色 | 领域事件 | 76×76mm |
| 蓝色 | 命令 | 76×76mm |
| 黄色 | 角色/外部系统 | 76×127mm |
| 粉色 | 热点/疑问/争议 | 76×76mm |
线上工作坊用 Miro 或 FigJam,模板提前搭好。但说实话,线下效果永远比线上好。面对面时的肢体语言和即时讨论,是屏幕传达不了的。
确定工作坊的叙事主线
开工前,引导者要和业务方对齐一个"叙事范围"。比如"从客户下单到货物签收的全流程"。范围太大铺不开,太小又没有建模价值。
一个经验法则:选一条端到端的业务主线,涉及至少 3 个部门或系统的协作。这种范围的颗粒度刚好能在 4 小时内跑完。
事件发现:让业务自己讲故事
这是整个工作坊最核心的阶段。
规则极其简单
每人拿一叠橙色便利贴,用"过去时态"写出业务中发生的事件。比如"订单已创建"、“支付已完成”、“库存已扣减”。
写的时候不用商量,各写各的。写完直接贴到墙上,按时间顺序从左到右排列。
这个"各写各的"是刻意设计的。如果一开始就讨论,强势的人会主导话题,沉默的专家脑子里的关键细节就丢了。
时间线合并的威力
10 分钟后,所有人停笔,开始一起看墙上的事件流。这时候神奇的事情发生了——
同一个业务环节,不同人写的事件粒度完全不同。运营写的是"发货单已审核",开发写的是"订单状态已更新",仓储写的是"拣货任务已生成"。
这些差异就是宝藏。每一个差异背后都藏着一个被忽略的业务规则或系统边界。
在某个电商项目的工作坊里,运营团队贴了"退货申请已提交",客服团队贴了"退货工单已创建"。两个事件看起来差不多,一聊才发现中间隔了一个自动风控审核环节,这个环节在现有系统里完全没有体现。
处理分歧和热点
遇到大家说不清楚的事件,或者有人明确反对某个事件的存在,贴一张粉色便利贴标记为"热点",继续往下走。
不要在热点上纠缠。事件风暴的节奏是"先铺全貌,再深挖细节"。一个热点卡住 15 分钟,后面的事件就铺不出来了。
引导者在这个阶段的核心职责是控节奏和提问。常用的追问句式:
- “这个事件发生之后,紧接着会发生什么?”
- “有没有例外情况?什么时候这个事件不会发生?”
- “这个事件是谁触发的?还是系统自动触发的?”
命令与角色识别:反推因果链
事件流铺完之后,团队开始从右往左回溯——每个事件是怎么发生的?
命令是事件的因
“订单已创建"这个事件,是"提交订单"这个命令触发的。在橙色便利贴左边贴一张蓝色便利贴,写上命令名称。
命令用祈使句:“提交订单”、“审批发货单”、“发起退款”。
这个反推过程会暴露很多隐藏逻辑。有些事件的触发命令很明确,有些事件却找不到命令——说明这个事件可能是定时任务、消息消费或外部回调触发的。
标注角色和外部系统
命令是谁发出的?在命令左边贴黄色便利贴,标注执行者。
执行者可能是:
- 人:客户、运营人员、财务审核员
- 外部系统:支付网关、物流平台、ERP
- 定时任务:每日对账、过期自动取消
一个常见的陷阱是把所有执行者都写成"系统”。这等于什么都没说。要追问到具体是哪个角色在哪个场景下操作了什么。
补充读模型
有些命令的触发条件很复杂,需要展示信息给用户做决策。这时候可以加一张白色便利贴表示"视图/读模型",标注用户做决策时看到了哪些信息。
比如"财务审核员"在点击"审批通过"之前,需要看到"订单金额、历史退货率、客户信用等级"。这个读模型就是后续设计查询接口的输入。
聚合识别:找到领域的骨架
什么是聚合
到这一步,墙上已经贴满了事件、命令和角色。接下来要回答一个关键问题:这些命令作用在什么东西上面?
“提交订单"作用在"订单"上。“扣减库存"作用在"库存"上。“创建拣货任务"作用在"拣货单"上。
这些"东西"就是聚合。在事件和命令下面贴一张大的黄色便利贴,写上聚合名称。
聚合是 DDD 中最实操的概念之一。它定义了数据一致性的边界——同一个聚合内的状态变更必须原子性地完成,跨聚合的变更通过事件异步协调。
聚合粒度的判断标准
新手最常问的问题:聚合到底该多大?
两个判断维度:
事务一致性。如果两个数据项必须在同一个事务里一起更新,它们大概率属于同一个聚合。订单行项和订单头必须在同一个事务里创建,所以它们是同一个聚合。
生命周期。如果两个东西的生命周期完全不同,硬塞在一起只会让聚合变得臃肿。用户和用户的收货地址看起来关系很近,但地址的增删改查完全独立于用户本身的生命周期。
| 信号 | 说明 |
|---|---|
| 一个聚合超过 5 个实体 | 粒度可能太粗 |
| 两个聚合经常在同一事务里修改 | 考虑合并 |
| 聚合内某个实体有独立的查询需求 | 考虑拆出 |
| 并发冲突频繁 | 聚合粒度太粗 |
真实案例:物流系统的聚合拆分
在一个同城配送项目里,工作坊上团队最初把"配送单"和"骑手轨迹"放在一个聚合里。讨论后发现,骑手轨迹是每秒上报一次的高频写入,配送单是状态机驱动的低频更新。两者的写入频率差了两个数量级。
拆成两个聚合之后,轨迹上报走独立的写入通道,配送单状态变更通过事件驱动。系统的写入性能提升了 8 倍。
这种洞察,在传统的 PRD 评审里几乎不可能产生。只有一线开发者和业务专家同时看着墙上的事件流,才能发现这种数据访问模式的差异。
限界上下文划分:划定系统的国境线
从聚合到上下文
聚合是领域内的"城市”,限界上下文是"国家”。一个国家包含若干城市,有明确的国境线,国境线两侧的语言含义可能不同。
“商品"这个词在商品管理上下文里指的是 SKU、价格、描述。在仓储上下文里指的是货位、重量、体积。在推荐上下文里指的是标签、热度、关联关系。
同一个词在不同上下文里含义不同——这是限界上下文存在的意义。
划分方法
把墙上相关的聚合圈在一起,用大圆圈标注限界上下文。判断标准:
- 语言一致性:这组聚合共享同一套术语体系吗?
- 团队协作边界:这组聚合由同一个团队维护吗?
- 变更频率:这组聚合的变更节奏一致吗?
一个做 SaaS 的团队在工作坊上发现,他们的"合同"概念在销售侧和财务侧完全是两个东西。销售关心的是签约条款和回款计划,财务关心的是发票和收入确认。拆成两个上下文之后,两边的模型各自简化了 60%。
上下文之间的集成模式
画出上下文之间的关系,常见的集成模式有三种:
共享内核:两个上下文共用一部分模型。适合紧密协作的团队,但维护成本高。
客户-供应商:上游提供接口,下游消费。最常见也最健康的模式。
防腐层:下游对接一个老旧的或不可控的外部系统,中间加一层翻译。保护自身模型不被外部污染。
在工作坊产出的上下文地图上,用不同线型标注集成关系:实线表示同步调用,虚线表示异步事件,波浪线表示防腐层。
常见踩坑点
把事件风暴开成需求评审会
最常见的翻车模式:业务方说一个事件,开发团队立刻开始讨论技术方案。“这个用消息队列还是直接调用?"、“数据库怎么设计?”
引导者必须果断打断。事件风暴的目标是理解业务领域,不是做技术设计。技术方案的讨论放到后续的设计阶段。
事件粒度失控
有人写"用户完成了一次包含优惠券的在线支付并在三个工作日后发起了退货”。这不是一个事件,这是五个事件揉在一起。
判断标准:一个事件描述一个不可再分的状态变化。如果你需要用"并且"来连接两个状态变化,就应该拆成两个事件。
粉色便利贴泛滥
如果墙上一半都是粉色热点,说明工作坊的范围选太大了,或者业务方对流程本身没有达成共识。
这种情况下应该缩小范围,聚焦最核心的一条业务主线。其他分支留到下一场工作坊处理。
引导者经验不足
事件风暴的引导者不是简单的主持人。需要对 DDD 有深入理解,能在混乱中识别模式,在分歧中引导收敛。
如果团队内部没有合格的引导者,可以考虑请外部顾问带前两三场,内部人员观摩学习后逐步接手。
工作坊产出的后续落地
4 小时的工作坊结束后,你会得到一面贴满便利贴的墙。但这只是起点。
接下来的两周是关键窗口期。热度还在的时候,架构师要把墙上的产出转化为正式的领域模型文档和上下文地图。
推荐的后续动作:
- 拍照存档:每个区域高清拍照,便利贴内容录入电子文档。
- 模型验证:用墙上的事件流做一遍"桌面走查”,模拟真实的业务场景,验证模型是否覆盖了主要路径和异常路径。
- 技术 Spike:针对热点和争议点做技术验证,用最小代价确认方案的可行性。
- 迭代建模:对核心域做更细粒度的建模工作坊,这次可以深入到实体属性和领域服务的层面。
有个团队在事件风暴后直接按上下文地图拆分了微服务边界。三个月后回头看,当初划定的 7 个上下文中只有 1 个做了调整。这比传统的"先做单体再拆分"路径节省了至少半年的架构调整时间。
适用边界
事件风暴不是万能的。它最适合的场景是业务流程复杂、多团队协作、领域知识分散的项目。
对于纯技术项目(比如开发一个缓存中间件),或者业务逻辑极其简单的 CRUD 系统,事件风暴的投入产出比不高。
另外,事件风暴对参与者的专注度要求很高。如果团队成员已经被日常需求压得喘不过气,硬拉来做 4 小时工作坊,效果不会好。选一个相对宽松的时间窗口,让参与者能全身心投入。
事件风暴的真正力量不在于那些便利贴,而在于它创造了一个场域——让不同背景、不同视角的人,在有限的时间里,对同一个业务现实达成深层共识。模型会演进,便利贴会褪色,但那份共识会沉淀到团队的每一次设计决策中。
