10分钟带你快速且深入了解:DDD-领域驱动设计

背景:

传统项目中的代码架构都是MVC架构,视图层 --> 控制层 --> 模型层,但mvc只是一种思想,是一种抽象,在不同人看来会有不同的指向,对于Java后台开发来说,MVC架构具体指的就是Controller层、Service层、Mapper层了。

我们整天进行CRUD来实现业务需求,其实做的事情不过就是:将数据库中的数据转换为前台需要的数据格式。如何在需求评审时证明产品设计的合理性呢?只要可以根据产品设计可以对应地设计出合理的表结构就证明了:需求合理。所以传统开发中只有一种视角:数据视角,更准确些就是:关系型数据库的数据视角。然后,整个开发过程不过就是把设计好的数据视角里的数据转换为前端页面要的数据格式。

但缺少了另一种视角:业务视角。业务所需要地数据都是通过各方数据拼凑起来地,而且是临时拼凑起来地,之所以说是临时拼凑是因为:逻辑不能复用。

简而言之:

DDD是什么?领域驱动设计。什么是领域?领域是业务相关知识的集合。领域是和业务有关系的,不仅仅是和业务有关系,所谓的领域就是通过业务划分出来的。举个简单的例子:一个商城系统,其内的领域可以划分为:商品、购物车、订单、积分等。订单这个领域又可以细分为:订单、支付、发货单、收货单等。领域不是数据库里面的表,不需要遵循什么数据库范式,领域只关心业务,领域由业务产生、由业务划分而来。所谓领域驱动设计,就是从业务的视角出发来进行代码架构、微服务架构!

代码架构视角:

代码架构层面不再是Controller、Service、Mapper三层了,而变成了四层:“接入层”(Controller)、“应用层”(ApplicationService、QueryService)、“领域层”(Repository等)、“基础设施层”(Mapper,RedisTemplate等)。而它们之间的依赖关系如下图所示(上层依赖于下层):

10分钟带你快速且深入了解:DDD-领域驱动设计_第1张图片

接入层:

也叫用户界面层,其实就是Controller层。负责系统的输入和输出,不关心业务,也不关心参数校验,只关心沟通协议。拿web场景的HTTP应用来举例,如果使用的是SpringBoot,那么@RestController标注的类前面会有很多的过滤器、拦截器等,可以对HTTP协议进行处理,最终把有用的数据拿出来并转换为@RequestMapping方法的入参。

应用层:

组织业务场景,编排业务,隔离场景对领域层的差异。关注点在业务场景处理。例如,对于一个服务多种类型用户的应用,to C 的网页界面和后台管理界面对应的是不同的业务场景。对于新用户注册这个业务来说,通过 to C 的网页注册和通过后台管理界面进行后台注册是不同的业务场景。然而,“用户注册”在系统层面的基本逻辑是一样的。所以,“用户注册”的基本业务逻辑可以交由领域层来实现。而两种不同渠道进行用户注册所需要进行的身份验证等逻辑,可以设计在应用层进行实现。这样便能达到关注点分离,复用核心业务逻辑的目的。

领域层:

实现具体的业务逻辑、规则,为应用层提供无差别的服务能力。例如,对于用户注册的场景,用户既可以通过邮箱自己注册,也可以由管理员在后台进行添加。用户注册的核心逻辑可以由领域层完成,但是对于不同渠道进行用户注册的参数校验和权限验证等逻辑则由应用层实现

基础设施层:

提供具体的技术实现,比如存储,基础设施对业务保持透明。对于基础设施层来说,基础设施层并不是指 MySQL、Redis 等外部组件,而是外部组件的适配器,Hibernate、Mybatis、Redis Template 等,因此在 DDD 中适配器模式被多次提到,基础设施层往往不能单独存在,还是要依附于领域层。基础设施层的适配器主要包括:存储、通知、第三方系统等外部设施(防腐层隔离)

业务视角:

还可以用另外一个视角来审视一下所谓的“领域驱动设计”:

