在考虑如何对业务模型进行抽象从而建立领域模型之前,必须解决业务与产品、开发之间“沟通”的问题。如何让业务人员和开发人员顺畅沟通,在业务流程设计中不遗漏成败攸关的业务场景?如何才能让业务沟通的过程顺畅过渡到架构设计、编码乃至测试?阿里巴巴技术专家李建结合团队的实际案例,分享了他们在使用 Event Storming(事件风暴) 进行领域建模时的经验、收获和思考。
一 软件研发的困境
“失效”的语言交流
日常研发过程中不同角色经常需要进行各种交流:沟通业务需求、讨论产品原型、讨论设计方案等。每个环节不同角色反复沟通,这是研发过程非常重要的环节。但问题是:我们花费大量时间沟通,真的“说” 清楚了吗?
让我们看两个例子:
上面的两段对话发生在一次项目 Review 的过程中。通过第一个对话,我们能看出不同的角色在沟通的时候遇到了障碍;通过第二个对话说明即便是相同的角色,沟通在某种程度也遇到了障碍。
软件研发的困境
无论传统的瀑布流程还是敏捷模式,软件研发总体上能划分成几个阶段:提出需求,产品设计,研发,测试,最后上线。不同阶段会产出不同交付物,有些比较简单,也有些比较详尽:MRD,PRD,技术方案,验收方案等。在整个过程中,我们还会组织不同会议,或者是线下讨论。
大家想一想,在哪一个阶段暴露了最多的问题?
不管我们多么期望在早期发现问题,然而现实是越到研发晚期越会暴露更多问题。当产品进入测试阶段,当上线后真实数据开始跑起来,当业务同学开始使用产品,这时候问题会像泉水一样主动涌现出来,用户会反馈各种问题:“这个不是我想要的功能”,“XX 和我的预期不一样”等等。通常在软件研发的后期发现很多这种类似的问题。软件研发发展到今天,这个问题依然没有被很好的解决。
阻碍产品正确交付的原因
我们通过下面一个例子来分析什么原因阻碍了产品的正确交付。
当产品同学提出需求的时候,研发同学做了好的回应,但实际上双方想的内容并不一致,这种情况我们称之为表面一致;当产品上线后,产品同学提出需求疑问时,研发同学的回答充满了各种技术行话:定时系统,原子性等。显然大部分产品同学不能理解这些技术行话,对话进入停滞状态,我们称这种现象为沟通障碍。在软件研发中该问题反复的出现:沟通不畅阻碍了产品价值的正确交付。在不同角色进行交流时,三个原因阻碍了沟通的顺畅进行:
- 得到的信息不同:产品同学和业务同学关注的是业务需求,市场情况,近中远期规划,以及运营数据等;开发同学关注的是一个个具体的需求列表,功能点,是实现层次的细节信息。
- 思维方式不同:产品同学关注业务/需求的合理性,产品逻辑,用户体验;而开发同学关注方案的可行性,实施成本,系统稳定性等。
- 沟通语言不同:产品同学用描述性的语言,语言的模糊会导致不同角色理解的不同;而开发同学习惯使用技术语言,SDK、数据库、一致性等。不同角色交流的时候,会因为语言不相容,沟通不到一起去。
由于以上的原因,沟通容易陷入“鸡同鸭讲”的窘境:讨论很热烈,甚至能取得表面的一致,实际并没有“说”清楚。
洞察软件研发困境
Event Storming 方法的发明者 Alberto Brandolini 认为:产品体现了程序员对业务的理解(或误解)。很多时候沟通失败导致的误解进入产品实现。于是真正的业务需求在产品中没有得到体现。沟通失败是软件研发的一个痛点,有待解决。
二 Event Storming
Event Storming 介绍
Event Storming(ES):由不同角色共同参与,用彩色贴纸进行交流的工作坊。
如上图,一群同学围绕一个业务场景,用贴纸进行交流,这就是 ES 工作坊。通过贴纸进行交流,让大家用同一种沟通语言,同一个思维方式,让大家的思维在一个频道上,这是 ES 的形式,也是 ES 的目的。
Event Storming 语法
ES 定义了一套彩色贴纸的“语法”:不同颜色的贴纸都有定义。浅黄色代表 Actor (角色)、蓝色表示 Command (命令)、粉色代表 Policy (业务规则)、浅粉色代表System(系统)、橙色代表 Event (事件),浅绿色表示 Read Model (读模型)、红色代表 HotSpot (热点/问题)。
用 ES 的语法表达用户的下单流程:买家 (浅黄色贴纸) 提交订单(蓝色贴纸),如果订单里商品是在线状态,购买量小于商品库存量 (粉色贴纸 Policy) ,那么订单创建成功(橙色事件贴纸),已创建的订单 (绿色贴纸) 展示给用户。订单创建后需要通知买家(业务规则,粉色贴纸),系统执行发送站内信(蓝色贴纸)。
如何在业务中使用 ES
下面我们通过一个业务场景(优惠券的投放和使用)介绍如何使用 ES。
业务背景介绍
电商网站提供各种优惠券:满减券,折扣券,有无门槛券。
下图描述电商运营小二在活动中投放优惠券的整体流程:小二先创建优惠券,然后再创建一个活动,把优惠券和活动关联起来。活动通过公司财务的审批后才可发布上线。消费者在活动页面领取优惠券,在下单流程使用优惠券抵消金额。最后活动结束时要对整体活动的数据进行统计分析。
准备 Event Storming
在开始 ES 前,先做好准备:
- 准备物料:彩色贴纸、笔纸、一个足够大的房间等。房间里不要有椅子,因为在 ES 过程中,我们希望大家都全神贯注的投入,而不是坐在椅子上开始放松。
- 邀请正确的人:有问题的人和有答案的人。程序员、交互设计师、测试等都是有问题的人,需要通过 ES 理解业务和产品;有答案的人通常是用户、业务或产品,他们通常能回答业务的背景,诉求和目标。
Event Storming 的过程
ES 可以分为开场介绍、ES 沟通业务和讲故事三个阶段。
开场介绍
在 ES 中有一个特殊的角色叫做 Facilitator(推动者),一般是 ES 的组织者。在 ES 开始前,Facilitator 向大家介绍 ES 是什么,有什么好处,以及彩色贴纸的用法。然后介绍讨论的范围和目标。
比如,今天讨论优惠券场景,目标是理清营销活动过程中优惠券的业务流程。最后 Facilitator 强调 ES 的规则:所有的讨论都写在贴纸上;不允许使用电脑,手机;也不允许坐下。在 ES 的后续过程中,Facilitator 还需要承担另外两个重要职责:保持参与者的专注,通过提问驱动交流。
ES 的方式沟通业务
第一步先梳理事件(橙色贴纸): 事件是已发生且重要的事情。事件必须是既成事实,且业务关注的事情。通常 Facilitator 会先准备第一个事件(可以是系统中任一事件), 然后把它贴到墙上。
假设第一个事件是:优惠券已领取。接下来 Facilitator 通过提问引导大家找到更多的事件:
- 事件发生前有哪些事件(“优惠券已领取”前须先有“活动已发布”事件)?
- 事件发生后下一个事件是什么(“优惠券已领取”后有“优惠券已使用”,“优惠券已过期”等事件)?
提问会引导参与 ES 的同学将新发现的事件不断补充到墙上。事件要保持整体的时间顺序:先发生的事情贴在左边,后发生的事情在右边。通常大家容易关注系统的正常流程,也就是 Happy path。这时候 Facilitator 需要引导大家关注业务的非正常流程 Unhappy path。边界条件,异常情况通常是业务复杂性的重要原因,也是非常容易被忽视的部分。
- 事件一定会发生吗(优惠券一定领取成功吗?不是,贴上“优惠券领取失败”事件)?
追问 unhappy path 梳理出业务的完整视图,当大家发现新事件的速度接近停滞的时候,就应进入梳理业务规则的阶段了。
Policy,业务逻辑或规则,这是业务中最重要的部分。Facilitator 会提出以下问题:
- 事件是否一定成功?如果不是,那么成功的前提条件是什么?
- 该事件是否会导致其他事件的发生(Reaction)?
例如“活动已提交”事件:
- 活动提交成功的前提条件:活动已关联有效优惠券,且已选择了生效方式,并且选择了适用人群。
- 活动提交后,会导致审核任务已创建事件,这里的业务规则是:活动提交或需创建审核任务。
接下来找出三个角色:Actor (和系统交互的人),Command (用户动作) 和 Read Model (辅助用户决策的工具)。Facilitator 提出以下问题:
- 是什么触发了事件?即事件发生的原因 (ES 的语法:when Event, then Command)。
- 谁执行了动作。是人,系统,还是时间(例如定时触发的事件)?
- 做出动作前,用户需要获取哪些信息?
以上的问题会引导大家找到 Actor, command 和 Read Model。 在营销活动已提交事件中:小二(Actor)执行了提交活动(Command), 从而产生了“活动已提交”事件。
最后介绍 Hotspot:业务痛点、瓶颈、模糊点。Hotspot 是 ES 过程中随时都应该发现并记录下来的。Facilitator 可以引导大家发现业务中未描叙到的问题,例如:用户使用优惠券进行支付的场景中,如果用户支付失败,已使用的优惠券该如何处理呢?优惠券应该返还给用户,还是不做处理?通过提出这样的问题,引导大家对业务流程进行更深入的讨论。通常在 ES 的过程中,识别并记录 Hotspot,不要在 ES 中尝试解决所有的 hotspot。
以上介绍了 ES 的主要元素:Event,Policy,Actor,Command,Read Model,Hotspot。用 ES 描述了优惠券发放的业务流程,最后一步是“讲故事” (storytelling) 的阶段。
讲故事
Facilitator 邀请不同的人担任志愿者,每个志愿者讲一段故事:按时间顺序和 ES 描叙的逻辑, 向其他人介绍业务流程。过程中,听众注意到不一致的地方随时提出问题,大家讨论问题,通过增加/删除/移动贴纸来修复问题,并继续讲故事的流程。
最开始大家会按时间正序讲故事,最后大家还可以倒序讲故事。梳理业务的异常场景,倒序讲故事的方法更有效。例如为什么会发生“优惠券领取失败”事件,事件的原因是 balabala…
经过讲故事阶段的完善,大家获得了业务的完整理解,这时候可以结束讨论,保存相关材料,遗留下来的 Hotspot 交由相关同学跟进。
Event Storming 常见问题
ES 比其他方式更能帮助大家顺畅的沟通,但是对于首次参与或组织 ES 的同学也有一些疑问。 以下列出一些常见问题:
Q:ES 通常邀请多少人参加?我需要邀请所有角色吗?
A:不一定。ES 鼓励不同角色共同参与,但是参与人的态度更重要,积极主动参与是 ES 成功的关键。通常一个 Pizza (8 - 10人) 的规模,是适合 ES 人数。
Q:我的业务场景和复杂,在 ES 中要梳理完整个业务流程吗?
A: 不需要。ES 需要大家高度参与,因此需要控制好时间。每次 ES 的范围选择复杂业务场景的一部分,保证 ES 的效果。
Q:我应该在什么阶段做 ES?
A:项目的任何阶段都可以做 ES。ES 既可用于梳理业务现状,也可以用于设计业务的未来方案。
Event Storming 小结
下面的四个图直观的解释了 ES 的作用:
- 图 1,说明不同角色通过语言交流,虽然达成表面一致,实际上大家理解不一致。
- 图 2,ES 要求大家通过贴纸的形式可视化出来脑海中的想法,从而使分歧自动显现。
- 图 3,ES 通过不断的提问触发讨论,从而能够拉通认知,消除分歧点和模糊点。
- 图 4,ES 拉通了大家对业务的理解,从而达成了真正的共识。
总的来说,ES 让不同的角色用同一种语言(彩色贴纸)从全局对业务达成共识。
从 ES 到代码
简单介绍下 ES 如何顺畅过渡到 DDD(Domain-Driven Design 领域驱动设计)。
提取业务概念
DDD 中最重要的是统一语言:交流使用统一语言;模型表达统一语言;代码表达统一语言。语言是由概念组成的,ES 的过程已经将概念写在贴纸上,并且在交流中反复使用。例如:优惠券,营销活动,已领取优惠券,领取方式,人群等。
一部分概念有生命周期,并且有唯一的标识符。例如:营销活动,优惠券,已领取优惠券。这些就是 DDD 中的实体;还有一部分概念标识一个完整的业务含义,但是没有生命周期,并且属性相同的两个对象可以替换,这些对象就是 DDD 中的值对象,例如:领取方式,生效方式,人群。
提炼模型
概念和概念之间是有关系的。比如说,优惠券和营销活动有关联关系,已领取优惠券是在某个营销活动下领取的,营销活动也包含很多信息,它的生效方式是什么,领取方式是什么,人群是谁。概念与概念之间的关系也就是领域模型。
从模型到实现
将 ES 贴纸重新组合:围绕一个核心概念,将与该概念有关的 Event,Command,Policy 组合在一起。例如下图左边围绕营销活动为中心重新组织了贴纸(Command,Policy,Event),这些贴纸和右边的代码映射起来,这也就是 DDD 中说的代码表达统一语言。到此,简单介绍了如何从 ES 到概念,从概念到模型,以及模型和代码实现是怎么关联起来的。
架构,代码和约束
下图简单描述应用架构,代码结构,以及如何通过 ArchUnit 实现架构约束。
四 总结
ES 的价值在于:不同角色在具体业务场景下用一种共同语言(彩色贴纸)进行交流,通过不断提问触发探索、讨论,最终达成真正共识。