DevOps落地笔记-06|代码预检查:提高入库代码质量的神兵利器

上一讲主要介绍了从软件开发的需求阶段就要关注非功能需求以及如何有效关注非功能需求,希望你对非功能需求引起重视,对软件的质量引起重视。除了对非功能需求的关注,代码本身的质量也是决定软件质量的关键因素,比如:代码的漏洞、复杂度、Bug 等。这些问题都是导致软件可维护性差,软件不可用的罪魁祸首。越是提前发现这些问题,修复的成本就越低,出于这个原因,在 DevOps 中提倡检查前置。今天要介绍的内容——代码预检查,就是让我们在代码进入代码库之前进行检查,阻止有问题的代码合入代码库。

什么是代码预检查
代码预检查就是在代码提交到代码库之前对代码进行检查,包括静态检查、Code Review、测试、编译等多种方式。主要目的就是保证提交到代码库的代码的质量。

我先介绍一下强调提交到代码库的代码的质量的原因:版本控制系统除了可以维护软件每次修改的完整历史,还有一个非常重要的用途,让团队一起开发软件的不同部分。它是团队高效协作的工具。毕竟,一旦低质量的代码提交到代码库,那么就会更新到团队每个成员的本地仓库,低质量的代码不仅会导致后续维护困难,也为软件的健壮性埋下了祸根。 因此,将低质量代码直接拦在门外,然后通过代码检查等方式指导开发人员哪里有问题,如何修改,开发人员按照提示进行修改,直到满足要求。

目前版本控制系统都是采用分布式版本控制系统,如 Git。根据 Git 的架构设计,可以在下图中 ①②③④ 进行代码预检查。如下图所示,下半部分是指开发人员本地仓库,上半部分是指远程仓库。这几个检查点是:

①本地检查, 一般是在开发人员本地开发空间进行检查,比如 IDE 的插件检查,本地编译时检查;

②本地提交, 一般当代码提交到本地仓库时进行检查,可以使用 Git 的客户端 Hook,如 pre-commit、pre-merge 进行检查;

③远程提交, 一般当代码提交到远程仓库时进行检查,这时会先提交到临时分支,当评审人同意后再合入代码库,比如 Gerrit;

④分支合并, 一般当代码从一个分支合并到另一个分支时进行检查,评审人进行 Code Review,同意之后再合入另一个分支,常见的分支合并方式有 MR(Merge Request)和 PR(Pull Request)两种。
在这里插入图片描述
这几个检查点的使用场景、成本和收益各不相同。每家企业在落地代码预检查的时候也会根据内部情况各有侧重。后面会详细介绍每一种检查的优劣。

为什么要做代码预检查
前面提到代码预检查的主要目的就是保证提交到代码库的代码的质量。在当今快速发展的数字经济中,没有一个企业不是通过软件来支撑业务的。**软件是业务发展的核心,**因此软件的整体质量非常重要。高质量的软件可以带来客户满意度、用户量和收入,而更好的设计可以使组织更轻松的赢得市场。

举个简单的例子。共享单车我们都骑过,共享单车刚出来的时候,市场竞争非常激烈,市场上瞬间就出现了五颜六色的单车。作为用户来说,你喜欢骑哪种颜色的单车?首先,自行车得好骑(硬件质量好),然后开锁要方便快捷(软件质量好)。通过这个例子,不难看出,软件和硬件的质量决定用户量的多少,用户量的多少决定了企业能否存活下去。

这里,你可能会说,作为初创公司,市场机会稍纵即逝,产品投放市场的时间更重要。重视产品投放时间这个观点本身没问题,但如果通过牺牲软件质量,来节约时间,这叫欠下了技术债。具体问题在下一课时我会为你细致说明。在这里你要知道的是,欠下的技术债是要还的。 技术债就和欠的银行贷款一样,如果不及时还,债务会越滚越大。直到公司最后不堪重负,产品下架,公司倒闭。

