领域驱动设计(DDD)详解:微服务拆分神器

@TOC

一、领域驱动设计概念

1、基本概念

(1)通用语言

领域驱动设计,作为一个技术、产品、用户通用的语言进行沟通,极大地降低了沟通成本与沟通失真问题。

(2)领域设计4层模型

(3)DDD适合的场景

DDD既不是UI导向(SMART UI)、也不是数据导向(UML),而是以产品为导向,并不是用户所使用的产品,而是整个产品的业务逻辑。 适合中大型项目、API经济、中台化,可以借鉴DDD进行对微服务进行拆分。

2、领域、子域、界限上下文

领域(Domain):具备一个完整的,在一个市场里面赚钱的能力。比如说二手车市场、电商领域、宠物托管平台。

领域可以进一步划分为子领域。我们把划分出来的多个子领域称为子域,每个子域对应一个更小的问题域或更小的业务范围。 子域(SubDomain):比如支付子域、商品子域、用户认证子域。

界限上下文(Context):所谓上下文,就是为了解决子域的问题的。比如支付上下文,认证上下文。

子域提出问题空间,界限上下文提供解决空间。

3、核心子域、支撑子域、通用子域

核心域:核心域就是一个领域的核心。 比如说电商平台有哪些核心域:产品信息核心域、支付交易核心域、物流域,自然也就对应着产品信息上下文、支付上下文、物流上下文。

支撑子域:支撑核心域正常工作的子域。比如用户行为分析域、风控域,自然也有对应的界限上下文。

通用子域:一些业内通用的子域,比如用户认证系统,可以通过购买第三方的平台来实现。

4、界限上下文的关系

界限上下文的内容,就代表着对应的子域的功能。

界限上下文的上游(U-upstream)提供服务,下游(D-downstream)接收服务。

Conformist:跟随者关系。一定要跟某个上游系统绑定,但别人是主,本系统是从。

ACL(Anticorruption Layer):Open Host Service(RPC、消息队列等)/Published Language(xml、json等) ,反腐层。集成遗留系统,又不能强制老系统更新,新系统要做个适配器层来转换模型。

partnership:更紧密的合作伙伴关系。

Shared Kernel:共享内核。两服务之间紧密合作,代码模型可以提取成通用组件共享。

Separate Ways:分离模式。两个微服务没有任何联系。

Customer Supplier Teams(客户供应者模式):强依赖,上下游系统开发合作顺利,对模型逻辑修改反应迅速。常见于消息队列的两端。

Single Bounded Context(合并上下文模式):单个界限上下文,两服务如一家人,紧密到无法分开。一切模式要素都是共享的。

5、领域模型的要素 - 实体、值对象、聚合

(1)实体

(比如说一个学生) 唯一标识(用户提供、应用生成UUID/GUID、持久化生成)。 数据可变。 生命周期管理。(订单状态管理) 实体的唯一标识是实体与实体,聚合与聚合之间的纽带。

(2)值对象(Value Object)

(比如说一个学生中的某个属性,居住地、性别、性格等等) 无标识。(不唯一) 数据不可变,可复制,可替代。 整体性。(比如:¥100 - 两个概念一个整体,山东省济南市 - 两个概念一个整体) 通常用来做实体的度量和描述。

(3)聚合(Aggregate)

(比如一个班级,有学生、书) 事务一致性边界。(各种动作的数据一致性、行为一致性,比如说所有学生一起上课、下课) 聚合之间通过聚合根(通常为聚合同名实体)进行沟通。 尽量缩小聚合(通常使用最终一致性和领域消息)。(缩小聚合事务复杂度就缩小了) 聚合是创建、发布领域事件和操作资源库的操作主体。

(4)案例分析

6、构建领域模型 - 工厂、库、领域服务

(1)工厂(Factory)

用于创建聚合和实体,可以用工厂类、工厂方法模式、创建者模式来实现。 实现了对象的解耦。 封装复杂操作过程。

(2)资源库(Repository)

实现对聚合的增删改查。 对接持久化机制(如Hibernate)。 和DAO、Mapper类似,但更侧重集合的处理。 封装复杂操作过程。

(3)领域服务(Domain Service)

无状态。 无法归为实体和值对象。 业务操作过程,对领域对象进行转换。 如:密码加密服务、文字转换服务、应收账款和应付账款对账。

7、反腐层

反腐层(Anti-corruption layer,简称 ACL)介于新应用和旧应用之间,用于确保新应用的设计不受老应用的限制。是一种在不同应用间转换的机制。

