首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【方向盘】IDEA的代码审查能力,来保证代码质量

【方向盘】IDEA的代码审查能力,来保证代码质量

作者头像
YourBatman
发布2022-09-16 10:13:05
1.3K0
发布2022-09-16 10:13:05
举报
文章被收录于专栏:BAT的乌托邦BAT的乌托邦

你好,这里是Java方向盘,我是方向盘(YourBatman),坐稳扶好,开始发车。

Title

Link

所属专栏

【方向盘】-IntelliJ IDEA

源代码

https://github.com/yourbatman/FXP-java-ee

程序员专用网盘公益上线啦,注册送1G超小容量,帮你实践做减法

https://wangpan.yourbatman.cn

Java开发软件包(Mac)

https://wangpan.yourbatman.cn/s/rEH0 提取码:javakit

女娲工程

http://152.136.106.14:8761

版本约定

[Mac OS 12.5],[IntelliJ IDEA 2021.2]

📚前言

上篇文章【方同学】是如何高效的使用IntelliJ IDEA 再一次勾起了较多读者对IDEA的兴趣,让我没想到的是一个小小的IDE开发工具而已,甚至都与Java语言没有直接关系,竟然也能写成一个系列。也许它代表着一种态度,一种程序员对工具使用的态度,not only code。

在这里插入图片描述
在这里插入图片描述

认识我的朋友可能比较清楚,笔者近些年一直从事和带领团队从事基础架构、中间件的研发工作。众所周知,写基建代码与业务开发有不同,它对代码质量、可靠性、性能、软件长久生命力均会有更高要求,毕竟基础不牢,地动山摇是共识。

本文就为你分享,笔者是如何借助IDEA自带的一些能力,对书写的代码进行(质量)审查的。工具的出生就为提效,熟练使用对个人甚至团队都有好处。

✍正文

在这里插入图片描述
在这里插入图片描述

提高代码质量的手段

代码作为软件的载体,是软件最为重要的组成部分。所以一个软件的质量如何,很大程度上是由代码质量决定的。也许在写几句hello world的时候软件质量尚可,但随着时间的推移、代码量的增加、需求的多变、团队协作日益复杂等因素的加入,往往在质量这条路上渐行渐远。蓦然回首,是不是感觉自己已忘初心,但依旧砥砺前行呢?

殊不知,代码并非编译通过,万事大吉,编译只是最最最最基础的保证而已。

大部分程序员是期望写出高质量的代码,对自己的代码质量要求是较高追求的。可一旦遇到赶工压力,尤其是在 deadline 之前,就很可能会把完成度很低的代码交出去,心想“反正有人给我检查,到时候再说吧”。但是,这些代码就好比是一台“行走的Bug制造机”,后患无穷。作为你的领导看到这样的代码上线,可谓慌得一批

既然赶工期、deadline这种“事件”无法避免,并且团队内程序员的水平/追求也高低不一,怎么办?随着软件行业的发展,出现了一批又一批的方法论、手段、工具用于整体提升软件质量,下面按照离程序员由近及远的顺序从两个方面简要了解一下。

✌程序员侧 - 最行之有效

代码是由程序员写的,最了解它的莫过于程序员自己。因此在本侧若能够做好质量把控关,是最行之有效的。正所谓在离“用户”最近的地方发现问题、解决问题往往效率最高的。

当然,从品控的方式方法上,自然也有成套的解决方案。处在程序员侧,有个非常大的优势:可借助IDE提供的“超强”能力,高效的进行代码审查工作。

IDE通用代码审查

什么叫通用代码审查?说白了就是关乎代码格式、方法/变量命名、基础语法合理性等等,一般的IDE都有这样的能力。

比如本文接下来将要讲的IDEA代码审查能力,就是提供的这方面的能力。

静态代码检测

借助checkstyle、p3c这类工具,对代码进行静态检测,能够提早发现很多运行期潜在的bug/风险点。静态代码检测对Java这种静态语言效果极佳,这也是静态语言的巨大优势之一:健壮性强。它对动态语言(如Python、PHP等)有点无能为力,效果欠佳。