10分钟带你快速且深入了解:DDD-领域驱动设计_第2张图片

 这个视角就不是代码架构的视角了,而是业务视角。其实图里面是把和业务紧密关联的领域模型放在了最中心的位置,也就是说领域模型是业务最核心的东西;而领域模型外层是应用程序,对应于应用层,用来布局业务场景,应用层不是业务核心,但要布置业务场景肯定和业务是相关的;再往外走,一圈都是适配器,适配器分别对应了界外的各种中间件,举个例子:Mybatis就是其中一个适配器,其对应的中间件是Mysql。

这个图就是在说:软件开发的核心目的在于实现业务,业务的核心在于领域模型,领域模型要登台唱戏需要应用层来搭台布局,而最外层的各种中间件离业务最远,要使用这些中间件还需要再程序中引入对应的适配器。

具体概念:

10分钟带你快速且深入了解:DDD-领域驱动设计_第3张图片

上图把领域驱动设计里面所有的概念名词全部都串了一遍,看这个图可能会有些懵,我来解释下:

所谓领域驱动设计,就是将已知的“问题空间”划分为“领域”来进行问题解决(图上深绿色部分)

问题空间”:待解决的业务问题集合。

领域”:业务相关知识的集合。打个比方,在一个线上采购系统中,可以划分的领域大体上包括:订单、商品、库存、积分等等。但领域绝不是数据库里面的一张表,领域不必去遵循数据库设计范式,划分领域的唯一约束在于:业务,面向业务来划分领域!

那怎样来划分呢?把相关人等召集在一起通过“事件风暴”,遵循特定的“原则”,进行“软件设计”,包括如何进行领域划分的“战略设计”,以及如何创建具体的“领域模型”的战术设计(图上浅绿色部分)

事件风暴”:把业务专家、技术专家召集在一起,大家讨论所有可能的场景、所有可能发生的事件,把业务吃透的一个过程。

战略设计”:对业务进行高层次的抽象和归类,关注点在于领域的分离,其解决的问题是把大的领域划分为小的领域以及相互之间如何关联。战略设计的产出为:界限上下文、领域(在单体中可能为为一个包或一个模块,在微服务中可能是某个微服务,总之,领域是一个抽象概念)。

战术设计”:对特定上下文中的领域模型进行详细设计,设计的对象包括:聚合、实体、值对象。

其中核心中的核心其实就是如何进行领域的划分,不同的“领域”之间被“界限上下文”所隔离开,在某个特定的领域之内的“领域模型”可以包括这几种:“实体”、“值对象”、“聚合”、“聚合根”(图中黄色部分)

实体”:领域模型的一种,具有唯一标识,比如ID

值对象”:领域模型的一种,通过值判断唯一性

聚合”:聚合是一组生命周期强一致,修改规则强关联的实体和值对象的集合,表达统一的业务意义

聚合根”:聚合根( Aggregate Root)是聚合中最核心的实体,其他的实体和值对象都从属于这个实体

领域之内不仅仅包括实体类,还主要包括这几种类:“仓储”、“服务”、“工厂”、“策略”、“规格”来对领域模型进行操作。(图中红色部分)

仓储”:仓储的目的在于屏蔽业务逻辑和持久化基础设施的差异

服务”:领域模型的操作者,负责领域内的业务规则的实现

工厂”:以构建领域模型(实体或值对象)为职责的类或方法

策略”:业务规则的实现方式

规格”:一些特殊的业务规则。通常表现为用于校验(e.g. 数据格式,业务逻辑)、查询和搜索条件

在领域驱动设计的项目中,代码架构大体上分为四层:“接入层”、“应用层”、“领域层”、“基础设施层”(图中红色部分)

具体概念讲解:DDD 概念参考

具体项目落地:xtoon-cloud-ddd: 基于DDD(领域驱动设计)并支持SaaS平台的微服务框架https://gitee.com/xtoon/xtoon-cloud?_from=gitee_search

你可能感兴趣的:(微服务,ddd,领域驱动设计)