创建一个反腐层,以根据客户端自己的域模型为客户提供功能。该层通过其现有接口与另一个系统进行通信,几乎不需要对其进行任何修改。因此,反腐层隔离不仅是为了保护你的系统免受异常代码的侵害,还在于分离不同的域并确保它们在将来保持分离。

反腐层是将一个域映射到另一个域,这样使用第二个域的服务就不必被第一个域的概念"破坏"。

二、领域建模方法论

1、企业架构法

2、面向服务设计法(SOA)

3、用例分析法

4、四色建模法

红色:时标型(Moment-Interval)对象。 绿色:PPT(Party/Place/Thing)对象。 黄色:角色(Role)对象。 蓝色:描述(Description)对象。

5、初识Event Storming事件风暴

演进式架构和迭代式开发。 微服务拆分和向前兼容。 如何和产品业务人员沟通。 有没有一个可以在喝茶聊天中完成微服务拆分的方法?

6、领域模型的选择 - 贫血、充血模型

所谓的血,就是业务逻辑。

贫血:getter+setter方法,每个领域并没有太多业务逻辑,更多的业务逻辑在更上层。 充血:更符合领域驱动设计,应用逻辑为主、数据管理为辅。get、set方法是私有的,对外暴露的是更加丰富的有血有肉的方法动作。

贫血模型和充血模型各有优势: 贫血模型:上手快、发展受限,适合应用逻辑简单、信息记录类型的业务。 充血模型:上限高、适合三高项目,适合逻辑复杂、信息处理类型的业务。

7、洋葱圈模型

三、领域事件

1、初识领域事件Domain Event

异步通信,符合事件驱动风格。 通常用消息队列(MQ),可以实现削峰填谷。 但是要处理消息丢失、消息重复的问题。

2、领域事件,代码实例

(1)生产者发布事件

(2)消费者订阅事件

(3)EventStore做事件存储

(4)定时任务轮询投递事件

3、领域事件与CQRS

(1)什么是CQRS

CQRS:Command Query Responsibility Separation。(写和读的责任分离) Command:执行动作,返回void。(行动可能会改变聚合、实体、值对象的内容) Query:只查询,不修改对象状态。

适用CQRS的风格:事件驱动系统风格、管道过滤器风格。

(2)CQRS和ES事件溯源

普通CQRS:做数据的增删改查,对于数据无法溯源。

事件溯源:数据只做增和查,可以做到事件溯源。

四、案例:敏捷项目管理系统

1、功能分析

项目管理系统,涉及项目发布、代办、状态、任务等等。

2、子域划分

3、定义实体、值对象、聚合

(1)聚合根

领域驱动设计中,对外提供功能的只有聚合根的功能,聚合根里面的实体尽量只对聚合根提供服务。 聚合根的子对象,尽量都用实体对象封装。

(2)值对象

值对象不提供独有的ID,全部通过快速复制快速创建,永不修改来实现这些值对象的描述性的信息。

(3)实体

把子对象用实体的形式进行封装,成员变量private,set和get方法private,让它们更加生动的操作protected,让其他成员来访问。,聚合根里面的实体尽量只对聚合根提供服务。

(4)聚合

把聚合根、值对象、实体打包起来,就形成了聚合。

4、落地工厂、库、领域服务

(1)工厂

(2)资源库

(3)领域服务

5、落地反腐层

(1)完整图示

(2)领域服务

(3)适配器:进行适配+调用上有服务

6、应用服务

应用服务的方法与工厂、资源库之间的关联:

7、建模的核心要素 - 隐性的概念显性化

隐性的概念显性化:多种不同的逻辑封装到一起,按情况进行处理。

隐形的上下文显性化。

封装多对象行为。

8、规则选择 - 策略模式

9、规则拼装 - 组合模式

10、事件风暴 - Event Storming

(1)事件Event

事件即事实,即在业务领域中那些已经发生的事件就是事实,并可能需要保存下来或者让"别人"响应。

事件是对系统产生了业务上的影响的动作,相对的,如果仅仅是数据查询操作,则只会对系统产生技术上的影响,如CPU上升或者内存上升等。

注意:一般查询操作都不会触发事件的产生,所以查询操作不是事件,如点击了查询按钮显示了数据列表,一般情况下不会有类似于:数据已查询或列表已查询,这样的事件。

事件使用正方形橘黄色的便利贴表示,并且是过去式,如:用户已注册(User Registered),激活邮件已发送(ActivationEmail Sended)等。

(2)痛点/问题/关键点(IDEAS, RISKS)

关键点用红颜色的贴纸表示。