拿Java举例,像Long.equals(Integer)这种无数人踩过的坑,通过静态代码检测就可以规避。另外,代码规范、格式等等都可以通过静态代码检测来实现很好的约束。值得注意的是,别看只是格式,这也很重要,很多时候程序出现bug,代码格式才是原罪。对于一个普通的程序员来讲,第一任务是要写出人能看得懂的代码,其次才是机器

单元测试

单元测试(UT),是指对软件中的最小可测试单元进行检查和验证。那什么叫最小可测单元呢?以Java语言为例,最小可测单元就是一个方法/函数。

写出一个可单测的代码其实是非常困难的,有工作经验的程序员或多或少经历过“拒绝写单元测试”的情况,根据我的经验,出现这种畏难情绪的根本原因是:不会写,没有可“抄”的,毕竟ctrl c + ctrl v才是第一生产力嘛,让自己去搞,没有的事。

在这里插入图片描述
在这里插入图片描述

国内的开发环境尚处在初、中期,普遍对单元测试的重视度不够。主要原因我认为有两点:

  1. 写好UT需要花费一定时间,而国内行情一般“工期紧”,较少做中长期规划
  2. 业务逻辑代码分层不够、耦合严重,导致写UT代码时工作量剧增,近乎无法单测

久而久之,积重难返。等到最后上级领导说要关注代码质量要求写单元测试的时候,受到的阻碍情绪将会是空前的,然后就陷入了恶性循环。

关于UT,开发者公认的事实:UT是确保代码健壮性极其有效的手段。根据现实情况,我本人对UT的态度是:尽量不要自顶向下的强推,而应

单元测试其实是一门严重被低估的“学问”,经常是领导大嘴一巴说要写,至于怎么写可能领导自己也不知道,甚至可能从来没写过。正所谓己所不欲勿施于人,我认为UT覆盖率问题应该上升到方案级别,而不只是只有一个字:写。

畏难情绪是顺人性的,是天性的表现。在代码的世界了,不会才觉得难,才会抗拒。毕竟写UT远没有写业务代码来得那么的“轻松”。针对此问题,可采用榜样的力量逐步疏通、渗透。对于个人来讲,应该迎难而上,追求更高质量的代码。

✌CI/CD侧 - 统一卡点

虽然说在程序员侧进行一些质量把控环节效果是最佳的,但此方式高度依赖程序员本身的综合水平和自觉性,可靠性是明显不够的。因此在实际生产上,需要辅助一些集中式卡点行为来做保障。

Code Review

对每个提测的分支,(至少在上线前)必须要进行CR(code review)环节。此环节比较出名的工具有:Gitlab(商业版)、Fisheye等

集中式静态代码检测

简而言之,就是将你本地静态代码监测的能力搬到云端,进行集中检测。一般可分为全量检测和增量检测。此环节比较出名的工具有:sonar、cubase等

集成测试

对多个系统进行集成测试、边界测试。该环节一般属于QA人工介入阶段,和业务逻辑强关联,是最为耗时的阶段之一。

持续集成流水线工具

在软件发布阶段,也会有一些相应的审核、卡点机制。此环节比较出名的工具有:jenkins、hudson等

借助IDEA审查你的代码

做个小调查:有多少同学从来没有使用过甚至从来没有看过IDEA的code菜单呢?

在这里插入图片描述
在这里插入图片描述

不管你看没看过,应该直接或间接的使用过其相关功能。比如这个Generate…

在这里插入图片描述
在这里插入图片描述

自动为JavaBean生成get/set方法、构造器、hashCode()、toString()等方法。也许你会说现在用lombok基本不使用它了,对,这是事实。但是,再不济,像Override Methods、Implement Methods这些功能都用过吧,毕竟我不信方法复写、方法实现这种模板代码你会一字一句手敲~

在这里插入图片描述
在这里插入图片描述

那么,接下来重点向你介绍code菜单里面的代码审查功能,顺带也分享笔者是如何利用IDEA提供的这些能力去帮助自己、甚至帮助团队提高代码质量、保证代码质量的。

代码审查相关功能在Code菜单这里(如下图)。两条灰色的线条将这几项归为一类:

在这里插入图片描述
在这里插入图片描述

