Android代码重构——实战小技巧

在平时开发 Android 工程中,我们如何高效去做重构,重构和开发怎么比较好的有效结合起来。

所谓工欲善其事必先利就是这个道理,我们如果需要去做重构优化,首先我们要知道我们做的不好的地方 - 代码的坏味道在哪里,这种工作如果靠人为手动的去发现,那么效率和产出将会及其低下,所以我们需要借助于集成插件工具帮我们自动去扫描发现问题,然后再去针对性的重构优化,产出 Clean code 。

Long Method 实战

Long Method 是笔者前面提到的“代码坏味道”之一,这也是开发者一般经常容易犯的典型错误。

接下来笔者介绍在 Android 平台中如何去解决这个“bad taste”,实际上我们可以通过计算函数的圈复杂度(cyclomatic complexity)来判断函数是否过长, 一般 cyclomatic complexity > 11 , 就可以认为函数过长,需要进行重构优化,那么关于函数重构的优化技巧在前面几章我也有重点提到。

在解决圈复杂度过大这个问题,首先我们要去发现你的工程哪里存在问题,这一步我们可以通过工具或者第三方插件帮我们去解决,比如打开 Android studio 工具栏 Analyze –> Run inspection by name, 如下图 8 所:

Android代码重构——实战小技巧_第1张图片

图 8 Analyze 工具示意图

如图 8 所示,选择 Run inspection by name , 打开如下图 9 所示界面:

Android代码重构——实战小技巧_第2张图片

图 9 Overly long method 界面示意图

如图 9 所示,输入 long 出现 Overly long method , 选择如上图所示,点击会打开一个新的界面如图 10 所示:

Android代码重构——实战小技巧_第3张图片

图 10 Run ‘Overly long method’

如图 10 所示,可以选择对当前工程,当前 File, 当前 Module 或者其他 Module 进行分析,等待运行一段时间分析结果如下图 11 所示:

Android代码重构——实战小技巧_第4张图片

图 11 Run ‘Overly long method’ 结果

得到图 11 分析结果之后,我们就可以有针对性的去进行优化重构了,知道哪些类哪些函数需要去优化,具体重构优化是一般可以将过长的函数拆分成几个不同的小函数,拆分原则:一个函数的功能要保持职责单一,查询和修改职责分开;所以可以通过不同类型的功能业务逻辑处理或者查询、修改功能去拆分大函数。

Too many parameters 实战

函数参数过多,也是典型的“代码坏味道”之一,同理打开如上图 8 所示的界面,然后输入 too many pa 关键字打开如下图 12 所示的界面:

Android代码重构——实战小技巧_第5张图片

图 12 Analyze too many pa 关键字界面

选择图中所示的 “Method with too many parameters”, 会出现如上图 10 所示的界面,然后选择“Whole Project”, 运行之后,分析得到的结果如下图 13 所示:

Android代码重构——实战小技巧_第6张图片

图 13 “Too many parameters”结果分析图

Redundant local variable 实战

冗余的局部变量,同样是造成代码坏味道的源头,输入 “Redudant 关键字”,同理执行得出分析结果如下图 14 所示,然后我们根据分析后的结果有针对性的去重构优化:

Android代码重构——实战小技巧_第7张图片

图 14 冗余局部变量分析结果

Unused Declaration –无用函数实战

无用函数是“代码坏味道”来源之一,很多函数因为历史遗留的原因,需求已经下线了但是代码还在遗留在工程里面,或者因为重构,历史遗留代码没有完全删除或者想暂时留着下个版本使用,这些都是不好的习惯,不用的代码应该立即删除,而不应该保留在工程项目中。

同理打开如上图 8 所示的界面,然后输入 Unused declaration 关键字打开如下图 15 所示的界面:

Android代码重构——实战小技巧_第8张图片

图 15 Unused declaration

分析结果能得出你整个工程中没有被使用的函数,我们都可以删除掉。

无用函数参数 - 实战

同理,输入关键字 Unused method parameter, 如下图 16 所示, 执行可以分析出工程中有哪些函数存在无用参数,可以针对性的进行优化。