因此,当我们面临稍纵即逝的市场机会而对软件交付充满时间压力的时候,可以临时适当降低对软件质量的标准。但是,从长远考虑,我们绝对要重视软件质量。软件是由代码编写而成的,代码的质量是软件质量的决定性因素,因此,重视软件质量,其中的核心就是要重视代码的质量。总结一下,代码的质量的重要性主要有三个原因。

& 可读性:代码不只是给机器理解的,也是给人看的。要能够使团队中的每个人都能容易的阅读和理解代码。

& 可维护性:当维护和测试高质量的代码时更加容易、安全和省时,且不易出问题。

& 减低技术债务:高质量的代码设计良好,技术债少,开发人员无须花费大量的时间修复代码的问题和重构,因此,可以加快软件开发的进度。新团队成员容易理解代码,更容易加入项目。

高质量的代码是高质量软件的基础,不管是什么业务,高质量的软件都可以使你免去生产问题带来的烦恼。

代码预检查实践有哪些

质量不是一种行为,它是一种习惯
——亚里士多德

虽然代码质量对于现在的软件项目非常重要,但绝不要搞“代码质量月,利用一个月的时间,将代码质量提高到百分之百,消灭所有的 Bug”这样的活动。《丰田套路:转变我们对领导力与管理的认知》一书中介绍过“改善套路”:以循环的方式不断改进。我们也可以利用循环、培养等手段,将提高代码质量的活动融入每个迭代中,形成一种习惯。下面介绍几种能够提高代码质量的预检查的工具和实践。

本地检查

本地检查是指在开发人员本地执行的检查,比如 IDE 或命令行的方式。本地检查有优点也有缺点。

优点

& 按照检查前置的原则,本地检查的时机是最合适的,发现问题和修复问题的成本是最低的;

& 因为是在本地执行,执行检查的效率最快。

缺点

& 需要开发人员具有很高的自觉性。

本地检查常用的检查工具和实践有:

& IDE 插件:SonarLint、FindBugs、CheckStyle、PMD、阿里规范插件等,可以检查代码的编码风格,坏味道,漏洞等

& 本地构建:maven 编译、gradle 编译,可以检查代码语法问题,是否能够编译过。

& 本地测试:单元测试,可以检查代码的逻辑问题。

下图是 IDEA 中 SonarLint 实时检查单个文件的结果。开发人员一边写代码,一边做检查,实时检查增强了反馈的时效性,是一种不错的实践。
在这里插入图片描述
本地提交检查

本地提交检查是指在本地执行git commit的时候进行的检查,这种检查方式同样有优点和缺点。

优点:

& 检查的时机适中;

& 检查的效率较高;

& 基于 Git 的 Hook 机制,在每次提交时运行 Hook,自动识别代码中的简单问题,代码审阅者只专注于代码逻辑和系统结构,避免因为琐碎的样式问题而浪费时间。

缺点:

& 本地提交对提交速度要求很高,只能进行省时的静态检查,如代码风格等;

& 客户端的 Hook,因为是在开发人员本地,并未实现完全“强制”检查;

& 同样依赖开发人员的自觉性。

使用 Git 的 pre-commit 钩子能够在提交时检查代码问题。但随着我们创建的项目越来越多,使用的编程语言也各不相同,在不同的代码库之间共享 pre-commit 的钩子脚本是一件非常痛苦的事情。需要在每个项目之间拷贝脚本,还需要手动更改脚本才能适用于不同的项目结构。

这里介绍一个 pre-commit 的多语言包管理工具——pre-commit。在每个代码库中,只需要指定所需要的钩子列表,在每次提交之前,pre-commit 就会安装并执行任何语言的钩子。

pre-commit 安装教程可以参考官网。主要配置文件如下,在每个代码库中都维护该配置文件,指定需要钩子的代码库、版本以及钩子的 ID。这样就可以像代码一样管理 pre-commit 的钩子,还可以进行版本控制。

[root@localhost devops]# cat .pre-commit-config.yaml 
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.4.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-yaml
    -   id: check-added-large-files