以这段示例代码为例审查:

package cn.yourbatman;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;

@SpringBootApplication
public class Application {

    private String name;
    private String agee;

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    public boolean fun1(boolean bool) {
        return bool ? true : false;
    }

    public String fun2(String s) {
        return s.toString();
    }
}

✌Inspect Code…审查你的代码

Inspect:检查、审查。

在这里插入图片描述
在这里插入图片描述

点击OK运行,在problem视窗里可以看到“有问题”的代码:

在这里插入图片描述
在这里插入图片描述

经过审查,本工程里的“坏味道”代码就在problem视窗指出了。如图,IDEA针对性的提供了便捷的一键处理按钮,你可以快速处理,非常智能化和人性化有木有。

到这,你可能不禁想问:IDEA怎么知道这是坏味道代码的?遵照什么规则?显然,一切都是“有法可依”,它在这:设置 -> Editor -> Inspections

在这里插入图片描述
在这里插入图片描述

一般来讲,Inspections保持默认即可。但我会把拼写检查(毕竟英语并非咱母语,偶尔单词拼写错误甚至用拼音是可以原谅的,关掉它以节约点性能开销嘛)相关的关掉:Spelling、Typo

注意:Inspect Code只会帮你把坏味道代码“揪出来”,改还是不改的决策权还在于你自己。

✌Code Cleanup…精炼你的代码

不同于Inspect Code帮你指出坏味道的代码,它比较“狠”,会拿你的代码直接开刀。如下:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

执行该动作不需要同意,IDEA会直接动手修改你的代码。

当然喽,你duck不必担心它改乱了:它有且只做同等语义的替换,使得代码组织起来更优雅,绝不会影响到程序的正确执行。

Tips:有时候人容易理解和优雅写法是相冲的,这个时候你就得三思是否有必要执行此功能喽

✌Analyze Code…分析你的代码

它是一个功能集的统称。

在这里插入图片描述
在这里插入图片描述

:为何这些功能被放在二级目录下? :相对来说不太常用。这是基本的产品设计逻辑嘛:常用的放在一级目录,不常用的功能下层

Silent Code Cleanup

静悄悄的完成精炼你的代码操作,执行结果同Code Cleanup。 我的使用情况:基本不用

Run Inspection by name

如果觉得每次运行Inspect Code把所有的规则都走一遍太慢了,那么就可以使用此功能:只运行指定名称的规则

在这里插入图片描述
在这里插入图片描述

我的使用情况:基本不用。现在微服务开发模式,每个应用“体积”都很小,1s和0.5s的差异who care呢

View Offline Inspection Results

离线查看代码分析的结果。此功能的存在,是因为problem结果是可以导出的:

在这里插入图片描述
在这里插入图片描述

我的使用情况:只使用过几次。那是我要给团队做分享,所以通过导出文件来保留“现场”,从而在分享时在导入方便说明问题。

Infer Nullify

Infer:推断。此功能作用是在方法参数、返回值里帮你推断:哪些必须不能为null、哪些可以为null

在这里插入图片描述
在这里插入图片描述

以这个方法为例:

public String fun2(String s) {
    return s.toString();
}

内部调用了s的toString()方法,因此s肯定不能为null,进而推断出返回值也就不可能为null。因此,运行IDEA的此功能后,代码会被改成这样:方法签名的语义更加明确

public @NotNull String fun2(@NotNull String s) {
    return s.toString();
}

值得注意的是,注解它只用于表达语义,运行期无任何作用。另外,该功能要正常执行需要此依赖包才行:

在这里插入图片描述
在这里插入图片描述

若没有此依赖,执行时会弹出提示你添加依赖:

在这里插入图片描述
在这里插入图片描述

此时点击ok就能自动帮你把依赖加上了,非常方便。

Tips:点ok后此框不会消失,但实际依赖已经加上,不用重复点哦,否则会重复添加依赖的。这是IDEA的一个小bug

我的使用情况:从未使用过。因为我习惯使用功能更强大的Bean Validation,不仅语义明确,runtime时期也会生效。

Locate Duplicate

顾名思义,帮你定位重复代码,以便做封装、抽象。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

