本文来自极狐GitLab 资源中心。原文链接:https://resources.gitlab.cn/articles/614fb704-882f-4601-927f-00a8b1dca2ed。
关联阅读
- 如何做好 Code Review?【上】
- 如何做好 Code Review?【中】
GitLab 是一个全球知名的一体化 DevOps 平台,很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab :https://gitlab.cn/install?channel=content&utm_source=csdn 是 GitLab 在中国的发行版,专门为中国程序员服务。可以一键式部署极狐GitLab。
更多关于极狐GitLab :https://gitlab.cn 或者 DevOps 的最佳实践,可以关注文末的极狐GitLab 公众号。
Code Review 是否影响老代码?
随着项目越来越大,没人敢改老代码,有的人就把函数复制一份。这样虽然没有影响老代码,但是影响整个项目的可维护性,这是很多老项目必然面临的一个无解的问题。
另外,回归测试也越来越久,假如要改一个紧急的 bug,想上线也要回归,这么大的项目回归测试需要很久。那多花钱招一些测试人员行不行?
实际上是解决不了问题的,业界已经踩过这个坑了。因为 bug 多的根源是开发人员写的代码质量不高,而不是测试人员的问题。只有在开发阶段就确保代码质量,才能更好的规避这些问题,也就是进行自测。
很多开发同学都会用 Postman、Curl 或在浏览器里去测试,这样行不通的。因为你第一次写的时候,有耐心测了 4 次,比如左边代码有 4 种情况,测了 4 次,但第二次改的时候,可能就不想测这么多次了,或者别人改的时候也不会帮你测所有情况。于是,低成本、低质量必然的结局就产生了,这在国内非常普遍。
但如果严格要求任何人改一个字母、一个空格都要去测试所有情况,成本将高到难以接受。上图里的 4 种情况算少的,往上组合可能是 4×4×4 指数级的数量。
作为一个负责任的开发,有时间去操作 postman,不如去写一个脚本。把 postman 的参数都存在一个脚本里,自动去跑,这就是业界的终极方案,即自动化测试。
第一次写脚本虽然多花一点时间,以后再修改,成本就非常低了。不管改任何老代码,只要测试跑挂了,立马就能发现,实现了中等成本、高质量的方案。有人可能会问,中等成本到底有多少成本?根据国内某家大厂的调研,大概要多花 20%~40% 的开发成本。
技术管理的同学听到这里,可能还是觉得行不通,我们公司业务非常忙,如果再增加 40% 的开发成本,直接就要破产倒闭了。实际上不一定,公司总成本可能会下降。
有本书叫做《有效的单元测试》,里面做了一个统计,假设 A 公司不写单元测试,就像咱们国内大部分团队的情况:
- 写代码花费 7 天,然后丢给测试同学;
- 测试发现很多 bug,打回修改,又花了 12 天;
- 26 天后终于上线了,客户还发现了 71 个 bug……
而另一种情况,B 公司写单测试,虽然写代码时间翻倍,花了 14 天,但提交之后基本没 bug,最后上线总时间 23 天,上线之后客户发现的 bug 还很少。
如果这是同一个行业的两家公司,就意味着 B 公司把钱砸在了开发人员上面,提升了开发成本,降低测试成本,最后公司的迭代速度、交付速度变快了,提高了公司的市场竞争力,而且客户满意度更高了;而 A 公司 bug 多,交付慢,竞争力越来越低。
有的开发同学从来没有学过单元测试,抱有一个偏见,觉得自己测自己的代码,肯定不仔细,还是丢给别人测比较好 ,其实这是个误解。
比如左边这个代码,有三种情况,右边只写了一种情况来验证它,不要紧,只要执行一下 mwnw verify,它就会告诉你:你的覆盖率测试覆盖率只有 33%。
写单元测试的核心指标就是覆盖率。那么,做到多少才算优秀?可以看下 GitLab 项目本身,后端 Ruby 做到了98%的单元测试,前端覆盖率做到了 76%。
因为后端都是数据和接口,非常便于做自动化测试,做到 90% 以上才算比较好。前端有的界面难以去自动化测试,可能需要一部分测试同学人工进行验收测试。
Google 是在 20 年前就开始这么做了,微软大概是在 2010 年左右,开始推行开发人员写单元测试,国内某家大厂在前两年开始要求开发人员写单元测试覆盖率达到 80%,否则就不允许合并。
强制测试覆盖率
如果覆盖率不到 80%,怎么去拦截?用 Java 插件 jacoco 就可以了。
比如这个 Java 项目,在 pom 插件里引入 Java 插件,里面写上 limit 0.8,就是最低 0.8 的覆盖率,然后去执行最下面执行命令,就可以算出来测试覆盖率。假设覆盖率只有 0.33,就会产生报错拦截。这个拦截配置在 CI 流水线里设置就可以了,非常简单。
覆盖率下降拦截
但是这样对老项目非常不友好,大量的老项目测试覆盖率是 0。如何让它逐渐提高,减少 bug 呢?极狐GitLab 有一个更好的方案:覆盖率下降拦截。
比如老项目的覆盖率 50% 多,而这次提交新写的代码又导致覆盖率下降了 2.85%,这个时候就会被拦截了。同时还会对测试报告进行标准化采集,与上面提到的代码质量报告类似。
合并请求的页面是开发同学最常使用的,极狐GitLab 把很多报告都做在这个页面里,让开发同学自助修复,不需要跳到任何别的地方,大幅度提高开发效率。
单元测试覆盖率报表
评估一家公司的技术水平,如果只看一个指标,就看单元测试覆盖率,如果看两个指标,则再看代码规范的错误率,即代码不规范的比例(代码规范错误率报表功能即将上线,敬请期待)。
极狐GitLab 会自动生成一个单元测试覆盖率报表,技术管理者可以看到公司所有项目的覆盖率排行榜。这样就知道各个团队的代码质量如何,bug 多不多。
通过报表里的走势图可以一目了然看到,项目覆盖率是不是在平滑上升。因此 Code Review 不需要去评判是否把老接口改挂了,假设改了一个地方,可能被几十个地方调用,人脑不是编译器,判断不出来,只有自动化测试才能够解决这个问题。
哪些需要人工审核?
Code Review:英文术语
前面提到的这么多问题都通过持续集成自动解决了,我们还需要人工审核吗?答案是要的。
比如 Java 项目, spring 项目里面提交了一个 SQL 文件,这段代码应该提交到代码库里进行数据库评审。那么当你新做了一个业务逻辑,建了一个表或者加了一个字段,怎么去评判数据库设计合不合理、文档放在哪里?要不要开个评审会?
直接把它提交到 Git 里,走代码评审就好了,这是非常成熟的一个流程。
如上图,用户表里有个字段:积分,怎么翻译?很多同学词典一搜积分叫 integral,就贴进数据库建表了,等来了个过了英语四级的新同学,发现这是数学积分,数学术语,跟用户积分完全没关系。
怎么样才能正确翻译?可以通过整句翻译,结合场景等方式更加准确,比如积分可以换礼物,才知道积分原来是 point,很多生活中的专用术语,很难通过机器直翻获取。
还有个例子,微信的「拍一拍」在英文版里怎么翻译?第一版不好,后面又改了个词,程序员就疯了,数据库字段和代码都写好了。跑了几个月又改掉了,那么代码里到底是跟着改还是不改呢?
所以英文术语设计是 Code Review 很重要的部分,关系到数据库字段设计,因为数据库字段往往会变成变量,变成接口,它一错后面全错了。
怎么降低术语审核难度?理论上术语应该由需求方提供,假设你是做一个航空行业的外包,这个航空行业有什么术语应该甲方来提供是比较合理。
如果不是外包,是自己做的产品,产品经理应该提供英文术语表吗?这个也不太现实,因为大部分产品只做中文版,产品经理只需要中文界面,没有想过英文术语。于是,代码中用什么英文术语,大部分时候都是开发人员自由发挥,一不小心就导致质量的灾难。
设计模式等技巧
Code Review 还要 review 一些业务逻辑、设计模式,即面向对象的最佳实践,有一些编程有更优雅的写法,这个是高级工程师指导初级工程师成长的很重要的一部分。
比如下图左边这段 Java 代码,它的缩进换行都很漂亮,唯一的问题就是看起来这些函数都太简单了,get ID、get name、set ID、set name…
这么简单的代码,全部重复的写,就是体力活,所以业界用 lombok 解决这个问题:定一个 @Setter、@Getter,就可以把这些函数全部省略掉了。
总结
最后我们总结一下,一个完善的持续集成流水线应该是怎样的?它包括:
- 代码规范的质量门禁;
- 强制的单元测试;
- 编译打包;
- 安全扫描。
有了极狐GitLab 这么一个自动落地规范的流程,把研发流程理顺,Code Review 就省心了。
极狐GitLab 在持续集成里做了 Git 各种规范的拦截;
在极狐GitLab git server 端,做了 Git 规范拦截,包括 commit 规范、分支规范、分支命名规范;
在持续集成里做了运行环境的拦截,包括代码扫描、漏洞扫描。
尽量让这些工作自动化,这样高级工程师评审的工作量就大大降低了,初级工程师能够迅速成长,企业可以通过校招实现人才梯队建设,实现降本增效。
学习极狐GitLab 的相关资料:
- 极狐GitLab 官网:https://gitlab.cn
- 极狐GitLab 官网文档:https://docs.gitlab.cn
- 极狐GitLab 论坛:https://forum.gitlab.cn/
- 极狐GitLab 安装配置:https://gitlab.cn/install
搜索【极狐GitLab】公众号,后台输入加群,备注gitlab,即可加入官方微信技术交流群。