在每次提交时,会按照配置文件中指定的钩子进行检查,有些钩子还能自动处理代码中的问题,如:去除空格。当钩子的退出码为非 0 时,表示 Failed。具体的执行结果如下:

[root@localhost devops]# git commit -m "fixed #123 issue"
Trim Trailing Whitespace.................................................Failed
- hook id: trailing-whitespace
- exit code: 1
- files were modified by this hook

Fixing Hello.java

Fix End of Files...........................................Passed
Check Yaml.................................................Passed
Check for added large files................................Passed

远程提交检查

远程提交检查是指在本地执行git push提交到远程仓库时执行的检查,远程提交检查同样有优点和缺点。

优点:

& 能够进行较为深层次的动态检查,比如漏洞、Bug,检查的效果较好;

& 能够做到强制检查,保证任何人提交的代码都是高质量的;

& 代码提交后并未直接提交到代码库中,可以加入人工评审环节,可以检查代码的业务逻辑和架构设计等较复杂问题;

& 可以控制每次提交的代码质量。

缺点:

& 检查的时机靠后,反馈周期较长;

& 需要搭建代码检查服务器;

& 维护成本较高;

& 每次提交都检查,会拖慢团队的开发节奏。

常用的检查工具和实践有下面这些。

& 代码检查

需要搭建代码检查服务器,比如 SonarQube。当代码提交后,自动触发代码检查并根据检查结果决定是否合入代码库。为了避免历史债务对问题修复的影响,可以考虑使用增量检查,只检查本次提交修改的文件,这样就不会因为问题太多打消提交者解决问题的积极性。在之前的实践中,我们每次提交时进行增量检查,控制新增代码的质量。在发版时,对全量代码进行检查,作为系统发版的质量关卡。质量分值每月递增,从而达到持续提升代码质量的目的。

& 人工评审

是指当代码提交后,由团队中高级别人员对代码进行评审。评审人会检查本次变更是否符合编码规范以及是否采用了最佳的技术解决方案,并在评审页面以行间评论的方式发表评审意见,提交人根据评审意见进行修改,直到满足评审人的要求。目前常用的代码评审工具如 Gerrit,通过与Jenkins 集成可以实现机器检查和人工评审的同时审核,这也是目前企业里用得最多的实践。下图是查看本次变更内容的 Gerrit 评审页面。
在这里插入图片描述
& 自动化测试

上面两个检查具有一定的局限性。代码检查能够发现代码问题,但不能发现功能性问题。人工检查对评审人的要求较高。比较有效的做法是使用 JaCoCo 检测单元测试覆盖率,或者执行一定范围的集成测试。建议选择系统的核心场景、10 分钟以内能够执行完成的测试用例。

分支合并检查

分支合并检查是指在远程仓库里执行分支合并的时候进行的检查,分支合并检查的优点和缺点如下。

优点:

& 每次在分支合入时进行检查,既能控制合入其他分支的代码质量,又不会对开发节奏造成影响;

& 分支合并时一般表示一个功能和问题开发完成,可以有相对充足的时间执行较为深层次的动态检查,比如漏洞,Bug 等;

& 可以设置强制检查,保证合入分支的代码是高质量的;

& 可以做 Code Review,评审人一次性评审完整的功能代码(不推荐长期分支,大功能开发);

& 代码托管平台支持,如 GitHub、GitLab。

缺点:

& 检查的时机靠后,反馈周期较长。

参用的检查工具和实践:

& GitHub 的 PR

当进行分支合并时,提交人申请 Pull Request,目标分支通过 Pull 的方式从提交分支上更新代码。在这个 PR 申请中,评审人进行 Code Review,同时触发 GitHub Action 执行自动化构建、测试、代码扫描等。

& GitLab 的 MR

当进行分支合并时,提交人申请 Merge Request,目标分支通过 Merge 的方式从提交分支上更新代码。在这个 MR 申请中,评审人进行 Code Review,同时触发 GitLab CI/CD pipeline 进行自动化构建,测试,环境部署等。下图是 GitLab 中在 Code Review 时添加的评论。
在这里插入图片描述
总结

