共计 3717 个字符,预计需要花费 10 分钟才能阅读完成。
简介: 什么是畛域驱动设计?传统分层架构在理论开发中存在哪些问题?业务开发人员如何设计并搭建本人的畛域模型?阿里娱乐技术专家战獒将为大家一一解答,并分享娱乐在畛域驱动设计上的实际。
一 什么是畛域驱动设计
畛域驱动设计的概念是 2004 年 Evic Evans 在他的著述《Domain-Driven Design : Tackling Complexity in the Heart of Software》(中文译名:畛域驱动设计:软件外围复杂性应答之道)中提出的,从畛域驱动设计提出距今曾经有 15 年的工夫,为什么最近才开始在中国的互联网圈大行其道?仿佛一夜之间大家都在议论,那么畛域驱动设计到底帮咱们解决了什么问题?带着这些疑难,一起来看下阿里巴巴娱乐是如何实际畛域驱动设计的。
二 畛域驱动设计大行其道的必然起因
软件系统素来都不是凭空而来,而是以软件的模式解决特定的问题。当咱们面临事实世界的简单问题时,如何以软件的模式落地?畛域驱动设计是一套方法论,领导咱们将简单问题进行拆分、拆分出各个子系统间的关联以及是如何运行的,帮忙咱们解决大型的简单零碎在落地中遇到的问题。
Evic Evans 在著述中将软件系统的设计分为 2 个局部:策略设计和战术设计。在策略设计层面提出了域、子域、限界上下文等重要概念;在战术设计层面提出了实体、值对象、畛域服务、畛域事件、聚合、工厂、资源库等重要概念。如图 1 所示:
策略设计局部领导咱们如何拆分一个简单的零碎,战术局部领导咱们对于拆分进去的单个子系统如何进行落地,在落地过程中应该遵循哪些准则。
以大家熟知的电子商务系统举例,晚期的电商零碎因为业务绝对简略,用户量和团队规模也较小,一个单体利用就能够搞定,随着容量回升能够将单体利用进行横向扩容,比方晚期的淘宝就是这样做的。拆分过程中咱们能够把电商零碎这个单体利用拆分成订单子系统、库存子系统、物流子系统、搜寻举荐子系统等等,如图 2 所示:
畛域驱动设计在策略层面上的域、子域、限界上下文的划分思维和微服务的划分不约而同。域对应一个问题空间,也就是上例中的电商零碎;子域是把域这个大的问题空间拆分成若干个小的更容易解决的问题空间,也就是单体利用向微服务演进过程中划分进去的各个子系统;限界上下文是解决方案空间,每个子域对应一个或多个解决方案空间。微服务的划分是也是将一个大的问题拆分成若干个小的问题,每一个小的问题用一个或多个微服务来解决。
对于大多数开发同学来说都没有机会接触零碎的划分,这些工作个别是公司的技术领导层与架构师来做的,一般的开发同学日常工作中接触到的只是某一个具体微服务或微服务中某一个模块的落地,那是不是说畛域驱动设计对于一般开发同学来说就没有用了?当然不是这样,畛域驱动设计中的战术设计局部就是领导咱们如何落地一个零碎才能够使零碎具备高可扩展性、高可读性。
所有的零碎最终都要以代码的模式落地,而落地的工作都是由一般的开发同学来做的,零碎是否具备高可扩展性、高可读性间接影响了整个团队的效率。
三 传统分层架构存在的问题
对于大多数开发同学来说,大部分工夫都花在落地一个个微服务上,上面咱们来看阿里娱乐是如何联合畛域驱动设计的思维将微服务进行战术落地的。
目前笔者接触过的微服务大多数都是分层架构并且在 Service 层与 Manager 层实现具体的业务逻辑,应用 DO、DTO、BO、VO 等进行数据传输,数据和行为根本齐全隔离。这种分层结构图 3 是《Java 开发手册》中的规范分层构造。
该标准中定义了各层的职责,其中最重要的两层 Service 层和 Manager 层是这样标准的(以下两层解释摘抄自《Java 开发手册》):
Service 层
绝对具体的业务逻辑服务层。
Manager 层
通用业务解决层,它有如下特色:
- 对第三方平台封装的层,预处理返回后果及转化异样信息。
- 对 Service 层通用能力的下沉,如缓存计划、中间件通用解决。
- 与 DAO 层交互,对多个 DAO 的组合复用。
阿里娱乐晚期的我的项目分层也根本都采纳这种架构模式。下面的分层并没有问题,然而这种分层架构采纳的是包的模式进行的层与层的隔离,须要每一位开发同学了解并且自觉遵守以上标准,然而在理论工作中咱们发现很多同学对 Service 层和 Manager 层的区别并不是特地的分明,即便分明的同学大部分也并没有齐全恪守手册中的标准,这种景象导致 Manager 层除了沉底一些通用能力以外和 Service 层并没有什么本质区别。
在理论的业务代码中 Service 层和 Manager 层都充斥了大量的第三方依赖,对系统的稳定性有很大的影响。每依赖一个第三方服务都要各种异样问题,这些异样解决的代码往往会和业务代码混在一起,当这种代码多了当前会使代码的可读性十分差。
阿里娱乐业务的复杂度晋升很快,业务迭代速度也很快,Service 层和 Manager 层代码量迅速收缩,业务逻辑变得越来越简单。在这种业务场景下,大娱乐引入了畛域驱动设计并设计了一套残缺的畛域驱动模型评估与演进的解决方案来辅助开发同学将畛域驱动设计的思维真正的落地。
四 娱乐畛域驱动设计实际
畛域驱动设计的关键在于辨认业务的模型,而模型又是会随着业务的倒退而演进的,对于新的业务来说能效平台提供了业务模型剖析的性能,开发同学能够在能效平台设计并搭建本人的畛域模型,搭建进去后能效平台能够评估畛域模型设计的是否正当,如果模型设计正当则能够基于以上设计的模型合乎畛域模型标准的代码。对于已有利用,能效平台设计了一套畛域注解并以 SDK 的模式提供进来:
- 第一步:开发同学依照畛域设计的准则对业务代码进行剖析并打上注解。
- 第二步:能效平台可主动扫描该我的项目并收集该我的项目中的畛域模型。
- 第三步:模型收集后,开发同学能够在能效平台改良业务模型并从新依照畛域模型的标准生成代码。
残缺流程如下图所示:
1 模型采集
对于已有的筹备重构的利用,咱们设计了一套畛域模型的注解,开发同学能够将注解加到对应的类、属性、办法上。当零碎是按数据模型落地而不是按畛域模型的形式落地时,能够先找到零碎的数据模型,而后在能效平台对数据模型进行组织生成畛域模型。
2 模型搭建
对于新利用或者曾经进行完模型采集的利用,开发同学能够在能效平台进行模型的搭建和批改,如图 6 所示。
3 衰弱度评估
对于曾经搭建完的模型能效平台,依据畛域驱动设计的标准创立了一套残缺的校验规定,模型搭建实现在生成脚手架之前会依据校验规定进行打分,当打分通过时能够将模型生成脚手架。
4 脚手架生成
当模型搭建结束并且校验通过后能够将模型生成脚手架,其代码构造是依照六边形架构的规范生成的,六边形架构也成为端口与适配器架构,该架构的思维是将外部外围的畛域逻辑与外界依赖进行隔离,这里的依赖是指所有对其余微服务的依赖、http 的依赖、数据库依赖、缓存依赖、消息中间件依赖等等,所有的这些依赖都通过适配器进行转换成利用可了解可辨认的最小化信息。
在理论的我的项目中,每种依赖都要思考各种异常情况并进行解决,而这些解决实际上并不数据畛域逻辑,却耦合到了业务代码里,当这种依赖多了对系统的稳定性会产生很大的影响,传统的分层架构尽管也会让咱们将本身的畛域逻辑和依赖进行拆散,在阿里巴巴标准手册中提到所有的依赖都应该放到 Manager 层,然而这种标准是非常容易被突破的。六边形架构从利用分层上让咱们更容易去恪守这样的标准。
依据六边形架构的指导思想,在理论的利用分层中个别划分为四层,别离是:
- 用户接口层:负责用户展示相干的逻辑。
- 应用层:负责对一个用例进行流程编排(将接口用例分成若干个步骤,然而不负责每步的具体实施)。
- 畛域层:负责实现外围的畛域逻辑即业务逻辑(负责实现具体的业务逻辑)。
- 基础设施层:所有依赖的具体实现。
然而从利用架构的角度看,层级组织模式能够分为两种:
传统分层架构
如图 9 左侧,这种分层架构是 Evic Evans 在《Domain-Driven Design : Tackling Complexity in the Heart of Software》中提出的,其中用户接口层、应用层、畛域层可间接依赖基础设施层,与图 3 的传统架构并无本质区别,因为所有层都间接依赖了基础设施层。这种形式须要强制开发同学将所有的依赖进行下沉,随着工夫的推移这种标准非常容易被突破。
依赖倒置的分层架构
如图 9 右侧,这种分层架构是依赖倒置的分层架构,特点是:
- 根底设计层可间接依赖其余三层,反之则不行。
- 用户接口层、应用层、畛域层如果要应用基础设施层中的能力,只能通过 IOC 的形式进行依赖注入,这也听从了面向对象编程中的依赖倒置准则。
当开发同学要在以上三层中间接援用第三方依赖时,是找不到具体的类信息的,也就是不能 import。同时这种形式对单元测试的标准也能够起到很大的作用,当咱们编写单元测试时能够为畛域层注入一个测试运行时的依赖,这样利用运行单元测试能够不依赖上游服务,在代码层面上也更加标准。
五 总结
经典的三层或多层架构尽管是目前最广泛的架构,然而在隔离方面做得并不够好。在业务架构选型时要联合本身业务特点,而不能千篇一律的抉择某一种业务架构,适合的业务架构能够缩短我的项目的生命周期,升高我的项目的重构频率,最终达到升高人力老本的目标。