源码先锋

源码先锋

代码精简执行过程

admin 154 43
一、代码精简背景

随着业务需求的不断增加和产品的逐步完善,我们应用对应的代码库也在日益庞大,其中有用的、无用的、低频使用的、灰度验证的等各种类型的代码堆积在一起,给后续接手的同学增加了很多的维护和学习成本。有些代码逻辑缺乏文档说明,无人能看懂,更不敢随意修改。当有新需求需要改动这些代码时,大多数选择都是重新写一套,老的代码还继续保留,慢慢的系统中这种代码越来越多,代码工程也逐渐腐化起来,腐化到一定程度只能进行推倒重构。因此定期进行代码缩减,清理腐化的代码,对代码进行优化升级,提升代码工程的可维护性与可理解性,是十分有必要的。

我们后端的java代码工程一般和应用一一对应,根据应用的分层,代码工程也可以分为以下几类:领域服务中心(领域服务)、业务聚合中心(业务系统)、多能力应用(前后端未分离、定时任务、消息)等种类。针对不同类型的代码库,我们需要深入代码进行探查,掌握代码的腐化程度以及有效代码的占比,判断是进行代码缩减还是进行代码重构。如果进行代码缩减,哪些代码可以直接清理,哪些代码可以重用优化,识别过程是个需要花费精力去认真做的。

二、代码精简步骤



三、代码精简实施1、静态代码检查1)idea自带工具检查

步骤1:通过idea自带的工具来检查未使用的类、变量、方法。Preferences—Analyze—Inspections,执行:RunInspectionbyName



步骤2:输入:unuseddeclaration(未使用的声明)



步骤3:输入:unusedimport(未使用的引用)



步骤4:重复代码检查,专业版才能扫描,扫描之后,通过人工识别的方式,看是否能抽离公共方法







•使用idea自带工具检查的缺点如下:

◦spring注入的参数值@value,会认为没有赋值"Fieldisneverassigned.",参数未被赋值,被检测出来;

◦lombook的@data注解对象,会认为"Allconstructorusagesbelongtothecallschainthathasnomembersreachablefromentrypoints",被检测出来;

◦实体类中没有初始化new过,会认为"Constructorisneverused",构造函数没有使用过,被检测出来;

◦无效代码的误判较多,识别需要要花费一定的时间;

◦重复代码检查都能检查出来,检查到以后,都需要人工进行识别,进行抽象处理;

2)使用PMD插件检查

步骤1:安装插件:IDEA通过FileSettingsPluginsMarketplace搜索“PMD”,按照提示进行安装,然后重启即可



步骤2:配置检测规则:通过FileSettingsOtherSettingsPMD可以打开检测规则的设置界面



执行PMD:



使用默认的规则的话,比较多,我们关心的是哪些代码可以精简,因此我们选择自定义规则,定义文件,然后配置PMD检查规则,选择文件。



具体文件内容如下:

?xmlversion="1.0"?rulesetname="myruleset"xmlns=""xmlns:xsi=""xsi:schemaLocation=""descriptionMyruleset/description!--空的catch块:发现空的catch块没做任何异常处理的事,在大多数情形下,这会吞噬一些应该被处理或报告的异常--ruleref="category/java//EmptyCatchBlock"/!--空的finally块:避免空的finally块-这些是可以删掉的--ruleref="category/java//EmptyFinallyBlock"/!--空的if表达式:发现使用if进行了条件判断,但是判断之后没做任何处理--ruleref="category/java//EmptyIfStmt"/!--空的初始化块:发现空的初始化块--ruleref="category/java//EmptyInitializer"/ruleref="category/java//EmptyStatementBlock"/!--空的switch表达式:避免空的switch表达式--ruleref="category/java//EmptySwitchStatements"/!--翻译空的Synchronized块:避免空的synchronized块--ruleref="category/java//EmptySynchronizedBlock"/!--空的try块:避免空的try块--ruleref="category/java//EmptyTryBlock"/!--空的while表达式:发现空的while表达式--ruleref="category/java//EmptyWhileStmt"/!--未用的常规参数--!--ruleref="category/java//UnusedFormalParameter"/--!--未用的本地变量--ruleref="category/java//UnusedLocalVariable"/!--未用的私有变量--ruleref="category/java//UnusedPrivateField"/!--未用的私有方法--ruleref="category/java//UnusedPrivateMethod"/!--不要引入:避免从’’包引入任何东西,它里面的类是自动引入的--ruleref="category/java//DontImportJavaLang"/!--避免重复引入--ruleref="category/java//DuplicateImports"/!--未使用的imports:去掉不使用的import--ruleref="category/java//UnusedImports"/!--从同一个包引入:不需要从同一包引入类型--ruleref="category/java//ImportFromSamePackage"/!--太多的静态引入:如果滥用静态引入特性,会使你的程序不具有可读性和可维护性,你引入的太多的静态成员污染--ruleref="category/java//TooManyStaticImports"//ruleset

检测效果截图:



步骤3:重复代码检查,下载pmd压缩包,运行cpdgui



•命令行执行:/Users/zhanglu7/Downloads//bin/

•选择检查的文件夹目录,执行检查,GO



使用PMD检查工具缺点如下:

•缺少无引用的public方法检查规则,目前都是私有方法的检查,公有方法检测规则需要自己实现,或者通过人工甄别的方式进行检查;

•重复代码检查需要额外使用CPD,重复代码检查都能检查出来,检查到以后,都需要人工进行识别,进行抽象处理;

3)静态代码检查结论

•建议使用PMD插件+CPD的方式进行,静态代码检查,检查包括:空逻辑控制代码块,未用的本地\私有变量、未使用的私有方法,检查出来的内容基本上都可以直接从代码库中删除。重复代码检查,使用CPD检查重复超过**行的代码,检查结果作为一个参考,帮助我们找到代码库中疑似重复的代码,然后通过人工甄别,判断该重复代码是否可以进一步抽象,抽象成公共的方法,供多处调用。

•test_code_reduce,demo工程,代码行数103行,通过pmd检查后,可删除10行左右(包括未使用的私有方法、无效引用、未使用的本地变量),占比10%左右。



•jdo-***,线上工程,代码行数20005,通过pmd检查后,可删除400行左右(包括未使用的私有方法,未使用的私有变量、重复引入、无效引用、未使用的本地变量),占比2%左右。通过idea扫描的重复代码,需要人工甄别,抽取出公共方法。另外需要人工检查无用的public方法,以及类等,估计可以删除600行左右,占比3%,可以完成整体缩减5%的目标。



2、动态代码检查1)京东jacoco流水线

步骤1:配置流水线



步骤2:行云应用添加启动参数

启动前配置:

mkdir-p/export/home/jacoco

cd/export/home/jacocowget""

tar-xzvf/export/home/jacoco/



启动配置:

ip=$(/sbin/ipa|grep"inet"|grep-v"169.254.95.120"|grep-v"127.0.0.1"|awk'{print$2}'|awk-F/'{print$1}')

exportJACOCO_AGENT="-javaagent:/export/home/jacoco//lib/=includes=*,output=tcpserver,port=8840,address='${ip}'-Xverify:none"

exportCATALINA_OPTS="${JACOCO_AGENT:-}${CATALINA_OPTS}"



步骤3:运行流水线



待运行一段时间后,再运行流水线,查看动态代码覆盖率



2)动态代码检查结论

•建议使用京东jacoco流水线来进行动态代码检查,但需要进行长时间的运行才能得到一个相对精准的代码执行记录,该记录也仅供参考,代码是否可以删除,还需要人工进一步甄别。