DevOps落地笔记-20|软件质量:决定系统成功的关键

上一课时介绍通过提高工程效率来提高价值交付效率,从而提高企业对市场的响应速度。在提高响应速度的同时,也不能降低软件的质量,这就是所谓的"保质保量"。具备高质量软件,高效率的企业走得更快更远。相反,低劣的软件质量,高效率则会让企业死得更快。高质量的软件是企业一直在追求的目标,那么又有哪些指标可以帮助我们识别软件存在的问题呢?这就是今天就介绍一些有关这方面的内容。

什么是软件质量?

如今,任何一个企业都是数字化企业,任何一家数字化企业都是以软件为业务核心。因此,软件的质量是企业生死存亡的关键因素,务必要引起重视。既然软件质量如此重要,领导者需要了解当前软件质量是多少,存在什么问题,软件质量的发展趋势是什么,这些就是软件质量的度量。

软件质量也包含两部分:内部质量外部质量

& 内部质量:是指被开发人员感知的质量,比如,代码的缺陷、坏味道、不合理的架构设计等。内部质量是造成外部质量的源头,在开发过程中要尽早发现、尽早修复内部质量问题,提高发布到生产环境中产品的外部质量。

& 外部质量:是指能够被用户感知到的质量。比如,用户在使用产品的过程中出现异常,服务不可用,响应迟钝等现象,影响用户体验。外部质量是决定产品是否成功的关键,提高外部质量是团队成员的最终目标。

& 下面分别从内部质量和外部质量两个方面介绍软件的质量。

内部质量

企业在实施 DevOps 的实践中,也一直在尝试将代码质量的检查集成到流程中,比如持续交付流水线中集成静态代码检查,单元测试覆盖率检查等环节。针对代码质量检查的工具也有很多,常用的有 SonarQube、PMD、FindBugs 等。下面这张图是 SonarQube 代码质量检查的概览页面。

代码质量检查

代码质量度量是针对代码本身的度量,根据开发人员的主动和被动,以及对软件造成的影响大小,可以分为Bug 和漏洞以及技术债务。

& Bug 和漏洞

Bug 和漏洞是开发人员在开发业务功能时,在无意识行为下产生的代码问题,即并不是开发人员故意为之。这类问题一般不易被发现,一旦被发现需要及时修复,因为会对软件造成严重影响。Bug 是指代码中的错误,可能会阻止程序按预期运行,影响的是程序的可靠性。漏洞是指代码中的问题,心怀不轨的人会利用这些问题破坏程序的安全性。

比如:Java 语言中,字符串和装箱类型的比较使用 equals() 进行比较。下面这段代码就会检查出 Bug。

String firstName = getFirstName(); 

String lastName = getLastName();

if (firstName == lastName) { ... };

这是因为使用==或!=比较运算符,比较的是内存地址而不是具体的值。在某些情况下,即便 firstName 和 lastName 具体的值相等,但也返回 false。

缺陷和漏洞的度量,一般采用数量和级别,级别分为BLOCKER(阻断)、CRITICAL(严重)、MAJOR(主要)、MINOR(次要)、INFO(提示)。

& 技术债务。

技术债务是指开发人员在开发和设计的时候,为了能满足短期的效益而采取的权宜之计。比如:缺乏自动化测试的代码,包含坏味道的代码。坏味道是指不会阻止程序的正常运行,但可能会对代码的可维护性产生影响。如上图中技术债务需要1天偿还,包含坏味道 86 个,这些就是对技术债务的度量。

如下面就是一个坏味道的例子,当数组或集合返回 null 时,调用方需要做 null 判断,否则就会抛出空指针异常。

public static List<Result> getResults() {

  return null;                             // Noncompliant

}

public static Result[] getResults() {

  return null;                             // Noncompliant

}

public static void main(String[] args) {

  Result[] results = getResults();

  if (results != null) {                   // Nullity test required to prevent NPE

    for (Result result: results) {

      /* ... */

    }

  }

}

除此之外,还包含圈复杂度、函数代码行、文件代码行、重复代码率、重复文件数等度量。

测试质量检查

测试阶段又称为质量保证(QA)阶段,是软件开发过程中确保软件功能性和非功能性需求满足用户要求的阶段。为了提高测试效率,很多企业逐渐减少人工测试的比率,提高自动化测试的比率。测试阶段的质量度量可以使用测试覆盖率和测试缺陷数量来表示。

测试覆盖率。

测试覆盖率是衡量代码质量的一个方法,是指自动化测试中代码的覆盖程度,包含单元测试、集成测试、回归测试的测试覆盖率。上图中 54.6% 是测试覆盖率的度量。测试覆盖率越高,发现问题的概率越大,在测试阶段发现的问题越多,软件发布到生产环境后问题就会越少。

但是关于测试覆盖率"多少算是合适?"这一问题,很多人是存在分歧的。业界普遍认为测试覆盖率达到 80% 就足够了。这里强调的是,测试一定是有效测试,无效的测试即便 100% 覆盖也没有任何意义。

& 测试缺陷数量。

测试缺陷数量是指在测试阶段发现的代码问题的数量。如下图所示。每一个缺陷又可以按缺陷类型、严重程度、发现阶段进行标记。

