一周技术思考(第24期)-如何评判一个架构的成熟度

2021-08-20 10:28:28 浏览数 (1)

大家好,这里记录,我每周读到的技术书籍、专栏、文章以及遇到的工作上的技术经历的思考,不见得都对,但开始思考总是好的。

1、理论基础

“在越强大的基础架构支撑下,应用程序开发需要关注的问题就越收敛,我们的开发效率就越高“

对于开始的这句话,我们可以列举下面两个个例子来对比理解。

先举一个Spring框架的例子。

Spring是一个Java的开发框架,假如在没有Spring的情况下,为了提高编程的效率,我们必须要自己在工程代码里面实现控制反转、依赖注入,也就是我们需要将这些控制性的操作从代码中抽象出来。

当使用了Spring之后,类似这样的操作我们就不需要关心了,统统交给框架来处理,我们就可以专心的做业务逻辑处理。甚至有一种说法,“Spring框架可以让不太懂面向对象编程的研发人员也能开发出服务OO设计思想的工程代码”,这句话其实也是有一定道理的。

再举一个网络分层的例子。

无论是TCP/IP网络分层的四层模型,还是OSI网络分层的七层模型,最上面的一层都是应用层。在应用层有我们熟悉的Telnet、SSH、FTP、SMTP、HTTP等各种协议,而对于大多数Web研发人员来讲接触最多和应用最多的也是这层。

但实际上应用层能够运转起来完全是建立链接层、传输层等这样的底层协议上,除非你是要搞底层的网络协议栈“基建”,不然你都可以只在应用层上“潇洒”的写你的程序。我们之所以有这样的“福利”,实际上是依赖了一套成熟的网络分层架构。

在所举的这样两个例子中,我们提到的“框架”都属于架构设计的范畴

在日常研发过程中,我们自己设计的系统架构,也是类似的道理,一个成熟的架构可以解放研发人员的生产力,正如开头的那句话中所述的能够收敛关注的问题和提高研发效率。既然架构那么的重要,我们想看看自己设计的架构到底什么水平,换种说法也就是要判断我们自己的架构的成熟度,我们应该从哪几个方面着手呢。

我们要尝试给出一个架构设计的成熟度模型,那么我们首先要让这个模型符合一定的理论基础,也就是“要讲理”

在讨论如何设定一个架构的成熟度之前,让我们先从这张图看起,这张图是袁英杰老师发布在infoq网站上的一篇文章中的,我个人也是很认可这种逻辑,本文的一些观点也是参考了这篇文章。

我们现在要做一件事,就是如何来评估一个架构设计的【成熟度】,那么架构设计又显然属于软件设计的范畴,如果要看一个软件设计是否成熟,那么我们就要弄清楚我们设计的目的是什么,最后有没有达到我们的目的,这样我们便有了评判依据。

要回答上述这个目的的问题,先让我们回到我们的“初心”。

不可否认,我们如今大多数时候做的软件设计,其实是就是在进行面向对象的设计,那面向对象设计的“初心”是什么,就是如何实现高内聚和低耦合

从上面那张图你会看到为了要达到这样高内聚和低耦合的目标,我们进而有了正交四原则、在之上又有我们熟悉的SOLID原则(S-单一职责原则、O-开放封闭原则、L-里氏替换原则、I-接口隔离原则、D-依赖倒置原则),最后还有我们的设计模式(常见的23种设计模式),这几层下来都是为了达到高内聚低耦合,而这几层也正是要实现高内聚低耦合的方法。

注:正交四原则分别为,消除重复、分离不同的变化方向、缩小依赖范围、向着稳定的方向依赖,从目前已知的资料显示正交四原则为袁英杰老师提出。

好了,我们知道了设计的目的是为了高内聚低耦合,那高内聚、低耦合的本质又是什么。

架构设计一直绕不开两个问题,一个是如何”分“,软件的模块应该如何划分才是合理的;另外一个是如何”合“,划分好的模块间API该如何定义才是合理的,也就是我们一直在分合中做“斗争”。

我们说的高内聚,其实就是在阐述怎么分的,比如我们使用单一职责,通过对变化原因的识别,将一个承担多重职责的类,划分成更小的、只具备单一变化原因的几个类,这是”分“的动作,但同时通过职责的单一化实现了高内聚,因为我们把紧密关联的事物放在了一起。

我们说的低耦合,就是在阐述怎么合的,比如我们使用依赖倒置原则,由上层来定义接口,而不是由实现方根据自己的方式来定义接口,保证了依赖关系的稳定性,这是”合“的动作,但同时通过面向抽象编程实现了低耦合,因为上层和下层不再相互依赖,而都是依赖抽象。

