03 事件风暴(上):怎样和业务愉快地聊需求?
你好,我是钟敬。
上一讲,我们正式开始了第一个迭代,并简单分析了迭代一的需求。今天,咱们就要根据DDD的基本开发流程,使用事件风暴方法来进一步梳理需求。
你可能会问,上一讲的需求好像已经说得挺清楚了,为什么还要用专门的方法来梳理呢?
其实,在真实项目,尤其是敏捷项目里,领域专家很可能不会像我们上一讲那样,一开始就把需求都一一列出来,需求可能仅仅停留在领域专家的脑子里。所以,我们就需要一种方法,能够将这些头脑中的需求挖掘出来。
而且,即便领域专家已经把需求写出来,我们也很难保证没有遗漏,保证开发人员都彻底理解了。而事件风暴不仅能帮助我们尽量把需求补充完全,而且还能以协作的方式保证业务人员和技术人员对需求理解一致。
此外,事件风暴方法也能够帮助我们识别领域对象,这也是我们进行领域建模前的重要一步。尽管对于建模高手来说,通过“聊天”的方式就能把模型画出来,但对于多数开发团队而言,还是需要一种套路化的方法作为辅助,一步一步地做。
这节课我们从实践入手,让你真正掌握事件风暴的概念和具体操作。
事件风暴是怎么一回事?
那么,事件风暴是怎么来的呢?
一般来说,为了理解需求,我们首先要分析系统具有哪些功能,这些功能由什么人操作,会产生什么效果。这个过程传统上叫做“捕获行为需求”。
捕获行为需求的方法有好几种,在传统的软件工程中,最常用的方法是“用例”,也就是Use Case。但是,Eric Evans在《领域驱动设计》这本书里,并没有规定捕获行为需求的具体方法。直到2013年,一位叫Alberto的DDD专家提出了“事件风暴”,也就是Event Storming。
这种方法简单易学,而且充分体现了DDD中沟通协作、统一语言等要点,所以逐渐开始流行起来。你可以先看看这张图,这里说明了事件风暴的主要过程:
这里的第一步是识别领域事件,在这一步,我们要找到业务流程中发生了哪些事情;第二步是识别命令,进一步说明是什么角色,做了什么操作,导致上述事情的发生;而第三步是识别领域名词,从领域事件和命令中找到名词性概念,为进一步的领域建模打下基础。这里每一步的具体做法和要点,我们后面都会详细介绍。
那么现在,咱们就来想象一下如何在真实的项目中一起做事件风暴。为了保证把细节讲清楚,我们会分为两节课进行,今天的课先聚焦于第一步,识别领域事件。
我再强调一句,由于事件风暴是一个动态的协作过程,不太容易通过文字表达,所以在看后面内容的时候,你一定要充分发挥想象力,让头脑中有“画面感”,脑补出咱们两个人唇枪舌剑,反复讨论的过程。
事件风暴的准备
不过,在正式开始事件风暴之前,我们还要先做一些准备工作。
首先是人员的准备。事件风暴要求业务和技术人员共同协作。业务人员,也就是之前说过的“领域专家”,在实践中一般由业务部门的专家,或者产品经理、PO(Product Owner)、BA(Business Analyst)等角色来担任。技术人员呢,首先要有架构师,其次也可以有技术经理,或者其他的开发人员、测试人员也可以参加。
第二是场地准备。我们需要找一个比较大的会议室,或者至少有一面足够长的墙。
最后是器材准备。我们需要几套彩色的便利贴,到时候我们会把事件风暴的主要内容写在上面。另外,通常还要一卷一开的大白纸,把这些白纸打横,一字排开,贴在会议室的墙上,用来贴便利贴。
事件风暴的第一步:识别领域事件
好,现在还是我来扮演产品经理,你来扮演架构师。而且假设我以前做过事件风暴,而你是第一次,所以我比你知道得多一点。
一开始,我先口头给你讲了一遍需求,你大概听懂了。然后我们就开始事件风暴的第一步:识别领域事件。
所谓领域事件,就是在业务过程中,业务人员要关注的那些已经发生的事儿。比方说,对于电子商务系统,订单已提交、商品已签收等等,都是领域事件。实际上,领域事件表示的是,业务流程中每个步骤引发的结果。事件风暴的作者认为,从结果入手来梳理需求,比从操作入手,更容易把业务想清楚。事件风暴中的“事件”两个字就来源于领域事件。
另外,咱们还要注意领域事件的命名,如果套用英语的语法来说,一般是完成时 + 被动语态。比如说,订单已提交,这个“已”字就是完成时,代表已经发生的事情。而订单已提交也可以说成订单已“被”提交,实际是被动语态,只不过一般把被字给省掉了。
识别“项目管理”流程的领域事件
接下来咱们一个一个业务流程来做。至于具体先做哪个流程,并没有特别的规定。不过由于项目管理这个流程比较长,我们就拿这个流程为例来讲吧。
首先,咱们花十来分钟时间,各自按照自己的理解,把项目管理中发生的各个领域事件,分别写在橙色便利贴上。然后按大致的时间顺序贴在墙上。每人贴一行。写出来以后大概是下面这个样子:
然后,就可以对比咱们两个人写得有什么不一样,再经过讨论得出一致的结果。现在,咱们从左到右看一下。
第一步就发现了一个小区别。你写的是“客户已创建”,我写的是“客户已添加”。
那么你就会问我:“业务人员一般会说客户已创建还是客户已添加呢?”
我告诉你:“一般是说客户已添加,因为从业务的角度,客户本来就是存在的 ,不需要创建,只是把客户资料添加到我们的系统而已”。你表示同意。
然后我又叮嘱了一下:“以后添加客户的时候,都说添加这个词,别再说创建了。”这时候,其实我们已经是在建立“统一语言”了。统一后的结果是下面这个样子:
第二步,你写的是“签订合同”,我写的是“合同已签订”。
一说你马上就反应过来了,刚才我们说过要用完成时和被动语态,“签订合同”是个动作,不是事件。所以达成一致后,结果变成下面这样:
下一步,你写的是“项目已创建”,我写的是“合同已生效”。不过我后面还有一步“立项”,应该和你的“项目已创建”是一回事,所以说明我比你多了一步“合同已生效”。
于是你又问了:“合同签订以后不是马上就生效了吗,还要有一个额外的生效步骤吗?”
我解释说:“合同签订的时候未必马上生效,比如1月1日签了合同,但合同中可以约定,真正生效是在2月1日,所以需要一个单独的步骤让合同生效。”这时候,你知道了一条原来不知道的领域知识。
然后你又问了:“我写了项目已创建,但是你写的是已立项,你这种写法好像和其他的不太一致呀。”
我解释说:“虽然我们为领域事件命名的时候,常常用‘什么什么已什么什么’的形式,不过如果业务上已经有约定俗成的术语,我们就直接使用术语,这样更容易和业务沟通。现在业务觉得已立项是一个通用的术语,写成项目已创建反而显得生硬。”
现在你又知道了,在DDD中的各种命名,一般都优先使用约定俗成的业务术语。统一后的样子如下图:
再来看后面三步,这时我发现自己漏写了“项目已启动”。然后我们再比较了一下“项目已终止”和“项目已结束”两个说法,觉得“项目已结束”更符合业务术语。而“合同已结束”这一步,咱们俩是一样的。
不过我在“项目已结束”前面还多了一个“员工已分配”。
于是你又问我:“刚才你讲需求的时候,好像是把员工分配作为一块单独的需求来讲的,不属于项目管理这个流程吧?”
我想了想,说:“员工分配背后的业务逻辑有点复杂,所以之前单独拿出来讲,其实员工分配是项目运作中的一个重要环节,放在项目管理中也没毛病。”你对此表示认可。
这时我又补充了一点:“员工分配到项目的时候,要填入预计的投入工作量的百分比,一个人可以同时上多个项目,但预计的投入百分比总和不能超过100%。这种逻辑一般叫业务规则,为了避免忘记,咱们也写在便利贴上吧。”
于是我们把业务规则写在浅灰色便利贴上,贴在“员工已分配”事件的下方。经过这几步,结果变成了下面这个样子:
再下一步,你多了一个“客户已终止”。
我解释说:“客户可以在系统中长期存在,以便不断挖掘商机,一般不必专门进行终止。理论上说,万一客户破产了,是应该终止,不过目前业务上还没有这个需求,这一点可以以后再考虑。”于是我们把“客户已终止”拿掉了。
然后你又发现,我的流程中最后还多了一个“客户经理已更换”。
你有点惊讶地问:“可以更换客户经理吗?你刚才好像没说呀。”
我说:“可以更换,我刚才忘记说了。”
你紧跟着追问:“那么负责合同的销售人员,还有项目经理是不是也可以换呢?”
我说:“也可以,我自己都忘了写了。”
于是我们补充了这几个事件。同时,由于这三个领域事件不一定会出现,所以我们决定另起一行,也就是第一行表示主流程,包括必然发生的事件,第二行表示可选的事件。现在统一后,就变成了下面这个样子:
最后,我们把整个流程又仔细检查了一遍。你眼尖,又发现了一个遗漏的领域事件。员工分配到项目上以后,还可以下项目,所以应该有一个“员工已退出”事件。
好补充以后,最终结果就是下面这个样子:
现在,我们终于为项目管理流程,完成了“识别领域事件”这个步骤。
识别其他流程的领域事件
用同样的方法,可以识别其他流程的领域事件,这里就不一一重复了。下面这张图是我们识别出的所有领域事件:
在这张图里,你可以看到,有些业务规则在最开始的需求描述里是没有说明的,而是在咱们不断地讨论中,逐步澄清的。此外,我们还用橘红色的便利贴表示业务流程的名字,以便区分。
关于领域事件,我们还要注意下面这两点。
第一,不要把技术事件当成领域事件。领域事件一定要是领域专家所关注的,用的是业务术语。像数据库事务已回滚、缓存已命中之类的技术术语,不是领域事件,不在这个阶段讨论。
第二,查询功能不算领域事件。领域事件应该是对某样事物产生了影响,并被记录的事情。一般是某个事物的创建、修改和删除。还有一种情况是向其他人或者系统发消息,例如“通知邮件已发送”也算领域事件,因为接收方可能会通过进一步处理来影响某些事物。
而像“客户信息已查询”这些就不算领域事件,因为还没有对事物产生实际影响。不过,这并不代表查询功能不重要,查询功能也要以某种方式体现。这一点在后续的课程我们再讲。
到这里,我们就完成了事件风暴的第一步“识别领域事件”,后面两步“识别命令”和识别“领域名词”将在下一节课讲解。
总结
下面我们来总结一下。这节课,我们首先解释了用事件风暴之类的方法梳理需求的必要性,包括从头脑中挖掘需求、补充遗漏的需求、使业务人员和技术人员理解一致,以及辅助识别领域对象四点。
事件风暴是从识别领域事件开始的。“领域事件”是在业务过程中,业务人员关注的那些已经发生的事情。技术事件和查询功能都不算领域事件。领域事件意味着业务流程中每个步骤的结果。这种结果导向的思维方式更容易理清业务。事件风暴中的“事件”两个字就来源于领域事件。
识别领域事件的过程可以分成了两大步:第一步是参加的人,各自写出领域事件;第二步是一起讨论,统一理解。这种先发散,后收敛,反复迭代的过程实际上就是一种头脑风暴。
头脑风暴是一种常见的协作方式,可以让一群人一起通过思维的碰撞,分析问题,最终达成一致。事件风暴中“风暴”两个字就来源于“头脑风暴”。
在这个过程里,我们已经开始形成统一语言。所谓统一语言,英文是 Ubiquitous Language,是DDD中的一个核心模式。指的是业务人员和开发人员使用的语言要一致。语言是知识的载体。语言一致就意味着背后对领域知识的理解一致。统一语言贯穿了DDD的全过程。
同时,我们也开始识别业务规则。业务规则的处理,也会在后面继续讨论。
我们这节课不厌其烦地讲了识别领域事件的整个过程,是希望你能够体会到在真实的场景中,我们怎么通过不断地讨论,澄清误解、补充遗漏、发现业务规则。
一定要注意,“协作”才是事件风暴的精髓,而具体结果怎样呈现,反而是第二位的。当然,最好的学习方法不是听课,而是实践。所以呢,赶快找几个小伙伴,拿你手头的项目试一试,真正体会一下协作共创的乐趣。
思考题
1.今天识别的领域事件,主要是以“增加”的功能为主,你觉得需要把修改和删除的功能都列出来吗?
2.业务规则用便利贴写出来,时间久了可能不容易维护,你觉得有没有更好的办法呢?
好,今天的课程结束了,有什么问题欢迎在评论区留言。下一节课,我们继续完成事件风暴的另外两个步骤:识别命令和识别领域名词,为领域建模打下基础。
- Jxin 👍(85) 💬(10)
1.上诉场景,有一个非常关键的依赖,你有一个全知全能的PO。很遗憾这个依赖它并不可靠,大部分情况你可能无法在项目初期拥有这么一位PO。所以上诉事件风暴顺利沟通的场景它可能很难成立。 2.那怎么办?如果没有这么一位PO那我们就补位。那么问题就从与关键PO进行领域风暴编程了PO如何快速了解领域知识,沉淀认知概念。 3.那怎么做? A.绘制干系人地图,通过与业务专家/客户项目负责人沟通,把当前参与领域活动所有的角色都定义出来。 B。与参与度最高的角色,一起梳理业务全景(第一次时间会比较长,需要尽量不遗漏),重心在提炼顶层关键业务阶段,和该角色在这个顶层业务阶段下的所有用户旅程(用户旅程要包含 绩效指标 耗时 频率 参与人数 痛点等多维数据)。 C.拿着这个顶层关键业务阶段去和相同角色的其他一线人员碰(这里有框架了,主要在确认认知准确性和挖掘遗漏点)。 D.拿着顶层关键业务阶段去和其他角色重复上诉 B、C两个步骤。刻画全角色的用户旅程,得到业务全景。 E.拿着业务全景去跟领导层沟通,汇报 + 达成共识。这个环节最主要的是识别出战略重心/关键目标。领域知识本身是没有偏向性的,企业的战略才有。做子域划分要定义核心域,这里的核心域定义和选择很大程度取决于领导层提供的战略方向/关键目标。 F.有了业务全景和关键目标,拿着这两件产物和业务专家过事件风暴。这样在事件风暴一开始就有框架和目标,最后事件流的产出,成效会好很多(因为一开始就有了边界和收敛的方向)。 到这里没PO补位PO的玩法就完了。接下来把后续工作步骤也补充下。 G.事件流本身聚焦在"关键写"流程,修改删除查询不会过多刻画。这么做的原因在于,事件流后续产出物是领域建模(我习惯四色建模),重心是识别关键模型、模型角色及模型间关联关系。这个阶段的模型产出是比较粗的粒度。 H.追加业务全景里面的删改查场景,进一步增加模型、丰富模型上的属性、调整模型类型。 I.拆分子领域(这里与建模其实是并行的,提取完业务知识和关键目标就可以做,这是问题空间的事情,而建模是解空间的事情。多数时候它们是交织开展的,虽然概念上做了区分,但现实里它们就是交织在一起的,相辅相成)。基于关键目标,确定阶段核心域。两条个人观点:战略会变核心域也会变;关注点在核心而不是边界。 J.将问题空间与解空间合并。把聚合按业务相关性分类到子域上。结合物理因素/复杂度/组织结构/安全/调用频率等等一系列因素圈限界上下文。
2022-12-10 - 老狗 👍(10) 💬(6)
思考题: 1. 修改删除之类的,有相关的业务才需要列出来,比如合同签订了就只能违约,不能修改和删除,那就只有一个合同已违约,修改和删除甚至创建都一样是技术术语,事件风暴最好用业务术语。技术术语 创建,修改,删除 业务术语 添加(录入) 签订 违约等 2. 个人不觉得事件风暴是一种产出物,事件风暴只能做中间产物,产出物可以用多种方式记录,比如偏业务的用户旅程地图、服务蓝图 偏技术的UML 领域模型(带业务规则),这些图里面相对事件风暴更好记录,如果强行用事件风暴,觉得便利贴不好维护,可以推荐一波 BeeArt https://www.beeart.com/ 在线白板
2022-12-10 - 阿昕 👍(8) 💬(4)
尝试用事件风暴的方式梳理了支付系统的领域事件,放在了共享白板上,欢迎一起来头脑风暴 https://boardmix.cn/app/editor/3ywv0CZURp_x5wm2IDm8pQ?inviteCode=kjG6ak
2023-01-07 - 公众号:业余草 👍(8) 💬(3)
事件风暴是一项团队活动,领域专家与项目团队通过头脑风暴的形式,罗列出领域中所有的领域事件。 企业落地过程中,往往把事件风暴和头脑风暴混为一谈。 领域专家可能并不专业,往往谁的“权利大”谁说了算。 团队活动,参与人不明确,干系人选择性参与会议,比较佛系。 业务建模不关我的事,业务已经很清楚了,怎么做能不能实现是你们的事。 DDD是啥我们并不关心,对我们没有价值,没有DDD我们也做到了上市企业。 。。。 DDD实践是一个工程问题,践行时也是一个过程,在过程中只开一两次对齐会议是解决不了领域建模问题的。如果从利他角度来讲,在这个过程中的不同阶段每个人都可以受益,但不是同时受益,有可能要先解决哪部分人先受益的问题。
2022-12-12 - 奇小易 👍(5) 💬(1)
2w2h笔记 What Q1:什么是事件风暴? 是一种通过协助完成需求梳理的方法。 Q2:除了事件风暴之外,还有什么方法也可以帮助梳理需求? 用例,use case,传统需求梳理方法。 Why: Q1:为什么要使用事件风暴来做需求梳理? 1、业务人员与开发人员之间会通过协助方式来完成,可以使双方对需求的理解达成一致、补充遗漏的需求。 2、辅助识别领域对象。 3、事件风暴是结果导向的思路来梳理需求,更容易把业务想清楚。(DDD大师的经验) How Q1:怎样进行事件风暴? 1、识别领域事件。 2、识别命令。 3、识别领域事件和命令中的名词性概念。(领域模型的基础) 整个过程是一个动态协助的过程。 Q2:怎样进行“识别领域事件”? 1、业务人员和开发人员双方写出自己理解的领域事件。 2、通过沟通、协助来迭代领域事件,明确业务规则,构建统一语言,最终达成一致的理解。 Q3:在识别领域事件中使用的关键概念有哪些? 业务规则、统一语言、必然的事件和可选的事件、业务流程的名称。 Q4:什么是领域事件? 业务过程中业务人员主要关注的业务结果。例如:项目管理过程中,客户已添加。 Q5:什么不是领域事件? 1、技术事件不是领域事件。例如:数据库已插入。领域事件是业务角度的事件。 2、查询功能不能算领域事件。例如:客户信息已查询, How Good DDD常识 1、在DDD中的各种命名,一般优先使用约定俗成的业务术语。
2023-02-02 - 6点无痛早起学习的和尚 👍(3) 💬(2)
2 刷,再来留言,自己在团队实践过这个事件风暴,但不是协作方式,是我自己脑暴,根据产品 prd 来脑暴,然后脑暴一波再去找其他同事+产品 double check,不协作是因为他们不愿意做这个事
2023-04-25 - Michael 👍(3) 💬(1)
有个问题请教老师,我在做事件风暴的时候,如果事件本身很简单,但是业务规则非常复杂,这种情况怎么去揭示复杂的业务规则呢?
2022-12-30 - 靠人品去赢 👍(3) 💬(1)
其实想问一件事,就是有时候产品经理会把需求一些其它“模块的小问题”,弄到一个需求里,有时候感觉他这些小问题甚至比这个主流程需求,更耗时麻烦。像这种应该怎么样处理,尤其是给你安排了一个什么都不会拒绝,又很喜欢压工期的研发经理。
2022-12-22 - escray 👍(3) 💬(2)
对于思考题,以增加功能为主的领域事件,我觉得不需要列举修改和删除功能,一面冲淡了领域事件的聚焦。特别是对于修改和删除操作本身不复杂的领域事件,就更没有必要了;修改和删除所关联到的规则,可以在业务规则中说明。 业务规则可以从文字说明量化为领域事件的属性,或者是一对多、多对多之类的关系,采用代码来表达。
2022-12-19 - leesper 👍(3) 💬(2)
极客时间上的课程中,要数ThoughtWorks的各位老师讲课讲的深入浅出,钟老师,徐昊老师和郑晔老师都很厉害,我从中学到了很多 抓个虫:最后一幅图中有一个灰色便利贴:“只能在项目有小区内才能报工时”,应该是“只能在项目有效期内才能报工时”,编辑同志该打屁股,哈哈 思考题: 1. 如果修改和删除涉及重要的业务流程,我觉得应该列出来,但可以慢慢迭代,不必一次就思考的那么全; 2. 用实体便利贴确实不容易维护,可以建模完成后拍照,或者用一些工具比如draw.io画下来保存在电脑上,建模的时候投屏
2022-12-10 - 铿然 👍(3) 💬(3)
最大的问题在于业务人员会按上述的领域事件跟开发聊么? 他们不会认为加上“已”就是领域事件了,我们是学了DDD,业务人员并没有学,他们还是会用自己的术语。 第一步应该考虑业务人员实际会通过什么来描述需求,怎么描述?要不要教他们DDD,还是说就应用当前业务人员的术语来描述领域事件。 对事件的定义是什么,举个例子,刺客某日刺杀总统算不算一个事件?这个事件并不需要加上“已”才是事件。再举个例子,订单生成后要发送电子发票给客户,通常会说触发发送电子发票事件,这个事件可能尚未发生,但也是一个事件。 所以对于领域事件定义是什么,要素是什么? 加了“已”之后,更像一个结果,一个状态。相比而言“添加客户”比“客户已添加”能更好的表达事件。
2022-12-10 - HeM 👍(2) 💬(1)
我有几个疑惑想问下老师,还请帮忙解惑一下: 1.事件风暴的基于背景是什么,是基于系统流程还是业务流程,也就是说,事件风暴的事件是系统中会产生的事件,还是业务中会产生的事件? 比如说“合同已签订”,我觉得是站在业务的角度来说的,因为不会在系统签订合同,系统只能是录入签订好的合同,站在系统角度来说就是“合同已添加”。 那么同理“客户已添加”是站在系统角度来说的,业务不会说添加了一个客户吧,那么我就感觉“客户已添加”和“合同已签订”所基于的角度不同。 2.客户是什么时候绑定客户经理的,合同是什么时候绑定销售人员的,为什么在事件风暴里没体现出来,只有更换客户经理和更换销售人员
2023-12-07 - 6点无痛早起学习的和尚 👍(2) 💬(1)
因为是第一次学习 DDD,对很多理论知识也缺乏,所以做个小笔记+理解 事件风暴: 是什么? 在开发过程中(“捕获行为需求”):为了理解需求,我们首先要分析系统具有哪些功能,这些功能由什么人操作,会产生什么效果。 传统会用:“用例” DDD用:事件风暴 怎么做? 识别领域事件: ● 找到业务流程中发生了哪些事情; ○ 这里就需要一定的业务领域知识,这个业务流程里需要做哪些事 ○ 比如:海外支付,有些就是预授权+确定支付,而不是一步做了确认支付流程 ● 业务流程中每个步骤引发的结果,关注结果 ● 命名标准:完成时+被动语态,eg:订单已提交 ○ 优先使用约定俗成的通用业务术语,eg:已立项代替项目已创建 ● 误区: a. 不要把技术事件(事务回滚)当做领域事件 b. 查询功能不算领域事件,是指这个事件对某个事物有了影响(事件创建、修改、删除) 识别命令: 进一步说明是什么角色,做了什么操作,导致上述事情的发生; 识别领域名词: 从领域事件和命令中找到名词性概念,为进一步的领域建模打下基础。 回答课后思考: 1. 需要列,如果业务有诉求就需要列,列全,也便于后面做其他分析需要 2. 换个地方,在线协作等工具
2022-12-17 - 传说 👍(2) 💬(1)
纸上得来终觉浅,绝知此事要躬行。
2022-12-11 - 铿然 👍(2) 💬(2)
补充一点,“客户添加”和“客户创建”差别并不大,业务上不会说“客户添加”,而是“发展新客户”更合适些,发展了新客户才会到系统里添加客户,“添加”贴近系统操作,例如在excel里增加新客户信息。
2022-12-10