当前位置:网站首页>【方向盘】IDEA的代码审查能力,来保证代码质量
【方向盘】IDEA的代码审查能力,来保证代码质量
2022-07-24 06:04:00 【方向盘(YourBatman)】
本文已被https://yourbatman.cn收录;女娲Knife-Initializr工程可公开访问啦;程序员专用网盘https://wangpan.yourbatman.cn;技术专栏源代码大本营:https://github.com/yourbatman/tech-column-learning;公号后台回复“专栏列表”获取全部小而美的原创技术专栏
你好,这里是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才是第一生产力嘛,让自己去搞,没有的事。
国内的开发环境尚处在初、中期,普遍对单元测试的重视度不够。主要原因我认为有两点:
- 写好UT需要花费一定时间,而国内行情一般“工期紧”,较少做中长期规划
- 业务逻辑代码分层不够、耦合严重,导致写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就无能为力了。这个时候一般有两种办法来查看具体某个模块的依赖:
- 通过Maven视窗查看

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

这个依赖分析功能非常、非常、非常强大。它不仅仅能帮你分析出每个类(粒度非常细)依赖哪些库,还能分析出依赖了本project的哪些类。该功能在阅读他人代码(or开源代码)时非常有用
我的使用情况:较为频繁。我在阅读开源代码的时候使用较多,通过依赖分析,能够较快的掌握作者的整体设计意图,具有更全面的视野。
Backward Dependencies…
上面功能是查看自己依赖了谁,该功能表示谁依赖了自己。
Module、Cycle Dependencies…
用于分析本工程的模块粒度的依赖关系,是否存在循环依赖等,使用起来比较简单,不详细解释了。
Analyze Stack Trace or Thread Dump…
又一神器,这个工具我可太爱了。字面含义:分析堆栈,或者内存dump。
例如有这么一个场景:线上服务出bug抛了异常,日志文件里留下的是堆栈信息,面对这个堆栈信息你如何快速定位到问题代码呢?
这个时候一般是在这个黑框里逐行的找,找到“熟悉”的一行(有行号),然后返回到IDEA里找到对应的类,问题定位路径其实还蛮长的。
其实duck不必这么麻烦,IDEA为咱们提供了非常好用的分析工具,你只需要:
- 复制堆栈信息
- 在IDEA里Code -> Analyze Stack Trace or Thread Dump打开分析窗口

点击ok,控制台里就能显示出堆栈信息,和本地调试一模一样的效果了有木有
这里我演示的是该功能的最简单使用场景,除了分析这种简单的堆栈外,还可以分析dump文件,还可以自定义分析器(比如class文件混淆、加密了)等等,最终目的就是让开发者有种本地化“分析线上问题”的体验。
关于本功能的更多使用方式,感兴趣的同学在真正用起来的时,可自己发现。
总结
本文以IDEA作为着力点,我主要想输出的两个观点是:
- 单元测试被低估了
- IDEA的代码审查能力被低估了
作为一个开发者,很多时候人与人的差异体现在知道的多与少、知道和不知道上,毕竟大家的教育背景、智商大都差异不大,会得多一点并且让这些能支撑自己总是好的。
关于IDEA你还有哪些故事呢?你还想知道哪些故事呢?期待你的分享呀~
推荐阅读
- 【方同学】是如何高效的使用IntelliJ IDEA
- 【方向盘】IntelliJ IDEA 2020.2正式发布,诸多亮点总有几款能助你提效
- 【方向盘】IntelliJ IDEA 2020.1正式发布,你要的Almost都在这!
- 【方同学】女娲Knife-Initializr工程可公开访问啦
- 【方向盘】轰动从未停止,感动从未消失。他,是周杰伦
- 【方向盘】阿里巴巴入选的JCP最高执行委员会,何方神圣?

我是方向盘(YourBatman):前25年不会写Hallo World、早已毕业的大龄程序员。高中时期《梦幻西游》骨灰玩家,网瘾失足、清考、延期毕业、房产中介、保险销售、送外卖…是我不可抹灭的黑标签
- 2013.07 清考、毕业答辩3次未通过、延期毕业
- 2013.08-2014.07 宁夏中介公司卖二手房1年,毕业后第1份工作
- ️️2014.07-2015.05 荆州/武汉,泰康人寿卖保险3月、饿了么送外卖2月,还有炸鸡排、直销等第2345份工作
- 2015.08 开始从事Java开发,闯过外包,呆过大厂!擅长抽象思维,任基础架构团队负责人
- 2021.08 因“双减政策”失业!历经9面,终获美团外卖L8的offer
- *️Java架构师、Spring开源贡献者、CSDN博客之星年度Top 10、领域建模专家、写作大赛1/2届评委
- 高质量代码、规范践行者;DDD领域驱动深度实践;即将出版书籍
《Spring奇淫巧技》

