代码精简执行过程
一、代码精简背景
随着业务需求的不断增加和产品的逐步完善,我们应用对应的代码库也在日益庞大,其中有用的、无用的、低频使用的、灰度验证的等各种类型的代码堆积在一起,给后续接手的同学增加了很多的维护和学习成本。有些代码逻辑缺乏文档说明,无人能看懂,更不敢随意修改。当有新需求需要改动这些代码时,大多数选择都是重新写一套,老的代码还继续保留,慢慢的系统中这种代码越来越多,代码工程也逐渐腐化起来,腐化到一定程度只能进行推倒重构。因此定期进行代码缩减,清理腐化的代码,对代码进行优化升级,提升代码工程的可维护性与可理解性,是十分有必要的。
我们后端的java代码工程一般和应用一一对应,根据应用的分层,代码工程也可以分为以下几类:领域服务中心(领域服务)、业务聚合中心(业务系统)、多能力应用(前后端未分离、定时任务、消息...)等种类。针对不同类型的代码库,我们需要深入代码进行探查,掌握代码的腐化程度以及有效代码的占比,判断是进行代码缩减还是进行代码重构。如果进行代码缩减,哪些代码可以直接清理,哪些代码可以重用优化,识别过程是个需要花费精力去认真做的。
二、代码精简步骤
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-10-18-40HevSEEOJWomT0oM.png)
三、代码精简实施
1、静态代码检查
1)idea 自带工具检查
步骤1:通过idea 自带的工具来检查未使用的类、变量、方法。Preferences—>Analyze—>Inspections,执行:Run Inspection by Name
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-09-34RYveuM34vlfe13Pwp.png)
步骤2:输入:unused declaration(未使用的声明)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-09-379hOBPQ629annHgtR.png)
步骤3:输入:unused import(未使用的引用)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-09-38czQ29RZf9ZSYAcay.png)
步骤4:重复代码检查,专业版才能扫描,扫描之后,通过人工识别的方式,看是否能抽离公共方法
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-10-59zwjnN1iD69P54ocV.png)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-11-00uaQF40ePor9dhSrt.png)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-11-01Z0OI9L11mRQsZmuG.png)
2)使用PMD插件检查
步骤1:安装插件:IDEA通过 File > Settings > Plugins > Marketplace
搜索 “PMD
”,按照提示进行安装,然后重启即可
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-10-11-23U0ykRX8ZFj7xc10o.png)
步骤2:配置检测规则:通过 File > Settings > Other Settings > PMD
可以打开检测规则的设置界面
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-09-42fIjjNxWH8QuneJN.png)
执行PMD:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-09-45mWQ8VTGFDGpjrMW.png)
使用默认的规则的话,比较多,我们关心的是哪些代码可以精简,因此我们选择自定义规则,定义setting.xml文件,然后配置 PMD检查规则,选择setting.xml文件。
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-09-47P7XWjDamhfCocR6.png)
具体文件内容如下:
<?xml version="1.0"?>
<ruleset name="myruleset"
xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 https://pmd.sourceforge.io/ruleset_2_0_0.xsd">
<description>My ruleset</description>
<!-- 空的 catch 块:发现空的 catch 块没做任何异常处理的事,在大多数情形下,这会吞噬一些应该被处理或报告的异常 -->
<rule ref="category/java/errorprone.xml/EmptyCatchBlock"/>
<!-- 空的 finally 块:避免空的 finally 块 - 这些是可以删掉的 -->
<rule ref="category/java/errorprone.xml/EmptyFinallyBlock"/>
<!-- 空的 if 表达式:发现使用 if 进行了条件判断,但是判断之后没做任何处理 -->
<rule ref="category/java/errorprone.xml/EmptyIfStmt"/>
<!-- 空的初始化块:发现空的初始化块 -->
<rule ref="category/java/errorprone.xml/EmptyInitializer"/>
<rule ref="category/java/errorprone.xml/EmptyStatementBlock"/>
<!-- 空的 switch 表达式:避免空的 switch 表达式 -->
<rule ref="category/java/errorprone.xml/EmptySwitchStatements"/>
<!-- 翻译 空的 Synchronized 块:避免空的 synchronized 块 -->
<rule ref="category/java/errorprone.xml/EmptySynchronizedBlock"/>
<!-- 空的 try 块:避免空的 try 块 -->
<rule ref="category/java/errorprone.xml/EmptyTryBlock"/>
<!-- 空的 while 表达式:发现空的 while 表达式 -->
<rule ref="category/java/errorprone.xml/EmptyWhileStmt"/>
<!-- 未用的常规参数 -->
<!-- <rule ref="category/java/bestpractices.xml/UnusedFormalParameter"/>-->
<!-- 未用的本地变量 -->
<rule ref="category/java/bestpractices.xml/UnusedLocalVariable"/>
<!-- 未用的私有变量 -->
<rule ref="category/java/bestpractices.xml/UnusedPrivateField"/>
<!-- 未用的私有方法 -->
<rule ref="category/java/bestpractices.xml/UnusedPrivateMethod"/>
<!-- 不要引入java.lang:避免从’java.lang’包引入任何东西,它里面的类是自动引入的 -->
<rule ref="category/java/codestyle.xml/DontImportJavaLang"/>
<!-- 避免重复引入 -->
<rule ref="category/java/codestyle.xml/DuplicateImports"/>
<!-- 未使用的imports:去掉不使用的import -->
<rule ref="category/java/bestpractices.xml/UnusedImports"/>
<!-- 从同一个包引入:不需要从同一包引入类型 -->
<rule ref="category/java/errorprone.xml/ImportFromSamePackage"/>
<!-- 太多的静态引入:如果滥用静态引入特性,会使你的程序不具有可读性和可维护性,你引入的太多的静态成员污染 -->
<rule ref="category/java/codestyle.xml/TooManyStaticImports"/>
</ruleset>
检测效果截图:
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-09-496xjPuXAGUtYCV7N.png)
步骤3:重复代码检查,下载pmd压缩包,运行cpdgui
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-10-11-237WQvMvO23imkX760.png)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-10-43LdEr8wyU9vVVUAG.png)
使用PMD检查工具缺点如下:
3)静态代码检查结论
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-29-10-49XOypPg7DI7oqJCh.png)
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-30-09-37Ksvggs6dDeUT0Z39.png)
2、动态代码检查
1)京东jacoco流水线
步骤1:配置流水线
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-30-09-40ZlJkf7iP96rPIYG.png)
步骤2:行云应用添加启动参数
启动前配置:
mkdir -p /export/home/jacoco
cd /export/home/jacoco && wget "http://storage.jd.local/bpp-quality-public/code_coverage_statistics/jacoco-0.8.7-20210115.151120-42.tar.gz"
tar -xzvf /export/home/jacoco/jacoco-0.8.7-20210115.151120-42.tar.gz
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-30-09-42mhFVLEh1xSmPvFq.png)
启动配置:
ip=$(/sbin/ip a | grep "inet " |grep -v "169.254.95.120" |grep -v "127.0.0.1" | awk '{print $2}' | awk -F/ '{print $1}')
export JACOCO_AGENT="-javaagent:/export/home/jacoco/jacoco-0.8.7-20210115.151120-42/lib/jacocoagent.jar=includes=*,output=tcpserver,port=8840,address='${ip}' -Xverify:none"
export CATALINA_OPTS="${JACOCO_AGENT:-} ${CATALINA_OPTS}"
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-30-09-44bZdIK30tTSDqqqcX.png)
步骤3:运行流水线
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-30-09-478Pposm96KU47vgQq.png)
待运行一段时间后,再运行流水线,查看动态代码覆盖率
![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2024-01-30-09-48C1WtTwfa9gVHyRJ.png)
2)动态代码检查结论