软件架构治理 之 如何度量软件架构

为什么要度量软件架构

不管是架构治理,还是团队管理,通过有效地度量都能找到问题并加以改进,指标也能反映改进后的效果。

指标是很神奇的,它就像是系统中的一个开关,如果你关注它,就像打开一个开关,整个系统可能会有一些奇怪的反应。找到合适的指标让系统达到自己预期的效果,非常难。然而,这并不意味着我们要放弃通过指标度量的手段来解决问题。

很多人会用医生诊病来比喻软件架构健康度优化,我也曾在 《如何提升系统可用性》 用名医扁鹊三兄弟的故事来说明提前关注系统健康度的重要性。软件系统的运行可能远不及人体那么复杂,但随着系统规模的增大,系统的运行会变得非常复杂,远超出一个人所能认知的范围,在这种情况下,软件系统和人体都可以看做是非常复杂的系统,一些“诊断”和“医治”的手段和方法大概是相通的。

医学发展到今天,很多已经流程化,患者到医院说出疾病表现,医生就知道该做哪些检查,通过各种维度的“指标”数据来判断真实的病因。有些关键指标能够直接帮助医生确诊疾病,比如针对新冠肺炎的核酸检测。

如果你无法度量它,你就无法管理它。 —— 彼得·德鲁克

软件系统的维护者就是医生,指标度量的重要性不言而喻,一方面可以通过度量找到系统架构的问题,另一方面也可以通过度量,来指导改进并观察改进效果。

从哪些维度度量软件架构

Mamdouh Alenezi在论文《Software Architecture Quality Measurement Stability and Understandability》中整理了一些论文中提到的软件架构衡量标准和颗粒度定义,参见下表:

图片来源于Mamdouh Alenezi的论文《Software Architecture Quality Measurement Stability and Understandability》Table I

图中给出的颗粒度包括包/类/方法,组件/库,架构三大类,我在之前的文章 《架构优化方向》 中,将架构优化分为四个大的方向:代码实现、组件设计、架构设计和基础设施,在上面论文颗粒度的基础上增加的基础设施方向,是在静态代码和架构设计的基础上,增加对运行时状态的补充。

这四个维度涵盖了软件系统的顶层架构设计,到实际落地的代码质量,以及软件系统的运行时环境,从这四个维度入手进行优化,可以解决软件架构治理过程中的大部分问题。

通过哪些指标度量软件架构

然而,值得强调的是,给出一套度量标准用来衡量所有的软件架构是不切实际的。正如 ISO/IEC 25010 - Systems and software Quality Requirements and Evaluation (SQuaRE) — System and software quality models 中提到:

It is not practically possible to specify or measure all subcharacteristics for all parts of a large computer system or software product. The relative importance of quality characteristics will depend on the high-level goals and objectives for the project.

这两句话放到10年后的今天依然很契合,软件开发中没有银弹,不可能找到适合所有软件架构的度量方法和标准,从上文《Software Architecture Quality Measurement Stability and Understandability》Table I 中也可见一斑,每篇论文给出的metrics都不相同。在实际的软件架构设计和演进过程中,因业务场景不同,每个软件系统的架构关注点是不同的,要求也不同,自然对架构质量要求的重点就不同。

但这不妨碍我们用度量的方式来优化和治理软件架构演进过程中产生的问题,下面就从代码实现,组件设计,架构设计和基础设施四个维度给出一些可以参考的指标,以及每个指标能够帮助识别哪些问题,进而通过这些指标找到提升软件架构健康度的方法。

代码实现相关指标

在Bob大叔的《Clean Code》中,函数、类、对象和数据结构、边界、单元测试等都有专门的介绍,结合IOS/IEC 25010中对于Maintainability的定义,以及一些代码检查工具对扫描规则的定义,列举了一些常见的代码实现层面相关的指标:

