当前位置:首页 > 实用技巧 >

为什么开发软件装起来那么复杂(开发一个软件有那么容易吗)

来源:原点资讯(www.yd166.com)时间:2023-04-22 16:22:53作者:YD166手机阅读>>

作者:王洋 阿里ICBU技术团队

本文将重点围绕软件复杂度进行剖析,希望能够帮助读者对软件复杂度成因和度量方式有所了解,同时,结合自身的实践经验谈谈我们在实际的开发工作中如何尽力避免软件复杂性问题。

大型系统的本质问题是复杂性问题。互联网软件,是典型的大型系统,数百个甚至更多的微服务相互调用/依赖,组成一个组件数量大、行为复杂、时刻在变动(发布、配置变更)当中的动态的、复杂的系统。而且,软件工程师们常常自嘲,“when things work, nobody knows why”。

一、导致软件复杂度的原因

导致软件复杂度的原因是多种多样的。

宏观层面讲,软件复杂是伴随着需求的不断迭代日积月累的必然产物,主要原因可能是:

  • 对代码腐化的退让与一直退让。
  • 缺乏完善的代码质量保障机制。如严格的CodeReview、功能评审等等。
  • 缺乏知识传递的机制。如无有效的设计文档等作为知识传递。
  • 需求的复杂性导致系统的复杂度不断叠加。比如:业务要求今天A这类用户权益一个图标展示为✳️,过了一段时间,从A中切分了一部分客户要展示。

对于前三点我觉得可以通过日常的工程师文化建设来尽量避免,但是随着业务的不断演化以及人员的流动、知识传递的缺失,长期的叠加之下必然会使得系统越发的复杂。此时,我觉得还需要进行系统的重构。

从软件开发微观层面讲,导致软件复杂的原因概括起来主要是两个:依赖(dependencies) 和 隐晦(obscurity)。

依赖会使得修改过程牵一发而动全身,当你修改模块一的时候,也会牵扯到模块二、模块三等等的修改,进而容易导致系统bug。而隐晦会让系统难于维护和理解,甚至于在出现问题时难于定位问题的根因,要花费大量的时间在理解和阅读历史代码上面。

软件的复杂性往往伴随着如下几种表现形式。

1.1 修改扩散

修改时有连锁反应,通常是因为模块之间耦合过重,相互依赖太多导致的。比如,在我们认证系统中曾经有一个判断权益的接口,在系统中被引用的到处都是,这种情况会导致一个严重问题,今年这个接口正好面临升级,如果当时没有抽取到一个适配器中去,那整个系统会有很多地方面临修改扩散的问题,而这样的变更比较抽取到适配器的修改成本是更高更风险的。

@Override public boolean isAllowed(Long accountId, Long personId, String featureName) { boolean isPrivilegeCheckedPass = privilegeCheckService.isAllowed( accountId, personId, featureName); return isPrivilegeCheckedPass; }1.2 认知负担

当我们说一个模块隐晦、难以理解时,它就有过重的认知负担,开发人员需要较长的时间来理解功能模块。比如,提供一个没有注释的计算接口,传入两个整数得到一个计算结果。从函数本身我们很难判断这个接口是什么功能,所以此时就不得不去阅读内部的实现以理解其接口的功能。

int calculate(int v1, int v2);1.3 不可知(Unknown Unknowns)

相比于前两种症状,不可知危险更大,在开发需求时,不可知的改动点往往是导致严重问题的主要原因,常常是因为一些隐晦的依赖导致的,在开发完一个需求之后感觉心里很没谱,隐约觉得自己的代码哪里有问题,但又不清楚问题在哪,只能祈祷在测试阶段能够暴露出来。

二、软件复杂度度量

Manny Lehman教授在软件演进法则中首次系统性提出了软件复杂度:

软件(程序)复杂度是软件的一组特征,它由软件内部的相互关联引起。随着软件的实体(模块)的增加,软件内部的相互关联会指数式增长,直至无法被全部掌握和理解。

软件的高复杂度,会导致在修改软件时引入非主观意图的变更的概率上升,最终在做变更的时候更容易引入缺陷。在更极端的情况下,软件复杂到几乎无法修改。

在软件的演化过程中,不断涌现了诸多理论用于对软件复杂度进行度量,比如,Halstead复杂度、圈复杂度、John Ousterhout复杂度等等。

2.1 Halstead 复杂度

Halstead 复杂度(霍尔斯特德复杂度量测) (Maurice H. Halstead, 1977) 是软件科学提出的第一个计算机软件的分析“定律”,用以确定计算机软件开发中的一些定量规律。Halstead 复杂度根据程序中语句行的操作符和操作数的数量计算程序复杂性。针对特定的演算法,首先需计算以下的数值:

  • 为不同运算子(操作符)的个数。
  • 不同运算元(操作数)的个数。
  • 为所有运算子合计出现的次数。
  • 为所有运算元合计出现的次数。

上述的运算子包括传统的运算子及保留字,运算元包括变数及常数。依上述数值,可以计算以下的量测量:

为什么开发软件装起来那么复杂,开发一个软件有那么容易吗(1)

举一个例子,这是一段我们当前应用中接入AB实验的适配代码:

try { DiversionRequest diversionRequest = new DiversionRequest(); diversionRequest.setDiversionKey(diversionKey); if (MapUtils.isNotEmpty(params)) { DiversionCondition condition = new DiversionCondition(); condition.setCustomConditions(params); diversionRequest.setCondition(condition); } ABResult result = xsABTestClient.ab(testKey, diversionRequest); if (result == null || !result.getSuccess()) { return null; } ​ return result.getDiversionResult(); } catch (Exception ex) { log.error("abTest error, testKey:{}, diversionKey:{}", testKey, diversionKey, ex); throw ex; }

我们梳理这段代码中的预算子和运算元以及分别统计出其个数:

为什么开发软件装起来那么复杂,开发一个软件有那么容易吗(2)

根据统计上面统计得到的对应的数据我们进行计算:

为什么开发软件装起来那么复杂,开发一个软件有那么容易吗(3)

Halstead方法优点
  • 不需要对程序进行深层次的分析,就能够预测错误率,预测维护工作量;
  • 有利于项目规划,衡量所有程序的复杂度;
  • 计算方法简单;
  • 与所用的高级程序设计语言类型无关。
Halstead 方法的缺点
  • 仅仅考虑程序数据量和程序体积,不考虑程序控制流的情况;
  • 不能从根本上反映程序复杂性。给我的直观感受是他能够对软件复杂性进行度量,但是很难讲清楚每一部分代码是好还是坏。
2.2 圈复杂度

圈复杂度(Cyclomatic complexity)是一种代码复杂度的衡量标准,在1976年由Thomas J. McCabe, Sr. 提出。

在软件测试的概念里,圈复杂度用来衡量一个模块判定结构的复杂程度,数量上表现为线性无关的路径条数,即合理的预防错误所需测试的最少路径条数。圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系,一般来说,圈复杂度大于10的方法存在很大的出错风险。

为什么开发软件装起来那么复杂,开发一个软件有那么容易吗(4)

首页 123下一页

栏目热文

软件开发哪个版本最好(软件开发语言哪个最好用)

软件开发哪个版本最好(软件开发语言哪个最好用)

  工欲善其事,必先利其器。我们要做好一件事,准备工作非常重要。在开始学习使用Python之前,先要搭建好Python的...

2023-04-22 16:06:19查看全文 >>

宝马x5大轮胎是哪款(宝马x5推荐什么轮胎)

宝马x5大轮胎是哪款(宝马x5推荐什么轮胎)

全新宝马X5提供四种车型选择,搭载2.0T/3.0T发动机,拥有出色的操控性,定位为中大型豪华SUV,让我们一起看看这款...

2023-04-22 16:17:05查看全文 >>

宝马x5用什么品牌轮胎好(宝马x5使用哪种轮胎最好)

宝马x5用什么品牌轮胎好(宝马x5使用哪种轮胎最好)

我喜欢宝马X5,是从看到它的第一眼就开始的。我看上X5的第一个原因是它霸气的外表,线条丰富,肌肉感强,处处赏心悦目。我去...

2023-04-22 16:03:32查看全文 >>

宝马x5原装什么轮胎(18款宝马x5原装轮胎什么牌子)

宝马x5原装什么轮胎(18款宝马x5原装轮胎什么牌子)

2019年4月22日,在全球汽车领域,来自德国的汽车代表了最高的造车水平,尤其是其宝马,奥迪,奔驰等享誉全球,得到了广泛...

2023-04-22 15:39:21查看全文 >>

宝马x5原装轮胎什么品牌(18款宝马x5原装轮胎什么牌子)

宝马x5原装轮胎什么品牌(18款宝马x5原装轮胎什么牌子)

本期是2022年10月份长期评测的第三篇,由宝马客长测组撰稿人榴莲君和Charles呈现,亮相车型为宝马X5(G18)和...

2023-04-22 16:14:44查看全文 >>

为什么有些软件开发工具那么多(常用的软件开发工具有哪些)

为什么有些软件开发工具那么多(常用的软件开发工具有哪些)

随着业务的发展和公司规模的不断扩大,企业所需的软件开发需求也在不断增加,而传统的软件开发方式已经无法满足这种需求。但是,...

2023-04-22 16:05:45查看全文 >>

软件二次开发升级容易吗(软件的二次开发难不难)

软件二次开发升级容易吗(软件的二次开发难不难)

很多通用传统的 ERP厂商经常会有这样的抱怨:起初的几个月进行项目分析和讨论,用户也认可了,ERP系统做出后,结果这时候...

2023-04-22 16:17:22查看全文 >>

为什么软件要定制开发(软件定制为什么难做)

为什么软件要定制开发(软件定制为什么难做)

1、软件定制开发降低了对企业的资金要求,通用软件一般功能比较多,有一些功能其实有的时候也用不上(例如:一些app商城的购...

2023-04-22 16:08:45查看全文 >>

为什么要不断开发新的软件(大型软件都是用什么开发的)

为什么要不断开发新的软件(大型软件都是用什么开发的)

互联网时代,软件开发大势所趋。软件能够提高效率,按照固定的逻辑不间断的运行,能够承载企业的商业模式。随着移动互联网时代的...

2023-04-22 16:05:55查看全文 >>

软件开发完成后需要升级吗(开发软件要不要申请)

软件开发完成后需要升级吗(开发软件要不要申请)

很多客户朋友在开发完APP时,除了如何运营,还会关心软件做好了维护怎么办?这个问题其实被问的挺多的,因为大多数开发软件的...

2023-04-22 16:13:00查看全文 >>

文档排行