表示不确定的点、有风险的点或者需要特别注意的点,一般贴在事件旁边,代表这件事情值得特别关注。

(3)命令Command

决策命令产生了事件,可理解为产生事件的动作,与事件一一对应。如用户已注册(User Registered)事件对应的决策命令就是注册用户(Register User)。

决策命令用正方形蓝色便利贴表示,在实践中只需要将事件"反过来"就行了。

(4)聚合Aggregate

某个Actor在某个聚合调用某种Command产生了某个Event。

比如前面的用户已注册(User Registered)事件,是由普通用户(Normal User)在注册薄(Register)上调用注册用户(Register User)这个命令而产生。

聚合使用紫色即时贴表示。

(5)外部系统External System

Event不一定由前面所说的某个Actor触发Command而产生,也可能是由外部系统或者某种规则自动触发Command而产生。

外部系统使用绿色即时贴表示。

(6)第一阶段成果

(7)构建微服务间关联关系

(8)形成类图

(9)事件风暴核心思想

由下而上,更快:平时我们拆分都是从上层架构师进行总的模块拆分,再分到每一个模块里面。事件风暴从一个个事件开始,从下往上的考虑,出手更快。

事件驱动,更新:事件风暴是由事件驱动的,非常容易更新,当整个架构定下来以后,一旦用户体验有所变化,只需要改变对应的聚合。

团队破冰,更嗨:面前贴一张白纸,通过这种沟通,团队之间心平气和的把服务拆分的非常完美。

10、DDD模型下的代码分层模型

DDD实践_如何使用DDD设计代码模型

五、案例:电商场景领域模型设计

1、子域

核心子域:买家、支付、履约、卖家、市场、用户、风控、客服、搜索、财务、产品、定价、认证、内部、推荐、社交、合作、库存。

通用和支撑子域:数据平台、数据科学、负载管理、内容管理、消息通告、安全加固、基础架构、应用平台、质量保证、集成发布、遥测监控、合规审计。

2、上下文

认证上下文:注册认证、用户登录、访客登录、内部登录、身份验证、令牌管理。

用户上下文:用户联系、用户服务、用户设备、用户喜好、用户背调、用户支付、用户行为、用户设置、用户订单、用户发布、用户折扣、会籍管理。

市场上下文:折扣策略、优惠券、促销管理、用户粘性、SEO、SEM。

搜索上下文:公共搜索、个人搜索、信息编目。

客服上下文:语音客服、机器人、客户关系。

买家支付上下文:支付方式、支付网关、支付交易、保险。

卖家支付上下文:支付方式、支付网关、支付交易、税务。

履约上下文:卖家履约、买家验收、物流。

风控上下文:风控模型、支付风险、账户风险、交易风险。

推荐上下文:个性推荐、趋势推荐、广告推荐。

定价上下文:价格限制、价格推荐、费用计算。

买家上下文:下单、订单、购物车、跨境交易。

卖家上下文:发布管理、一手平台、二手平台、订单。

财务上下文:子账、收入、利润、税收、对账、应收应付。

参考资料

zhuanlan.zhihu.com/p/399103071 blog.csdn.net/wanghaiping...

相关推荐
红尘散仙2 小时前
我把终端小说阅读器接上了 AI Agent:TRNovel 现在能用 skill 生成书源了
人工智能·后端·rust
卷毛的技术笔记3 小时前
告别硬编码!Spring AI Alibaba 实现 AI Agent 智能工具调用(Tool Calling)
java·人工智能·后端·python·spring·ai编程
会编程的土豆3 小时前
Go 语言反射(Reflection)详解
开发语言·后端·golang
喵个咪4 小时前
GoWind Toolkit Go后端代码生成 完整全流程实战
后端·go·orm
basketball6164 小时前
Go 语言从入门到进阶:4. 数组和MAP使用方法总结
开发语言·后端·golang
qq_2518364574 小时前
SpringBoot+Vue 共享电池柜管理系统 完整实现 前后端分离项目实战 完整代码
vue.js·spring boot·后端
zhangxingchao5 小时前
AI 大模型核心六:量化、Workflow 与 Agent、多轮 RAG
前端·人工智能·后端
IT_陈寒6 小时前
Vite打包时遇到的坑,原来问题出在这里
前端·人工智能·后端
ayqy贾杰7 小时前
基层管理的三板斧,在AI时代行不通了
前端·后端·团队管理
Apifox7 小时前
Apifox 5 月更新|Postman 导入优化、Runner 支持非 root 运行、请求代码自动带鉴权
前端·后端·安全