| 序号 | 专栏名称 | 简介 |
|---|---|---|
| 01 | 【方向盘】-程序人生 | 程序人生,人生程序 |
| 02 | 【方向盘】-资讯/新特性 | IDEA、JDK、Spring技术栈…新特性 |
| 03 | 【方向盘】-IntelliJ IDEA | 熟练使用IDEA就相当拥有物理外挂,助你高效编码 |
| 04 | 【方向盘】-Bean Validation | 熟练掌握数据校验,减少90%的垃圾代码 |
| 05 | 【方向盘】-日期时间 | 帮你解决JDK Date、JSR 310日期/其实 的一切问题 |
| 06 | 【方向盘】-Spring类型转换 | Spring类型转换-框架设计的基石 |
| 07 | 【方向盘】-Spring static | static关键字在Spring里的应用 |
| 08 | 【方向盘】-Cors跨域 | 关于跨域请求问题,本专栏足矣 |
| 09 | 【方向盘】-Jackson | Almost Maybe是最好的Jackson专栏 |
| 10 | 【方向盘】-Spring配置类 | 专讲@Configuration配置类,你懂的 |
| 11 | 【方向盘】-Spring技术栈 | 暂无所属小分类的,Spring技术栈大分类 |
| 12 | 【方向盘】-JDK | 暂无所属小分类的,JDK技术栈大分类 |
| 13 | 【方向盘】-Servlet | Servlet规范、Web相关内容专题 |
| 14 | 【方向盘】-Java EE | 从Java EE到Jakarta EE,30年弹指一挥间 |
| 15 | 【方向盘】-工具/提效 | 开发工具、软件工具,目标是提效 |
| 16 | 【方向盘】-Spring技术栈新特性 | Spring Framework、Spring Boot、Spring Cloud、Spring其它技术 |
| 17 | 【方向盘】-基本功 | 每个Javaer,都需要有扎实的基本功 |
| … | … | … |
| 99 | 源代码库 | 大多数专栏均配有源代码,都在这里 |
边栏推荐
- Sparksql core usage, 220724,
- STM32 ADC based on Hal library uses DMA multi-channel sampling and solves the problems encountered
- Redis基本类型-哈希Hash
- 《大厂面试》之JVM篇21问与答
- Redis basic type - combined with set
- Redis 持久化
- Introduction to pyqt5 - student management system
- 渗透学习-SQL注入篇-靶场篇-安全狗的安装与绕过实验(后续还会更新)
- owasp top10 渗透测试
- 记录PHPSerializer工具类反序列化遇到的坑
猜你喜欢

反射

Mac can't connect to local MySQL server through socket '/tmp/mysql Sock '(2) problem

tensorflow scatter_nd函数

SparkSQL核心使用,220724,

Redis 分片集群

STM32外部中断(寄存器版本)

Requirements already satisfied: and read timed out. problem solving methods appear during the installation of snownlp package

JSONObject按照key的A——Z顺序排序

Tensorflow Einstein function

metaRTC5.0实现君正的纯C的webrtc版IPC
随机推荐
owasp top10 渗透测试
Redis.conf details
一日一书:机器学习及实践——从零开始通往kaggle竞赛之路
[C language] operator details (in-depth understanding + sorting and classification)
[lvgl (6)] display Chinese settings and make Chinese font
STM32 external interrupt (register version)
Introduction to pyqt5 - student management system
找工作备忘
Redis basic type - combined with set
Neural network superparameter adjustment (based on ray package)
GE口:SGMII模式和serdes模式
(static, dynamic, file) three versions of address book
反射
Three level classification / menu query tree structure
[wechat applet] understand conditional rendering, list rendering and wxss template style
MySQL gets the self incrementing line mark (different from MySQL version)
You don't have to waste your life on others' standards
Redis特殊数据类型-HyperLogLog
Redis特殊数据类型-BitMap
Huawei experts' self statement: how to become an excellent engineer