Android代码重构——实战小技巧_第9张图片

图 16 unused method parameter

infer 实战

Infer 是 Facebook 开源的静态代码检查工具,可检查 Android 和 Java 代码中的 NullPointException 和 资源泄露。除了以上,Infer 还可发现 iOS 和 C 代码中的内存泄露,内存泄露,内存泄露。

Android studio 已经将 infer 集成到工具栏里面,点击 Analyze->infer Nullity, 执行分析得出的界面类似如下图 17 所示:

Android代码重构——实战小技巧_第10张图片

图 17 infer Nullity 分析结果图

点击图 17 所示的分析结果具体项,可以定位到具体的代码文件,然后我们去手动判断 或者直接点击“Infer Nullity Annotations”, 工具直接帮我去完成改造结果。

第三方插件与 Android studio 的集成

FindBugs 集成

FindBugs 是一个开源的静态代码分析工具,基于 LGPL 开源协议,无需运行工程就能对代码进行分析的工具。它不注重 style 及 format,注重检测真正的 bug 及潜在的性能问题 ,以 bytecode(*.class、*.jar)为对象进行检查。除了单独运行,还可以用作 Android-studio 和 Eclipse 的 Plug-in,以及嵌入 Ant 或者 Maven 作为 task 之一进行运行。

Findbugs 自带 60 余种 Bad practice,80 余种 Correntness,1 种 Internationalization,12 种 Malicious code vulnerability,27 种 Multithreaded correntness,23 种 Performance,43 种 Dodgy。它可以检测检测 java programing 中容易陷入的 bug pattern,比如equals()实现时的一般规约违反 Null pointer 的参照 ,Method 的返回值的 check 遗漏 ,初始化前 field 的访问, Multi-thread 的正确性,无条件的 wait,Code 的脆弱性 ,可以变更的静态 object ,内部数列参照的 return 等。

Android Studio 可以通过插件的方式安装,具体是打开 Android Studio->Preference –>搜索 plugin 选择 Plugins Tab , 打开界面如下图 17 所示:

Android代码重构——实战小技巧_第11张图片

图 17 搜索 FindBugs-IDEA 界面

如上图 17 中,点击 install ,downloading plugin install , 然后重启 Android studio , 会有提示界面如下图 18 所示:

Android代码重构——实战小技巧_第12张图片

图 18 Android FindBugs Enable

点击“Enable Android FindBugs”, 会打开界面,在见面中添加 Plugin For Android FindBugs 即可。

然后在 Android Studio 工具栏上,打开如下图 19 所示的界面:

Android代码重构——实战小技巧_第13张图片

图 19 FindBugs 入口界面

如上图 19 所示,可以分析对前的文件,可以分析一个 Module files ,也可以分析一个工程文件,选择一项会得出分析结果如下图 20 所示:

Android代码重构——实战小技巧_第14张图片

图 20 FindBugs 分析结果图

根据图 20 所示的结果,我们可以查看具体的 Bug details , 存在什么问题,然后具体跟踪到对应的代码,根据对应的建议去修改。

MetricsReloaded 集成