指标 计算方法 指标说明
圈复杂度 参考PMD: CyclomaticComplexity 圈复杂度用来评估函数的复杂度,如果函数圈复杂度过高,表明函数有太多的决策变量,逻辑拆分不够,难以理解和维护
超大类占比 超大类数量/代码总量 超大类处理太多业务,职责不单一,业务耦合严重,不利于扩展和维护
超大函数占比 超大函数数量/代码总量 同上
重复代码频率 重复代码段发生次数 重复代码会让相同逻辑散落在不同的代码中,维护困难,容易产生修改过程中漏掉一部分导致问题
循环访问进程外组件频率 在循环中调用数据库或三方系统API的次数 循环访问进程外组件会引发性能问题,无端占用资源
测试覆盖率 测试覆盖率 测试覆盖率不足,缺少对既有代码的保护,修改很难保证不影响之前的功能

组件设计相关指标

在组件自身设计上,也要遵循开发团队约定的设计原则,比如分层架构每层的职责,以及层与层之间的关系。组件设计指标关注组件内部结构设计的合理性,以及一些交互机制的合理性,常用的指标如下:

指标 计算方法 指标说明
循环依赖数量 类之间循环依赖次数 循环依赖打破了单向依赖原则,很难判断修改产生的影响。一旦出问题,非常难定位问题
枢纽类数量 被依赖次数过多的类数量 业务实现耦合严重,职责不清
依赖异常数量 进程内模块分层依赖关系错误的次数 同循环依赖
组件间重复代码频率 公共功能代码重复发生次数 对于一些公共功能,没有抽象组件,复制粘贴代码,维护难度大

架构设计相关指标

架构设计相关指标关注组件之间的边界,交互关系的规范性,常见指标如下:

指标 计算方法 指标说明
组件循环依赖数量 组件之间循环依赖次数 组件间依赖关系混乱,职责不清
组件职责偏差率 组件职责与业务建模结果之间的偏差率 组件没有按业务合理划分,导致组件间关系复杂
调用链长度 接口在多个组件间流转的次数 调用链越长,组件间依赖深度越大,依赖关系越复杂,排查问题越难

基础设施(运行时)相关指标

基础设施(运行时)相关指标从软件系统的运行时观测软件架构的健康度,从外在表现上找到系统的脆弱点,常见指标如下:

指标 计算方法 指标说明
基础设施负载率 基础设施资源,数据库,缓存的使用量 衡量当前系统是否到了瓶颈,能否应对突发的峰值请求
平均响应时间 生产环境API的平均响应时间 衡量软件架构的性能
系统可用性 系统在线可用的时间占比 衡量架构的稳定性和整体质量
平均故障恢复时长 故障发生后恢复可用的平均时长 衡量架构在应对突发问题时快速恢复的能力
数据不一致问题占比 数据不一致问题占所有问题的比例 数据不一致通常是因为架构设计不合理,或组件交互方式不合理导致的
无用功能占比 生产环境长期不使用功能的占比 API或者某些功能长期不使用需要尽快清理,降低认知负载,也有助于优化组件之间的关系

度量之外

指标度量对于软件架构治理很重要,就像文章开头的隐喻,医生要看到各种检查指标的结果才能给出诊断,没有这些指标,大部分医生是没法坐诊的。然而,医生出具诊断时,指标只是作为参考,医生的专业知识和经验在诊断过程中起到至关重要的作用,也有常见的情况是指标异常,但医生仍然会说,不是什么大问题,定期复查,多运动,注意饮食。

除了可度量的指标,实际软件架构治理的过程中,也会有很多不可度量且非常重要的指标。就像行军打仗,能打硬仗的队伍不一定所有的指标都好看,但不妨碍它的战绩。因此,指标度量的重点是帮助开发团队更好的理解系统,理解架构,找到问题,找出解决方案,不断优化以达到软件架构治理的目标。

All rights reserved
Except where otherwise noted, content on this page is copyrighted.