总篇138篇 2022年第13篇
★ 目录 ★
01 | 项目背景 |
02 | 技术选项 2.1传统三层架构 2.2DDD四层架构 |
03 | 构建领域模型 3.1准备事件风暴 3.2分析福利中心功能 3.3构建福利中心领域模型 |
04 | 总结 |
05 | 参考资料 |
01
项目背景
使用DDD领域驱动设计的思想对福利中心(用于同事之间互赞互动)进行开发,在自己的业务中落地微服务。
02
技术选型
2.1 传统三层架构
在微服务盛行的今天,我们用得最多的还是传统的三层架构,即事务脚本开发方式,使用这种开发方式,对象只是用于在各层之间传输数据,只有数据字段和Get/Set方法,在对象中没有逻辑方法,这种对象就是“贫血模型”。
三层架构具体分为:表示层(UI);业务逻辑层(BLL);数据访问层(DAL)三层架构。
第一步根据需求做数据库设计,数据表如何建,表之间的关系如何设计。
第二步就是根据数据库设计搭建数据访问层,选择一个ORM框架生成数据库访问代码或者拼接SQL操作。
第三步就是根据需求实现业务逻辑,在业务逻辑层调用数据访问层对设计的表进行增删改查。
第四步表示层主要面向用户的输出。
传统的架构代码分层主要包括:Controller层、Service层、Dao层、Model层(贫血模型)。
缺点:
贫血模型,是面向数据库开发的模式,是基于数据表的设计,通过数据驱动,所有的开发都是围绕数据表来进行。贫血模型其实是违背了oop模式,oop模式要求对象有自己的属性和方法,而传统开发中很明显看不到方法,没有业务行为,只有get/set方法供外部获取属性值。
业务过度耦合,随着项目迭代的不断演化,业务各个方法互相调用,方法散落在各个模块中,模块彼此关联,业务逻辑越来越复杂,代码也越来越冗杂,上下文越来越模糊,层次越来越不清晰。
技术和业务耦合,业务需要什么技术就引入什么技术,如果想把业务脱离出来,去更换某种技术就很困难,很难适应新技术。
无法对齐业务,开发人员和业务人员交流语言不统一,开发用技术语言和业务沟通,而业务人员不了解技术。
优点:
这种贫血模型的传统开发方式也是当前最常用的方法,开发效率高、速度快,层次结构简单、开发框架容易被掌握。
2.2 DDD四层架构
针对上述传统开发和贫血模式存在的问题,我们对福利中心项目的落地实施,使用了DDD领域模型的四层架构模式:
1)适配层(Adapter):约定负责对用户的访问或任务调度中心的请求进行路由和适配,可按不同场景提供不一样的用户接口实现。面向Web的可使用http restful的方式提供服务,可增加安全认证、权限校验,日志记录等功能;
2)应用层(Application):约定负责获取输入,组装上下文,进行参数校验,调用领域层做业务处理,如果需要的话,发送消息通知等。层次是开放的,应用层也可以绕过领域层,直接访问基础实施层;应用层是领域层的上层,依赖领域层,是各聚合的协调和编排,原则上是不包括任何业务逻辑。
3)领域层(Domain):约定封装核心业务逻辑,并通过领域服务(Domain Service)和领域对象(Domain Entity)的方法对App层提供业务实体和业务逻辑实现。领域是应用的核心,不依赖任何其他任何层次;
4)基础实施层(Infrastructure):约定负责技术细节问题的处理,比如数据库的CRUD、外部API、文件存储、RPC调用等。此外,领域防腐的重任也落在这里,外部依赖需要通过gateway的转义处理,才能被上面的App层和Domain层使用。
03
构建领域模型
使用事件风暴构建福利中心的领域模型。事件风暴是一个协作活动,将领域专家、产品经理、开发团队等聚集在一起,通过头脑风暴(激烈讨论、散发思维)的形式,尽可能多的罗列出领域中发生的领域事件,然后讲这些事件整合成最终的领域事件集合,并针对每一个事件,找出引发该事件的命令,再为每一个事件找到命令发起方的角色,目的是试图捕获系统发生的整个业务流程。
然后使用贴纸以一个粗略的形式将可能会发生事件贴在空白的墙上(白版),尽管还没有考虑它们是怎么发生的或是什么结构支撑其发生的。
3.1 准备事件风暴
1)事件风暴参与者:
事件风暴采用工作坊的方式,将领域专家、产品经理、开发团队等聚集在一起,通过频繁互动、激烈讨论的方式逐步将领域模型设计出来。
领域专家就是非常熟悉业务系统的需求和设计,并对业务和需求有着深刻的见解,对问题能够进行深入的剖析。
除了领域专家,事件风暴的其他参与者主要包括:DDD 专家、架构师、产品经理、项目经理、开发人员和测试人员等项目团队成员。
2)事件风暴要准备的材料:
参与事件风暴的成员可以将自己的想法和意见写在贴纸上,然后将贴纸贴在墙上(或者白版)的合适位置(可以按照业务模块先划分好区域)。所以我们需要贴纸、笔、胶带、磁扣,需要多种颜色的贴纸来区分命令、实体、事件等行为对象,因为贴纸可能要更换位置,所以要多准备一些胶带或者磁扣。
3)事件风暴场地:
需要容纳足够参会人的会议室,需要一堵足够长的墙(白版)。墙(白版)是用来贴纸的,会议室可以让人互动,方便合作。
4)事件风暴分析的关注点:
在整个领域建模的过程当中,参会人需要重点关注业务的实体、动作和行为。是谁(实体)产生的动作(命令),触发了这个动作或行为(事件)是否会引发下一个业务动作,这个动作(事件)的输入项和输出项又是什么…我们可以在这些复杂的业务流或词汇当中,分析出领域模型中的事件、命令、实体、上下文等领域对象。
3.2 分析福利中心功能
福利中心主要的目的是用于同事之间互赞互动,使用家家币或者家家赞换购家家内购里的商品。之家福利项目多,成本投入较高,但缺少统一平台展示,员工感知度低,体验不好,所以人力牵头,合并hr、行政福利项目,打造福利门户;同时引入家家币概念,取代万里通积分;增加家家赞概念,用于同事之间感谢。
1)功能分析:
福利中心主要包括:福利发放、发放规则、赠送家家赞、个人信息等。
2)场景分析:
场景分析就是我们需要从业务角度出发,根据用户交互或者业务流程,采用用例分析的方式,画出流程图,确定业务的基本流程和走向,之后分析出主要的场景,然后通过场景分析,在场景中找出领域事件、实体和命令等领域对象来进行领域建模,并划分好上下文。事件风暴参与者要尽可能地多的梳理出业务细节,尽量不要遗漏业务关键点,要多讨论,多发表见解。
福利中心有这样三个典型的业务场景:
第一个是发放设置,设置系统中家家赞和家家币发放权限和遵循哪些规则发放;
第二个是规则配置,为用户建立发放规则,可以设置手动、也可设置自动定时任务,发放范围扫描等;
第三个是家家赞赠送,用于同事之间互赞互助。
我们可以按照业务的工作流程,通过场景分析,逐步的找到用户在业务流程中的关键领域事件,比如发放已创建,规则已创建等事件。再找出哪些行为会触发这些领域事件,这些行为可能是一个命令或多个命令共同产生的,比如创建发放时,第一个命令是查找发放规则,第二个命令是上传发放员工信息,上传完员工信息后,对员工信息进行确认后就可以创建发放的领域事件了,同时这个领域事件会触发下一步的操作,比如消息通知,可以通过邮件、钉钉、公众号、OA系统等将家家赞已发放的消息通知给员工,但也有可能业务到此结束,不需要下一步的操作,需要根据自己的业务、具体情况来分析是否还有下一步的操作。
3.3 构建福利中心领域模型
领域建模时,参与人要根据场景分析过程中产生的命令和事件,分析出它们之间的触发关系,找到发出命令的实体,梳理实体之间的依赖关系,根据依赖关系组成聚合,找出聚合根,划分限界上下文,然后再根据领域模型与领域模型之间的依赖关系、确定领域之间的通信机制。
总之,领域模型是通过划分限界上下文来确定微服务的系统边界,通过聚合领域对象来找到聚合根、实体和值对象,具体可以分为这样三步:
1)提取实体:从命令和事件中,反向推理出产生这些行为的实体。
2)找出聚合根:根据聚合根的管理性质以及实体之间的依赖关系,从六个实体中找出聚合根。
3)划分限界上下文:根据上下文语义将聚合归类,确定好业务边界。
04
总结
本篇主要是通过事件风暴的方式找到福利中心的实体、值对象、聚合、聚合根、聚合服务、聚合事件、限界上下文等。
实体:实体采用充血模型,在实体类内除了字段和Get/Set方法外,还应该实现实体的全部业务逻辑方法,在微服务架构中设计领域模型的实体时,实体主要包含属性、值对象和业务方法,一般情况下业务实体的属性与数据表字段是一一对应的,但是实体的某些属性有时候也可能被设计成值对象,而且实体都有自己独立的方法和业务行为,比如用户实体有新增和修改用户的方法,组织机构实体有新增和修改部门信息的方法。
值对象:通常用于描述业务实体,是一个没有唯一标识,不能单独存在,且不可变化的对象。比如馈赠人信息,我们只需要知道{“userName”:“张三”,”userCode”:“123456”}这样的值对象就能够满足基本要求,不需要唯一标识符。
聚合:将多个有依赖关系的实体和值对象组合到一起就是聚合,比如家家赞实体、馈赠人值对象、赠送人值对象就代表一个完整的家家赞概念,而且聚合中的所有对象的生命周期都是相同的,并且能够统一持久化到数据库中。聚合是一组相关的对象,通过定义对象与对象之间的依赖关系和确定边界上下文来实现领域模型的内聚,形成了井然有序、一目了然的对象关系网。
聚合根:将聚合中能够表达总概念的那个实体做成聚合根,在聚合中可代表整个业务操作的实体对象,通过它提供对外访问和操作的方法,使用它维护聚合内部的数据一致性,它是聚合中对象的管理者,是这个聚合的根节点,具有全局唯一标识。
领域事件:采用事件驱动的方式来解耦服务与服务之间的依赖关系,通过设计事件实体对象、事件的发布和订阅机制和事件的处理机制来判断是否需要引入事件总线或消息中间件,服务之内可以采用事件总线、服务之间可以采用消息中间件。
限界上下文:划清业务边界,即不同的业务模块有着不同的上下文,且能独立调用,且各自的业务模块可以有自己独立的数据库,互不干扰。一个业务模块想和另一个业务模块沟通,则需要通过消息队列或事件总线机制进行通信。
本篇主要是介绍了如果通过事件风暴的方式构建领域模型,而使用DDD设计福利中心微服务代码模型,在本文中没有提及,将在后续的文章中论述,敬请期待。鉴于作者经验有限,我们对领域驱动的理解难免会有不足之处,欢迎大家共同探讨,共同提高。
05
参考资料
https://www.cnblogs.com/songgj/p/9296057.html
https://zhuanlan.zhihu.com/p/382202178
https://github.com/alibaba/COLA/
作者简介
OA基础平台组
OA基础平台组主要负责OA框架的开发、OA基础组件的开发、OA相关业务系统的开发、代码规范的指定、脚手架的推广
阅读更多
▼ 关注「之家技术」,获取更多技术干货 ▼