领域驱动模型设计与微服务架构落地-从项目去剖析领域驱动
- 领域驱动模型设计与微服务架构落地-从项目去剖析领域驱动
- 事件风暴(Event Storiming)
- 事件风暴目的
- 什么是事件风暴
- 事件风暴的优点
- 事件风暴应用场景
- 事件风暴准备
- 场地设置
- 海报纸
- 邀请正确的人来参与
- 事件分类颜色
- 实施步骤
- 设计流程
- 架构技术填充
- 六个问题
- 1.为什么我们使用
- 2.方法与目标
- 3.不必纠结于局部
- 4.业务粒度的粗细
- 5.领域与数据
- 6.抽象与灵活
- 六个步骤
- 2.1流程梳理
- 2.2四色建模法
- 2.3划分领域
- 2.4 领域事件
- 2.5项目构建
- 2.6详细的设计
领域驱动模型设计与微服务架构落地-从项目去剖析领域驱动
事件风暴(Event Storiming)
Alberto Brandolini
事件风暴目的
统一语言的素材,包含对商业流程的共同理解,包含名词使用、责任范围、使用者体验等。
—份整体流程的概览图(Big Picture)
可以找出商业流程中的核心价值、风险与机会。
导入DDD的好起点
什么是事件风暴
- 探索功能
- 找出盲点
- 建立共识
事件风暴的优点
- 快速
事件风暴方法减少了创建全面的业务域模型所需的时间。过去需要数周的时间,一次研讨会可以在几个小时内完成。
- 简单明确
事件风暴不使用复杂的UML,而是将过程分解为技术和非技术利益相关者都可以理解的简单术语。不需要有过多准备,直接识别利益相关者就可以开始。
- 参与
事件风暴的目标之一是使建模变得有趣。这是一种动手的领域建模方法,可邀请每个人参与和交互。除了使参与者更加愉快之外,事件参与者还可以使参与者获得更多有价值的见解,因为参与者可以更轻松地参与该过程并提供他们的建议和专业知识。
- 有效
事件风暴不是数据建模,但通过大家讨论可以快速实施和验证的行为模型。同时为了获得最佳结果,团队应将事件风暴与面向领域驱动设计的实施相结合。
事件风暴应用场景
Big Picture(概览图)
理清混沌商业系统,凸显出合作关系、边界、责任归属与不同利益相关者的观点。邀请任何有兴趣的人、不用限制讨论范围。
找出瓶颈、核心价值甚至是新的解决方案
主要以Event.、 System、Question为主。
适合新创或小团队(人少、技术债少)
Process Modelling(流程模型)
讨论特定功能流程,以确保大家理解没有明显分歧,最后达到理解的一致性。
有明确范围,所以路径越完整越好。
在细节中找出流程的Bug,并且每个Bug都需要被处理。
包含Event、Actor、Command、 System、Policy、 Read Modelo
Software Design(软件开发)
利用前面的产出进一步设计软件
加入Aggregate(聚合)、 BoundedContext(限界上下文)建立模型边界。
用词更加精准
事件风暴准备
提前准备:人事时地物
场地设置
- 找到一面限制最少的表面来进行活动。不管是墙面、窗边甚至用多面移动白板组成都可以。你无法预测最后的产出有多少,所以尽你所能,不要因为空间而限制活动的品质。
- 在表面上贴上大型画纸卷方便收纳产出以及进行另一场Event Storming
- 以最大化活动空间。将现场的杂物移开,不过可以留下一张小桌子放道具。
- 一定要将椅子移走。经验中,只要有人坐下,就会开始沉默,最后自我放逐。。(建议)一面白板或海报写上名词定义清单。这场会议中的对话都要遵照清单上的用词。
- 提供几张有图示标明(Legend)的海报纸。
海报纸
邀请正确的人来参与
传统的建模过程通常需要一名或几名研发人员来一起进行类设计、接口设计,通讯协议和数据映射等。而事件风暴则可能是较大的不同团队的成员来一起构建领域模型。
谁是合适的人?根据Brandolini的说法,他们是知道提出正确问题和拥有答案的人。该小组可能是代表用户体验,业务,架构,开发,运维和营销等利益相关者的混合体。
主持人/Facilitator:
建议一定要有一名参与者负责主持会议进行、推动议程讨论。要严格注意时间与流程。最好不要跟Domain Expert重复。
领域专家(们)Domain expert(s):
专案的主要推动者,或是拥有足够领域知识的人,建议最好有一定的决定权,在陷入泥沼时才可以做出决定。如果是新创领域,可以事先做好使用者访谈或是找使用者来参加。可以不只一名。
其他利益相关者Other Stackholder:
可能是参与专案的工程师、设计师,也可能任何能提供专业意见的人士如业务、商业分析师甚至是主管。
事件分类颜色
•橘色(正方形 76*76):Event 事件
•蓝色(正方形):Command 命令
•紫色(长方形): Policy/Process 商业政策/流程
•黄色(小张长方形):Actor 角色
•黄色(长方形):Aggregate 聚合
•粉红色(长方形):System 外部系统
•红色(正方形):Hotspot 热点
•红色(小张长方形):Problem 疑问
•绿色(小张长方形):Opportunity 机会
•绿色(正方形):Read Model 资料读取模型
•白色(大张正方形):Uset Interface 使用者介面
实施步骤
从事件开始
主持人会先请领域专家简介专案需求,然后由领域专家(或是主持人)在画面正中央贴上第一张Event。贴在中间一方面可以灵活拓展,另一方面也能让所有人一起参与。
1.橘色便利贴。
2.使用过去式(根据Alberto Brandolini本人的叙述,使用过去式代表着系统的状态)如订单已成立、货物已送出、早餐已买到等等。
3.领域专家所在乎的事件。
如整合第三方物流时,领域专家可能只在乎送达时间而不在乎中间细节的运输过程。
4.有时间性,请从左到右排列。同时加上时间概念。
如「凌晨三点帐款已对帐完成」、「午夜十二点马车已变成南瓜」,甚至是某个时间点,如「本季度已结束」
「已过了一个月」。
5.可以加上原因。
如「因为密码输入错误三次,所以帐号已被锁住」。
比如商城的订单模块 用户下单事件
状态 主流程
待支付 待审核 待发货 。。。。
提出问题:
比如(主持人此时重要功能是将大家讨论全部针对事情上来)主持人鼓励随时打断、不要放过任何模棱两可,比如:
- 我不懂
- 商业逻辑和自己理解不同
- 与现有的处理逻辑不同
- 用户体验差
热点问题(HotSpot)
如果过程中某个节点卡住太久,很有可能是因为领域专家也不太了解这个问题,也有可能是目前资料量不足以做出决定。先贴上一张45度角旋转后的红色的Hotspot待日后解决。
Command
·事件的触发器
·蓝色便签条。
·事件是对过去已发生的陈述,命令表达了对将来发生某些事情的意图。·命令可以是执行也可以是拒绝执行。
例如,如果在订单系统中,库存不足,触发拒绝订单事件
Command的主体可以是用户(Actor)、后台管理也可以是系统触发。
Read Model
一些读取的信息
System
一般由Command或者由第三方回调(支付完成)所触发。System在上一流程完成后,再产生新的Event。
比如用户支付完成,系统生成「卖家发货」、「物接揽收」、「开始分拣」、「运输中」、「商品已到指定取货点」等。
Policy
系统对于特定Event如何回应,Policy就像Event Storming 的侦探一样,可以找出许多尚未发掘的问题或是现有流程矛盾之处。
围绕Aggregate对事件和命令进行分组。
每个Aggregate代表一个特定的业务概念,该概念具有具体的业务功能。
同时在时间表上标记了这些组。刚标好的组,标记聚合可能把时间顺序打乱。
Aggregate想成是一个State Machine(有限状态机),一个Model会有很多的状态,因此一种Aggregate可能会对应到多组Command与Event。
最终聚合定义的模型再结合DDD
如何设计一个电商项目
DDD可以将业务分析与技术进行分离。
我们在进行领域驱动设计时,需要考虑战略设计以及战术设计。包括架构选型。
设计流程
- 战略设计通过限界上下文从全局的角度规划整个系统的业务模块
- 逐步细化,对每个模块开展事件风暴会议进行领域建模
- 逐步落实到每个模块的数据库设计与微服务设计以及需要涉及的分布式技术与云端部署
我们就以我们的一体化商城平台项目为例,我们的一体化商城项目是一套集物流,仓储,电商为一体的智慧电商平台。同时,服务于广大的中小型商家。商家可以在平台进行申请开店。平台提供对应的第三方物流,仓储以及一系列交易保证功能。
一体化商城系统
- 移动用户端 + PC端电商网站 技术专家 + 技术经理
- PC端商家后台 + 移动端商家后台 技术专家 + 技术经理
- PC端后台管理 技术专家 + 技术经理
- 大数据管理后台 技术专家 + 技术经理
支撑子域
得到多个聚合 APP下单
用例模型 领域模型 建模
架构技术填充
六个问题
1.为什么我们使用
DDD的方法论的核心将我们的问题不断的分解,将大问题分解成为小问题,将大的业务范围分解成小的领域,简单的说就是分而治之,各个击破。
分而治之,我们可能直接会面对大业务,我们无从下手。我们就需要分解,雏形:多少业务功能-每个功能–接口
分解成为高内聚的小领域,可以让我们的业务有边界。但是领域是实际的边界。这就是领域驱动设计的核心。
各个击破,是指的我们的问题被划分成为小领域之后,因为小领域业务内聚,所以说子域的相关度高,同时我们在设计的时候可以对他进行详细设计。并且我们在管理的维度我们也可以对项目进行分工。所以我们的DDD的战略设计是不能替代详细设计的,DDD的本质是为了更加清晰的进行详细设计。
现在微服务是特别流行的,当我们的业务逻辑越发复杂的时候,实际上也可以靠我们的DDD来解决我们的业务逻辑复杂的问题。
2.方法与目标
首先,我们需要明确一点,我们去使用DDD是干什么事,就是将我们的业务划分为边界清晰的模块。DDD只是其中的方法之一,DDD在这里是方法,不是目标。比如你的业务模型很简单,很容易分析的项目就不需要DDD,短平快,你也不需要。
3.不必纠结于局部
由于项目过于庞大,导致我们整个项目可以无限极的划分,比如我划分了领域,子域,子子域,限界上下文的划分,本质上不就是子域。
我认为大家不必纠结,这取决于你当前功能的重要性,如果你当前的功能是核心模块,那么这个时候你的划分需要尽可能详细一些,其他的一些子域,划分可以不用那么详细。你认为的局部,在别人看来是整体。高内聚,将与核心业务高度关联的功能,优先收敛。
4.业务粒度的粗细
关于微服务的粒度划分至今是没有粗细的详细标准的。根据业务需要,开发资源,技术实力综合考虑。拆分微服务过细会导致开发难度增加,部署难度增大,维护难度增加,但是迭代成本减少。
建议大家核心领域单独划分模块,非核心可以选择性聚合
5.领域与数据
领域对象与数据对象,区别:值对象的存储方式
足球运动员指标
6.抽象与灵活
抽象的核心是找相同的,对不同事物的相同的地方提取公因式,变相的体现了灵活性。
六个步骤
2.1流程梳理
梳理的视角是什么?
如果对于业务不熟悉,那么我们应该怎么做?
2.2四色建模法
1.时标对象:1.事实的不可变性 2.责任的可追溯性
2.参与方,地,物
3.角色对象
4.描述对象
2.3划分领域
2.4 领域事件
当业务系统发生了一件事情,这个事情会影响到其他子域的后续动作,那么这个时候我们将这个事情称之为领域事件。
事件订阅的交互,需要注意一个问题,在软件当中,事件模式只能用到最终一致性,需要放弃强一致性,所以,领域事件的产生会引入技术复杂度的权衡。
2.5项目构建
参见架构代码结构对照表
2.6详细的设计
领域已经确定了,根据领域划分任务,用例图,活动图,时序图,数据库设计,接口设计规范。