我的使用情况:在review组员代码的时候,用得较多。查找结果还是蛮有参考价值的,推荐使用

Dependencies…

IDEA在Project视窗,把依赖统一全部放在了External Libraries里,就像这样:

在这里插入图片描述
在这里插入图片描述

若是一个多模块的项目,此时只想查看某1个模块的依赖的话,通过External Libraries就无能为力了。这个时候一般有两种办法来查看具体某个模块的依赖:

  1. 通过Maven视窗查看
在这里插入图片描述
在这里插入图片描述

这种方式,它对于中小型服务可以解决绝大部分问题,因为依赖不多不难定位。但是它的明显缺点是:不够直观。并不能一眼看出来模块的最终依赖。比如某个依赖是间接依赖进来的,这时通过这种方式就非常不直观了;又比如多个地方引入了a.jar,也就无法一眼看出来最终使用的是哪个版本的a.jar啦

  1. 通过本处的Dependencies功能
在这里插入图片描述
在这里插入图片描述

这个依赖分析功能非常、非常、非常强大。它不仅仅能帮你分析出每个类(粒度非常细)依赖哪些库,还能分析出依赖了本project的哪些类。该功能在阅读他人代码(or开源代码)时非常有用

我的使用情况:较为频繁。我在阅读开源代码的时候使用较多,通过依赖分析,能够较快的掌握作者的整体设计意图,具有更全面的视野。

Backward Dependencies…

上面功能是查看自己依赖了谁,该功能表示谁依赖了自己

Module、Cycle Dependencies…

用于分析本工程的模块粒度的依赖关系,是否存在循环依赖等,使用起来比较简单,不详细解释了。

✌Analyze Stack Trace or Thread Dump…

又一神器,这个工具我可太爱了。字面含义:分析堆栈,或者内存dump

例如有这么一个场景:线上服务出bug抛了异常,日志文件里留下的是堆栈信息,面对这个堆栈信息你如何快速定位到问题代码呢?

在这里插入图片描述
在这里插入图片描述

这个时候一般是在这个黑框里逐行的找,找到“熟悉”的一行(有行号),然后返回到IDEA里找到对应的类,问题定位路径其实还蛮长的。

其实duck不必这么麻烦,IDEA为咱们提供了非常好用的分析工具,你只需要:

  1. 复制堆栈信息
  2. 在IDEA里Code -> Analyze Stack Trace or Thread Dump打开分析窗口
在这里插入图片描述
在这里插入图片描述

点击ok,控制台里就能显示出堆栈信息,和本地调试一模一样的效果了有木有

在这里插入图片描述
在这里插入图片描述

这里我演示的是该功能的最简单使用场景,除了分析这种简单的堆栈外,还可以分析dump文件,还可以自定义分析器(比如class文件混淆、加密了)等等,最终目的就是让开发者有种本地化“分析线上问题”的体验。

关于本功能的更多使用方式,感兴趣的同学在真正用起来的时,可自己发现。

✍总结

本文以IDEA作为着力点,我主要想输出的两个观点是:

  1. 单元测试被低估了
  2. IDEA的代码审查能力被低估了

作为一个开发者,很多时候人与人的差异体现在知道的多与少、知道和不知道上,毕竟大家的教育背景、智商大都差异不大,会得多一点并且让这些能支撑自己总是好的。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 📚前言
  • ✍正文
    • 提高代码质量的手段
      • ✌程序员侧 - 最行之有效
      • ✌CI/CD侧 - 统一卡点
    • 借助IDEA审查你的代码
      • ✌Inspect Code…审查你的代码
      • ✌Code Cleanup…精炼你的代码
      • ✌Analyze Code…分析你的代码
      • ✌Analyze Stack Trace or Thread Dump…
  • ✍总结
相关产品与服务
持续集成
CODING 持续集成(CODING Continuous Integration,CODING-CI)全面兼容 Jenkins 的持续集成服务,支持 Java、Python、NodeJS 等所有主流语言,并且支持 Docker 镜像的构建。图形化编排,高配集群多 Job 并行构建全面提速您的构建任务。支持主流的 Git 代码仓库,包括 CODING 代码托管、GitHub、GitLab 等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档