MetricsReloaded 是一个计算代码复杂度即圈复杂度的 Jetbrain 开源开发的第三方插件。关于代码复杂度,有个维度的衡量,在这里需要普及下软件复杂度的相关知识:基本复杂度(Essential Complexity (ev(G))、模块设计复杂度(Module Design Complexity (iv(G)))、Cyclomatic Complexity (v(G)) 圈复杂度。

ev(G) 基本复杂度是用来衡量程序非结构化程度的,非结构成分降低了程序的质量,增加了代码的维护难度,使程序难于理解。因此,基本复杂度高意味着非结构化程度高,难以模块化和维护。实际上,消除了一个错误有时会引起其他的错误。

Iv(G) 模块设计复杂度是用来衡量模块判定结构,即模块和其他模块的调用关系。软件模块设计复杂度高意味模块耦合度高,这将导致模块难于隔离、维护和复用。模块设计复杂度是从模块流程图中移去那些不包含调用子模块的判定和循环结构后得出的圈复杂度,因此模块设计复杂度不能大于圈复杂度,通常是远小于圈复杂度。

v(G) 是用来衡量一个模块判定结构的复杂程度,数量上表现为独立路径的条数,即合理的预防错误所需测试的最少路径条数,圈复杂度大说明程序代码可能质量低且难于测试和维护,经验表明,程序的可能错误和高的圈复杂度有着很大关系。

同理,如上图 17 所示一样去安装 MetricsReloaded 插件,安装成功后执行 Analyze->Calculate Metrics, 打开如下图 21 所示的界面:

Android代码重构——实战小技巧_第15张图片

图 21 Calculate Metrics 界面

如上图所示,选择 Complexity metrics, 执行分析结果如下图 22 所示:

Android代码重构——实战小技巧_第16张图片

图 22 Calculate Metrics 分析结果图

如上图 22 所示界面中的红颜色部分,代表需要去重构优化的,点击当前行,会定位到源代码,然后我们针对性去优化函数。上图中,可以分析出方法的圈复杂度、类的圈复杂度、包的圈复杂度、模块的圈复杂度、工程的圈复杂度。

Sonar 集成

对于 Android(Java)工程,Sonar 官方提供了 Java Plugin 和 Java-specific Plugins,这些插件可以实现大部分 Findbugs、PMD、Checkstyle、Android Lint 等的检查规则。主要可以从以下几个方面检测代码质量:

(1)复杂度:项目中方法、类、文件的复杂度分布情况;

(2)重复:展示代码中重复严重的地方;

(3)单元测试覆盖率:统计并展示单元测试覆盖率(主要用于 java 工程);

(4)代码标准:通过 PMD、CheckStyle 等代码规则检测工具规范代码编写;

(5)代码注释:没有注释或者过多的注释都不是一个良好的编程习惯;

(6)潜在的 bug: 通过 PMD、Findbugs 等代码检测工具检测出潜在的 bug;

(7)架构设计:可以检测耦合、依赖关系、架构规则、管理第三方的 jar 包等。

集成 Sonar 之后,我们需要着种解决的就是代码重复率问题,这也是“代码坏味道”最典型的问题,开发者最容易犯这个问题,特别是不少开发者喜欢偷懒,容易拷贝来拷贝去,造成工程代码的重复率比较高。一次构建运行之后,我们可以得出分析结果,类似如下图 23 所示:

Android代码重构——实战小技巧_第17张图片

图 23 sonar 构建运行结果

点击重复率,我们可以看出哪些文件之间的代码是重复的,然后针对性使用抽取工具类、合并类、合并分解函数等技术重构手段去优化。

SonarLint 集成

前面我们所讲到的 Sonar 之前的提供的本地工具是需要依赖 SonarQube 服务器的,这样导致其运行速度缓慢。 新出的 SonarLint 的扫描引擎直接安装在本地,速度超快,实时探测代码技术债务,给程序员最快速的反馈,排除代码异味的绝佳利器,帮助程序员获得 Clean code。 新版 SonarLint 也能链接 SonarQube 服务器,但这并不必要。本地安装 SonarLint 来做代码本地扫描,本地发现本地修改,而且能快速看到修改结果,快速处理代码臭味,有效控制技术债务。

按照如上图 17 所示一样去安装 SonarLint 插件,安装之后重启 Android Studio , 即可动态扫描出结果如下图 24 所示:

Android代码重构——实战小技巧_第18张图片

图 24 SonarLint 扫描结果图

重构技巧实战 - 小结

本文我们讲述了在 Android 程序开发过程中如何结合工具去帮助我们做重构优化的各种技能包括 Android Studio 自己已经集成的插件 Code Inspection 、infer Nullity 以及 FindBugs、MetricsReloaded、Sonar、SonarLint 等第三方插件工具,其实还有很多类似著名的插件比如 QAPlugin、PMD、Hammurapi 、Lint4j 等工具,大家可以自行尝试使用,在这里我不一一说明。

参考文章:http://www.sohu.com/a/151197127_635110

你可能感兴趣的:(设计模式)