领域驱动设计中的事件风暴:从概念到实践
领域驱动设计中的事件风暴:从概念到实践
事件风暴(Event Storming)是一种集体头脑风暴的方法,旨在发现和理解系统中的关键业务事件。这种方法由Alberto Brandolini在2013年提出,旨在让所有相关人员(包括开发者、领域专家、业务分析师等)通过可视化的方式,快速、直观地捕捉领域知识。
什么是事件风暴?
事件风暴(Event Storming)是一种集体头脑风暴的方法,旨在发现和理解系统中的关键业务事件。这种方法由Alberto Brandolini在2013年提出,旨在让所有相关人员(包括开发者、领域专家、业务分析师等)通过可视化的方式,快速、直观地捕捉领域知识。
事件风暴的核心理念是通过"事件"来驱动讨论和设计。事件是指系统中发生的具有业务意义的活动,用过去时来描述。例如,“订单已创建”、“付款已完成”。事件风暴不仅可以帮助我们理解当前系统的业务流程,还可以发现潜在的问题和改进点。
事件风暴的过程和方法
事件风暴的过程可以分为以下几个步骤:
- 准备阶段:
- 准备大块的白板或墙面
- 各种颜色的便利贴和马克笔
- 收集各个领域专家和相关人员
定义事件: 让所有参与者将自己认为的重要事件写在便利贴上,并按照时间顺序贴在白板上。事件是系统中发生的重要动作或变化,用过去时来描述(比如“订单已创建”,“付款已完成”)。
排列事件: 将所有事件按照时间顺序排列开来,并不断调整,直到大家对整个流程有一致的理解。这一步有助于建立一个完整的业务流程视图。
加入命令和聚合: 深入一步,加入驱动事件的命令(角色行为或系统操作)和聚合(业务实体和它们的行为逻辑)。这一步帮助我们从更高层次理解系统的业务逻辑。
命令的命名规则:
- 命令通常以祈使句的形式书写,表示即将发生的动作或用户的意图。例如,“创建订单”、“支付停车费”、“识别车牌号”。
- 识别边界上下文: 根据事件、命令和聚合之间的关系,我们进一步划分边界上下文(Bounded Context),这是DDD中非常重要的概念,定义了系统的不同模块或子系统的边界。
通过事件风暴来实现领域驱动设计
事件风暴的成果可以直接应用到领域驱动设计的实现中,具体过程如下:
获取领域知识: 通过参与者的集体智慧,我们可以快速了解领域知识,建立一个共同语言(Ubiquitous Language),这有助于避免误解和沟通障碍。
发现聚合和实体: 在事件风暴中,命令和事件帮助我们发现系统中的核心聚合和实体,这些是我们设计领域模型的基础构建块。
划分边界上下文: 根据事件和命令,我们可以识别系统中不同的功能区域,并划分边界上下文,确保每个上下文内的高内聚和上下文之间的低耦合。
设计领域模型: 利用事件风暴的可视化成果,我们可以设计出符合业务需求的领域模型,包括实体、值对象、聚合、仓储等等。
驱动代码实现: 最终,我们可以根据设计好的领域模型,进行代码实现,确保代码与业务需求一一对应,增强系统的可维护性和扩展性。
举个例子:停车场管理系统
假设我们要设计一个多租户的停车场管理系统,我们可以通过事件风暴来进行领域驱动设计。具体步骤如下:
准备阶段: 我们邀请停车场运营商、软件开发团队、支付系统供应商等相关人员参与事件风暴会。
定义事件: 大家开始写下各自领域的重要事件,比如“车辆进入停车场”、“停车费已支付”、“车辆离开停车场”等。
排列事件: 根据时间顺序将这些事件排列在白板上,形成初步的业务流程图。
加入命令和聚合: 例如,在“车辆进入停车场”事件之前,我们可以加入“识别车牌号”的命令;在“停车费已支付”事件之前,可以加入“支付停车费”的命令。我们还可以标注出“车辆”、“停车费交易”等聚合。
命令命名规则和举例: 命令以祈使句形式书写,确保易于理解和直观。例如:
- “识别车牌号”:一个命令,用于识别进入的车辆。
- “支付停车费”:一个命令,驱动用户付款。
- “创建停车记录”:记录车辆进入停车场的情况。
- 识别边界上下文: 根据事件和命令之间的关系,我们可以划分出不同的边界上下文,比如“停车管理上下文”、“支付上下文”、“车辆识别上下文”等。
添加事件风暴建模模式
事件风暴建模模式用于描述事件、决策/策略、命令、聚合和外部系统的顺序处理:
事件 -> 命令 -> 聚合: 在一个典型的处理流程中,当某个事件(比如“车辆进入停车场”)发生时,它会触发一个命令(比如“记录进入”)。这个命令会作用于某个聚合(比如“停车记录聚合”),更新聚合的状态。
[事件] 车辆进入停车场 -> [命令] 记录进入 -> [聚合] 停车记录聚合
事件 -> 决策/策略 -> 命令 -> 聚合: 有些情况下,事件的发生需要业务决策或者策略来决定接下来的动作。例如,当“停车费计算”事件发生时,需根据不同的策略(比如不同的费率)来生成相应的命令,最终作用于聚合。
[事件] 停车费计算 -> [决策/策略] 选择费率策略 -> [命令] 计算费用 -> [聚合] 费用记录聚合
命令 -> 外部系统 -> 事件: 某些命令的执行需要调用外部系统的接口,例如“处理在线支付”命令。当支付成功时,外部系统会返回一个事件(比如“支付已完成”)。
[命令] 处理在线支付 -> [外部系统] 支付网关 -> [事件] 支付已完成
事件 -> 命令 -> 多个聚合: 有时候,一个事件触发的命令会作用于多个聚合。例如,当“停车费已支付”事件发生时,可能需要更新“车辆状态聚合”以及“支付记录聚合”。
[事件] 停车费已支付 -> [命令] 更新状态 -> [聚合] 车辆状态聚合 -> [命令] 更新支付记录 -> [聚合] 支付记录记录聚合
总结
事件风暴不仅使我们能更高效地获取领域知识,还能帮助我们设计出符合业务需求的领域模型,并最终实现高质量的软件系统。通过借助事件风暴建模模式,我们能更清晰地理解和设计事件、命令、聚合和外部系统之间的关系。希望通过今天的介绍,大家能对领域驱动设计和事件风暴有更深入的了解。