本课时开头提到代码的质量是软件质量的决定性因素,要尽早得发现代码中的问题,降低解决成本。引申出通过代码预检查的方法,在代码未合入代码库之前进行代码检查。从代码在本地开发到合入代码库之间,有多个检查点可以辅助开发人员进行代码检查,每个检查点的时机不同,执行的效率和效果也不同。根据以往经验,大多数都会在服务器端进行强制检查,收集代码质量的数据,通过代码质量度量指标,指导改进。

低质量的代码会大幅增加维护成本和时间成本,不仅决定了软件的成功和失败,也会进而决定了企业的成功和失败。代码质量受到越来越多企业的重视。有些企业把代码质量作为软件能否发布上线的重要标准。

就像开头提到,代码质量是一种习惯,是要融入每个开发人员的日常工作中,在开发的过程中就关注代码的质量。因此,对于软件从业人员来说,我特别推荐使用 “本地检查” 的方法随时随地的提示、指导我们开发高质量的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/363465.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker中配置MySql环境

目录 一、简单安装 1. 首先从Docker Hub中拉取镜像 2. 启动尝试创建MySQL容器,并设置挂载卷。 3. 查看mysql8这个容器是否启动成功 4. 如果已经成功启动,进入容器中简单测试 4.1 进入容器 4.2 登录mysql中 4.3 进行简单添加查找测试 二、主从复…

判断当前设备是不是安卓或者IOS?

代码(重要点): 当前文件要是 xxx.js文件,就需要写好代码后调用才会执行: // 判断是不是安卓 const isAndroid () > {return /android/.test(navigator.userAgent.toLowerCase()); }// 判断是不是ios const isIOS () > {return /iphone|ipad|ipod/.test(navigator.use…

【操作系统·考研】文件系统

1.概述 文件系统(File System)提供高效和便捷的磁盘访问,以便允许存储、定位、提取数据。 严格来说,VFS并不是一种实际的FS,它只存在于内存中,不存在与任何外存空间中。 VFS在系统启动时建立,在系统关闭时消亡。 2.结…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TextClock组件

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之TextClock组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、TextClock组件 TextClock组件通过文本将当前系统时间显示在设备上。支持不同…

VMware vCenter告警:vSphere UI运行状况警报

vSphere UI运行状况警报 不会详细显示告警的具体内容,需要我们自己进一步确认告警原因。 vSphere UI运行状况警报是一种监控工具,用于检测vSphere环境中的潜在问题。当警报触发时,通常表示系统遇到了影响性能或可用性的问题。解决vSphere UI…

2024斋月大促提前,跨境卖家请收好这份准备指南与大促策略

市场覆盖西欧、中东、东南亚、北非地区的跨境电商卖家注意了,2024年的斋月即将开启,较往年日期,今年提前了10天左右,斋月的第一天预测在3月11日星期一到来。 根据Google搜索数据可知,目前已经进入高频“斋月”搜索期&…

nginx刷新404问题

问题分析 在配置好 nginx 转发之后,发现页面能正常打开,但只要按 F5 刷新之后就会报 404。这是因为 web 单页面开发模式,只有一个 index.html 入口,其他路径是前端路由去跳转的,nginx 没有对应这个路径,然后…

安装GPU版本Pytorch(全网最详细过程)

目录 一、前言 二、安装CUDA 三、安装cuDNN 四、安装Anacanda 五、安装pytorch 六、总结 一、前言 最近因为需要安装GPU版本的Pytorch,所以自己在安装过程中也是想着写一篇博客,把整个过程记录下来,在整个过程中也遇到了不少的问题&a…

大数据开发之离线数仓项目(用户行为采集平台)(可面试使用)

第 1 章:数据仓库概念 数据仓库,是为企业指定决策,提供数据支持的,可以帮助企业,改进业务流程、提高产品质量等。 数据仓库的输入数据通常包括:业务数据、用户行为数据和爬虫数据等。 业务数据&#xff1a…