1.缺陷类型:用户体验问题、性能问题、接口问题、界面问题、环境问题等。

2.严重程度:致命缺陷、严重缺陷、一般缺陷、轻微缺陷和建议等。

3.发现阶段 :功能测试、单元测试、集成测试、用户验收测试等。

测试阶段的目的就是发现问题,所以我们不能惧怕发现问题。在实际开发过程中,测试人员给开发人员提 Bug,开发人员会很抵触,好像是污蔑自己的编码智商,使得开发和测试也会处于对立局面。另外,测试人员要分清哪些是 Bug,哪些是需求改进,不要将需要优化的需求也作为 Bug 提给开发人员。

虽然会度量测试阶段的缺陷数量,但不要作为衡量团队成员能力的依据,也不会作为绩效考核的标准。还是前面提到的,要以结果性、全局性的指标为最终指标。

外部质量

上面介绍了内部质量,以及通过代码检查和自动化测试来保证内部质量,在开发流程中也集成了工具和制度。虽然我们做了大量的质量保证活动,就一定能交付高质量的产品吗?答案是"不一定"。内部质量并不能说明用户对产品是满意的还是抱怨的,也不能说明用户使用过后,是想继续使用还是想舍弃。由于缺少这些相关的度量信息,以至于无法判断产品的质量状态。因此,要从用户满意度、产品非功能性等方面评估产品的外部质量。

用户满意度

用户满意度是从最终用户的角度对产品的评判。企业在调查用户满意度方面已经很成熟了,有多种方式可以收集用户对产品或服务的评价信息。拨打过 10086 的同学都知道,客服在结束时都会说"请您稍后对我的服务做出评价,满意请按 1,不满意请按 2",这就是收集用户满意信息的一种方式,其他的还有:

& 调查问卷;

& 互联网产品卸载时的弹窗;

& 投诉与建议。

这几种方式,都可以了解用户对产品的哪些功能不满意,为后期进行产品功能优化时提供依据。那么,用什么方式度量用户满意度比较合适呢?业界认为"净推荐值(NPS)"是衡量用户满意度的黄金标准。这是计算某个客户会向其他人推荐某个企业或服务可能性的指数,采用 0-10 分进行打分,分数越高说明你越愿意推荐这个企业或服务。

产品非功能性

除了用户本身对产品或服务的直观感受外,用户在使用产品过程中感知的产品非功能性问题也是衡量产品质量一个因素。比如产品的可靠性、性能等。

& 可靠性:是指用户在使用产品的过程中出现服务不可用的概率。这里既可以指具体的人使用产品功能,也可以指系统间的调用或通信。总之,给用户带来的影响是不能正常的使用产品。

& 性能:是指用户在使用产品时的流畅性,未出现卡顿、延迟等现象。比如,打开一个页面需要 10s 以上,虽然还能够使用产品,但用户体验不好。

产品的非功能性问题会最终影响用户满意度,一般通过用户反馈的缺陷和问题数量及严重程度来度量产品的可靠性,通过应用程序性能监控系统(APM) 度量产品的性能。随着DevOps实践的不断深入,通过蓝绿部署、金丝雀发布等方法,先在一小部分用户使用新版本,以便提前发现软件存在的问题,从而避免让更多用户受到影响。以及使用混沌工程,提前发现问题,减少产品不可用的概率。这些方法都是针对产品的非功能性采取的防控措施。

总结

本课时主要介绍了软件质量,这一决定产品成功与失败的关键要素。软件的质量分为内部质量和外部质量,二者相辅相成,互相影响。内部质量是源头,外部质量是结果。提高内部质量会进一步提升外部质量,外部质量也会反过来促进内部质量的提升。DevOps 的目标是在提高研发效率的同时,也要提高软件产品的质量。

如今市场竞争越发激烈,用户在第一次使用后,认为产品或服务没有达到满意,是不会再有第二次机会的。因此,软件的质量是企业研发的重中之重,也是企业实施 DevOps 的目标之一。

相关推荐
大数据编程之光10 分钟前
Flink Standalone集群模式安装部署全攻略
java·大数据·开发语言·面试·flink
D-海漠11 分钟前
基础自动化系统的特点
运维·自动化
我言秋日胜春朝★19 分钟前
【Linux】进程地址空间
linux·运维·服务器
爪哇学长24 分钟前
双指针算法详解:原理、应用场景及代码示例
java·数据结构·算法
ExiFengs28 分钟前
实际项目Java1.8流处理, Optional常见用法
java·开发语言·spring
paj12345678929 分钟前
JDK1.8新增特性
java·开发语言
捂月35 分钟前
Spring Boot 深度解析:快速构建高效、现代化的 Web 应用程序
前端·spring boot·后端
繁依Fanyi40 分钟前
简易安卓句分器实现
java·服务器·开发语言·算法·eclipse
C-cat.41 分钟前
Linux|环境变量
linux·运维·服务器
慧都小妮子1 小时前
Spire.PDF for .NET【页面设置】演示:打开 PDF 时自动显示书签或缩略图
java·pdf·.net