我们在上图中表露出的那些原则、模式都是在”努力地帮着“如何实现高内聚低耦合的”分合“。比如单一职责开放封闭,更多的在强调类划分时的高内聚;而里氏替换依赖倒置接口隔离则更多的强调类与类之间协作接口(即 API)定义的低耦合

2、成熟度模型

那我们设计的架构呢,一个常见的Web应用架构大致是分为三层,最上层是前端,中间有BFF层,最下层是我们的服务层。

从宏观上,它将我们的研发系统在横向上分成了三层,又将这三层通过接口协议在纵向上合在了一起,将业务数据按照颗粒度组件的目标提供给前端层使用,从而将沉淀的业务组件能力与前台用户需求的变化进行快速的匹配。

从中观上,在这三层中最下面的服务层是业务领域能力的核心,借助DDD的设计思想和,我们有应用服务、领域服务、基础服务等符合DDD分层风格的代码工程结构,这是“分”;我们有应用服务、领域服务、基础服务各层之间的调用依赖,这是“合”。

从微观上,我们在领域服务中,将能够反映现实业务实现的对象设计为实体,将不变的相关特征属性组合设计成值对象,这是“分”;在使用时我们又可以在实体中去引用值对象,这是“合”。同时实体和值对象都只是个体化的对象,它们所表现出来的行为也仅仅是个体的能力,要完成一个业务场景的功能我们把业务和逻辑紧密关联的实体和值对象组合成了聚合,这也是“合”。

因此我们常见的Web应用架构显然也是在分合之中,按照先前的理论基础所有的“分合”在最终都是为了一个中心目标:高内聚低耦合。

可见,我们常接触的Web应用架构显然也是在分合之中,按照先前的理论基础所有的“分合”在最终都是为了一个中心目标:高内聚低耦合。

基于此,在提出如何来评判架构成熟度的时候,也就有了我们的依据标准,我们提出了如下架构成熟度的模型,而这些模型因子都是在围绕分合中发挥着作用。

这张图是LEDGE网站上的ADMM所描述的架构成熟度的一个演化版本,我个人认为下面的这个图所涵盖的考核面更符合当前我们研发的实际场景。

这里归纳下来,包含三个方面,怎么分,怎么合以及共性设计(这里面没有绝对的归类,只是说某角度更强调更侧重哪个方面)。

接下来我列举出一些实际的模型因子,关于这9个考察点下面更详细的内容考核项,实际上我可以自己结合所在企业的实际环境来定义,这里仅仅是给出常用的定义。

怎么分:

分层架构设计

|有无依据业务/领域划分包结构、有无依据核心-扩展划分包结构

组件化设计

|有无支持多端业务、有无配置能力

微服务设计

|有无持续交付策略、有无小构建设计

怎么合:

API设计

|有无异常和错误的处理、有无容错的处理、有无向后兼容的处理

依赖耦合度设计

|有无三方集成防腐设计、有无循环依赖

领域设计

|有无领域服务、核心实体有无充血设计、有无统一业务语言和技术语言

共性设计:

代码可读性设计

|有无重复代码、有无测试用例、有无SOLID原则应用、有无控制和业务隔离设计

文档化设计

|有无系统架构设计文档、有无核心域代码设计文档

演进策略设计

|有无技术债、有无技术债管理策略

3、执行策略

成熟度模型有了后,我们具体应该如何执行呢,是定性还是定量呢,我们采用定性的过程,定量的结果。

总体执行“有无”原则,每一项5分制,有则加5分,无不加分也不减分。前期可以将上面考核项打印出表格的形式,在试点业务条线采用【自评 "教练"】组合的形式,这里的“教练”我们称为技术教练,一般由架构师担任。

注:这里的“有无”原则,也要注意反例,比如有无技术债,当然是无加分,还有有无循环依赖,也是无加分,等。

4、总结

一三九模型:一个目的(高内聚低耦合)、三个方面(分、合、共性)、九个考察点(模型的9条边)。我们之所以要为我们的架构设计做度量,是想找出架构设计中待改进的部分,是想增加将来架构实施过程中的可预测性,减少架构实施的风险。

我们这里给出的9个考察点是一个参照,我认为一个架构有9个考察点应该是足够了,大家可以将它看做一个模型,也可以根据自己所在单位的实际情况来更换考察点的内容,进而制定出符合自己团队的架构设计考核模型出来。

恭喜你,又完成一次思考。

0 人点赞