【Linux C | I/O模型】IO复用 | select、pselect函数详解(看完就会用了)

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀 🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C、数据结构、音视频🍭 🤣本文内容🤣&a…

【Eclipse平台】2 Eclipse Workbench工作台介绍

Eclipse Workbench工作台介绍 本文介绍Eclipse工作台Workbench。 当工作台启动时,首先看到的是一个对话框,该对话框允许我们选择工作区的位置。工作区是存储工作的目录。现在,只需单击“确定”即可选择默认位置。 选择工作区位置后&#x…

LVGL部件4

一.列表部件 1.知识概览 2.函数接口 1.lv_list_add_btn lv_list_add_btn 是 LittlevGL(LVGL)图形库中的一个函数,用于向列表(list)对象中添加一个按钮(button)。 函数原型为:lv_ob…

数据库复试-SQL数据定义与数据查询语句

数据库复试-SQL数据定义与数据查询语句 使用mysql数据库代替之前的sqlserver (完全使用命令行进行操作) 一:登录数据库登录与创建 mysql -uroot -p 123456 CREATE TABLE Student(Sno CHAR(9) PRIMARY KEY, /*主键约束*/Sname CHAR(20) UNIQUE, /*唯一值*/Ssex …

关于标准那些事——第十篇 符号标准

“符号”几乎是无处不在的,无论是生活、学习还是工作中,每个人每天都会碰到,只是我们没有意识到她的存在。正因如此,符号标准在不同场景、不同领域都发挥着统一认知,规范行为的作用,其简约、易用和一致性的…

分布式事务(四)——TCC补偿模式解决方案

系列目录: 《分布式事务(一)—— 事务的基本概念》 《分布式事务(二)—— CAP和Base理论》 《分布式事务(三)—— 两阶段提交解决方案(2PC)》 一、常见分布式事务解决…

轻型民用无人机驾驶航空器安全操控——理论考试多旋翼部分笔记

今天已经可以在线考取轻型民用无人机驾驶航空器执照了,所以我也在在线观看完视频之后整理了如下的知识点,所有知识点全部来自UOM平台。 目录 航空器知识 (1)多旋翼民用无人驾驶航空器螺旋桨的作用 (2&#x…

仰暮计划|“从米票、肉票、糖果票到肥皂票、煤票、棉花票等,生活里头的方方面面都能用粮票买到”

口述人:牛翠英(女) 整理人:霍芝冉 口述人基本信息:现68岁,河南省安阳市北关区霍家村人,现居河南安阳市区。 奶奶一生辛劳,操持家务;亲眼见证了时代变迁,社会发展,…

小米商城服务治理之客户端熔断器(Google SRE客户端熔断器)

目录 前言 一、什么是Google SRE熔断器 二、Google SRE 熔断器的工作流程: 三、客户端熔断器 (google SRE 熔断器) golang GRPC 实现 四、客户端熔断器 (google SRE 熔断器) golang GRPC单元测试 大家可以关注个人博客:xingxing – Web Developer …

【笔试常见易错选择题01】else、表达式、二维数组、%m.ns、%m.nf、常量指针和指针常量、宏定义、传参、数组越界、位段

1. 下列main()函数执行后的结果为&#xff08;&#xff09; int func(){ int i, j, k 0; for(i 0, j -1;j 0;i, j){ k; } return k; } int main(){cout << (func());return 0; }A. -1 B. 0 C. 1 D. 2 判断为赋值语句&#xff0c;j等于0 0为假不进循环 选B. 2. 下面程…

【日常总结】宝塔中 Gitlab服务器 forbidden

一、场景 二、问题 三、原因 四、解决方案 五、实战 Stage 1&#xff1a;打开 /etc/gitlab/gitlab.rb&#xff0c;并编辑 Stage 2&#xff1a;重启gitlab服务 Stage 3&#xff1a;测试&#xff08;打开girlab网页&#xff09; 六、后续 一、场景 公司更换新电脑 服务…