欢迎你们前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~前端
本文来自 云+社区专栏,做者 腾讯移动品质中心TMQ
提到“质量”二字时,咱们的第一反应每每是“有多少BUG?”“性能好很差?“这样的问题。咱们对软件产品或服务的质量定义看其能不能知足用户的需求,包括功能、性能和体验等维度的指标,咱们能够经过各类类型的检测手段来给出其质量高低的度量。可是,若是直接拿出一段源代码放在咱们面前,问这段代码的质量好坏时,咱们又该如何做答呢?java
有人说:“好的代码就像好的笑话同样,它不须要解释(Good code is like a good joke: It needs no explanation)”。有编码经验的人对代码都有必定的“鉴赏力”,能凭感受给出代码好坏的主观评价,看到所谓的“意大利面条式代码”都会感到不舒服,可是这样凭感受的方式太个性化、太随意了,有没有一种公认的标准来鉴定代码质量呢?安全
Bob大叔在其著做《代码整洁之道》的前言中引用了这样一幅漫画:微信
使用漫画中的“每分钟爆粗数量”来衡量代码质量是个颇有趣的玩笑,强调了代码的可读易懂等这样的“内在”质量属性。相对于知足需求规范这样的“外在”质量属性,“内在”的代码质量属性强调的是支持实现功能需求的代码内部结构的质量。《Sonar code quality testing essential》一书中从七个维度定义了代码的这种内在质量,Sonar开发团队上纲上线的戏称为开发人员七宗罪:架构
Martin Fowler在其著做《重构:改善即有代码的设计》中生动形象的使用“代码坏味道(Bad Code Smells)”来比喻低质量的代码设计和实现所显现的“症状”。书中罗列了22种代码坏味道以及对应的重构手法。前端性能
参照这些资料,如今咱们能够用可测性,可读性,可理解性,容变性等代码可维护性维度的质量属性来衡量代码质量。代码质量指的是代码内在的非功能性的质量,用户不能直接体验到这种质量的好坏,代码质量很差,最直接的“受害者”是开发者或组织自身,由于代码质量好坏直接决定了软件的可维护性成本的高低,例如重复代码会形成维护成本的成倍增长;不规范的代码、不良注释和复杂度太高的代码会增长阅读和理解代码的难度,复杂度太高也会极大增长测试覆盖的难度,耗费过多人力,而缺乏测试覆盖的代码会使得定位问题和修复问题的难度加大;结构不良、低内聚高耦合的代码则会使得哪怕是微小的需求变动或功能扩展都无从下手,修改的代价极可能超过了重写的代价。工具
至此,咱们获得了一些定性的办法来衡量代码的质量,咱们能够借助一些代码扫描工具来暴露代码的质量问题,也有了相应的重构方法和技巧来应对这些问题。可是,咱们仍是难以回答某段代码有多好或多差,两段代码相比哪一个更好这样的问题,由于咱们仍然没有彻底解决代码质量的量化问题:一样都是代码质量问题,重复代码和过多注释的危害确定是不同的;一样都是方法太复杂,圈复杂度为10的方法和圈复杂度为20的方法相比,危害和修改难度也差异很大。因此咱们不能直接用问题的数量来衡量质量,须要找到更精细合理的量化度量方法。性能
如何评估软件产品源代码质量一直是业界的一大挑战,SQALE(Software Quality Assessment based on Lifecycle Expectations)方法的出现提供一套科学的度量和分析方法,有效应对了这一挑战。SQALE方法整合了ISO-25010标准与代码规范,其目标是:以客观、准确、可复制和自动化的方式为评估软件应用程序的源代码提供支持;为管理技术债务提供一种有效的方法。SQALE是目前众多主流代码分析工具的参照标准,包括咱们熟知的SonarQube,和CoderGears, SQUORE等商用代码扫描分析工具。单元测试
下面咱们简单介绍一下SQALE方法的原理。SQALE方法包含两种模型:质量模型和分析模型。下图的树型结构展现了SQALE方法的质量模型:树根节点表明软件质量(此处即代码质量),从左向右展开,第一级定义了代码质量的特征分类,往下是每种特征的子类,最后是每一个子类对应的属性/具体的度量项。测试
从左向右的方向是把代码质量不断细化分解为更小的单元,直到最小粒度能够直接度量的属性;从右向左的方向是把度量值逐步汇总到根节点,最终获得一个总的代码质量的度量值。表1是SQALE质量模型分解的示例。表中第一列把代码质量细分为可维护性、可测性、可变动性和可靠性几个维度,对于每一个维度又有进一步的细节,如可测性又细分为单元测试可测性和集成级可测性这样的子特征,进一步的,子特征还能细化到可直接度量的属性,或者称为要求(表中第三列,即咱们一般说的代码扫描规则),例如单元测试可测性再细分为“模块测试路径数量<11”和“模块调用参数数量<6”这样的规则:
注:咱们使用的SonarQube并无彻底照般SQALE的质量模型,在5.4及以前的版本中还存在与SQALE相似的可测性、易变动性、可理解性和可读性等维度,整个模型只有两级,即第一列和第二列合并了,例如可测性维度下直接对应了“表达式不该该太复杂”,“方法不该该太复杂”,“方法不该该有太多参数”等规则。在5.4以后的版本,即目前使用的版本则进一步简化,代码质量对应的扫描规则直接归属于“坏味道”大类,具体的规则能够打上多种标签来归类,分类和配置更加灵活。
那么,这些规则应该怎么量化呢?或者说,如何度量代码违背规则的程度,并且这种度量是能够加总的,毕竟规则间差别很大,上文也解释过,直接按数量汇总确定是不合理的。
怎么办呢?SQALE方法的分析模型解决了这个问题,由此咱们也引出了本文中的第二个重要概念:技术债TechnicalDebts。
“技术债”这一律念最先出如今1992年,其本义是指,开发人员为了加速软件开发,在应该采用最佳方案时进行了妥协,改用了短时间内能加速软件开发的方案,从而在将来给本身带来的额外开发负担。这个定义暗示了这种“负债”是一种刻意的、理性的通过权衡的行为,后文中咱们进一步探讨技术债务的类型时会指出这必定义仅仅表明了技术债中相对良性的一类,是一个比较“温和”的定义。此处咱们关注的重点是使用技术债这一隐喻来帮助你们理解度量代码质量的方法。
既然谈的是“债”,天然就应该和钱有关了。所以,技术债的“本金”就定义为修复代码质量问题所需消耗人力资源估值,例如,针对java语言,修复一个圈复杂度为15的方法须要一个开发人员15分钟的时间(以sonar java分析器缺省设置为例),这个值就是负债的本金。代码扫描工具中对应代码质量的每条扫描规则都对应着一个债务计算方法,有的规则是设定了固定的债务值,有的则根据违规程度有相应的计算公式。引入技术债的概念后,SQALE方法就能够把不一样规则对应的代码质量度量统一为人力资源的消耗这一单一指标上。
根据图2质量模型所示由右向左的方向逐级汇总,就能够获得待评价软件的代码质量度量值。咱们的其中一个度量难题:如何客观评价代码的质量,由此就获得了解答。
关于技术债另外还有一个概念值得在这儿强调一下,即负债的利息。咱们知道,一般借钱是有利息的,有的负债利息很低(如安居计划利息为0),有的利息较高(如信用卡欠款),有的则高到使人绝望(如高利贷)。一样,技术债也是有利息的,存在利滚利的状况,有的违规项立刻修复要10分钟,若是放着无论一段时间后,也许就须要20分钟甚至更多的时间来修复(因为代码细节的知识随时间流逝,以及破窗效应形成代码问题加速恶化等缘由)。有的代码扫描工具会针对规则定义本金和利息的计算方法,如Coder Gears的CppDepend,咱们目前使用的SonarQube平台上的代码扫描插件不支持计算利息,所以本文就不过多讨论,你们只须要记住,由于利息的存在,技术债务不及时偿还的话,会在将来呈现出非线性增加,形成始料不及的损失。后续文章在讨论技术债的危害时,咱们还会时常说起技术债的非线性特征。
如今咱们还剩下一个度量问题:如何知道两段代码的质量差别?如今有了技术债本金这个绝对值,可是不一样规模,不一样类型的代码应该如何比较呢?SQALE方法中继续借鉴了“负债率”这个术语,计算公式为:偿还债务所需耗费的资源(即本金)除以重写全部代码的预估耗费的资源。在扫描工具的实现中,分母是经过代码量和开发生产力水平计算得出,其中的生产力是一个配置项,如SonarQube上能够配置编写一行代码的平均估计耗时。SQALE进一步使用了术语“债务等级”,定义了从A(很是好)到E(很是差)五个等级,根据负债率数值所在区间对应不一样的等级,例如SonarQube中缺省[0, 5%]是A,(5%, 10%]是B,(10%,20%]是C,(20%, 50%]是D,高于50%是E。当负债率达到100%时,即债务开始超过资产,资不抵债,这时就称这种状况为“技术破产”。固然,平常工做中碰到这种状况时,咱们不会用这么吓人的术语,一般是打着“重构”的旗号重写一遍。
下图是CppDepend的一个扫描汇总结果的示例,包含了咱们讨论的全部概念(使用CppDepend为例是为了展现更全面的信息)。
上图中工具扫描的代码行数为19862行,共负债32天,债务的年息是9天2小时,负债率是6.39%,债务等级是B级。
咱们平常工做使用的工具平台是SonarQube,以下图所示:
图中的项目负债12天,共有923个坏味道(即违规项数量),负债率(图中翻译为“技术债务比率”)为6.3%,债务等级(图中为SQALE评级)为B级。
SQALE给咱们提供一套有效合理衡量代码质量的方法和工具,下图中SQALE方法流程清晰的展现了整个方法流程各个环节:
图片来源:http://www.sqale.org
有了方法和工具(SonarQube)的支持,咱们能够看看咱们本身的代码质量是个什么情况。从扫描结果来看,与一些优秀的开源项目相比,咱们仍是有一些差距。部门EP(Engineering Productivity)极社根据扫描结果,挑选出了比较重要的如下4条规则:
注:SonarQube中有些语言对应的扫描插件不支持第2条规则,如C++和Python。
这4条规是咱们须要优先偿还的技术债,目前已经在整个部门推广实施。
读到这里,不少人也许忍不住想问,如此这般折腾有啥用?代码质量相对不高也没有影响到公司业务呀,提升这种代码质量除了让咱们忙上加忙外,能有什么好处?或者说有什么价值?跟个人KPI有啥关系?
好吧,既然代码质量很差就是“负债”,那么欠债还钱不就是天经地义么,毕竟“出来混,早晚要还的。”显然这样的苍白说教没法服众,因此咱们后续文章的重点就是深刻理解技术债,深刻分析提高代码质量的必要性和紧迫性。
So:读者朋友们,大家所在的团队或组织是否也在重视代码质量呢?
问答
是否有工具可用于计算项目的代码度量?
相关阅读
美团外卖Android Lint代码检查实践
几点建议帮你写出简洁的JS代码
Web前端性能基础指标&计算方式
此文已由做者受权腾讯云+社区发布,原文连接:https://cloud.tencent.com/dev...
欢迎你们前往腾讯云+社区或关注云加社区微信公众号(QcloudCommunity),第一时间获取更多海量技术实践干货哦~