三维重构步骤
最近有人在Twitter上问我,如果不理解代码的工作原理,如何重构。 我回答说 ,这是“通过重构学习”。 然后我尝试用Google搜索它,却一无所获 。 我很惊讶。 对我来说,重构似乎是研究源代码的最有效,最明显的方法。 这是我通常的九个面向对象步骤。
根据Wikipedia的说法, 代码重构是“重构现有计算机代码的过程-更改因子分解-而无需更改其外部行为。” 重构的目的是使代码更具可读性并适合于修改。
这是我不知道代码但需要修改时通常要执行的操作。 从最简单的技术开始,按照复杂性的顺序对这些技术进行排序。
删除IDE红色斑点
当我使用自定义settings.jar
在IntelliJ IDEA中打开Cactoos的源代码时,我看到的是这样的:
当我打开诸如Spring Boot的源代码时,我看到类似这样的内容(它是osbImageBanner
它是从一千个看起来非常相似的其他类中随机选择的): 看到不同?
当我看到别人的代码时,我要做的第一件事是使它对我的IDE来说是“红色斑点”。 这些红色斑点中的大多数很容易消除,而其他一些将需要一些时间进行重构。 在这样做的同时,我学到了很多关于 废话 我必须处理的程序。
删除空行
我前段时间写道 ,方法主体中的空行是不好的事情。 它们是冗余复杂度的明显指标。 程序员倾向于将它们添加到他们的方法中以简化内容。
这是来自Apache Maven代码RepositoryUtils
一种方法(随机选择类RepositoryUtils
,但是几乎所有其他类的格式都相同):
<
除了“全红”之外,他们的代码还充满了空行。 删除它们可以使代码更具可读性,也可以帮助我理解代码的工作原理。 较大的方法将需要重构,因为如果没有空行,它们将几乎变得完全不可读。 因此,我主要通过将它们分解为更小的方法来压缩,理解并缩小它们。
使名字更短
我通常赞成对变量使用简短的一名词名称,对于方法使用简短的一动词名称。 我认为较长的“复合”名称表明不必要的代码复杂性。
例如,我在Spring Boot的osbweuUndertowServletWebServerFactory
类中找到了方法registerServletContainerInitializerToDriveServletContextInitializers
(69个字符!)。 我不知道为什么笔者跳过couldYouPlease
前缀和otherwiseThrowAnException
后缀。
除了笑话,这么长的方法名称清楚地表明代码太复杂了,无法用简单的register
甚至registerContainer
来解释。 似乎有许多不同的容器,初始化程序,servlet和其他生物需要以某种方式进行注册。 当我加入一个项目并看到一个使用该名称的方法时,我正为大麻烦做准备。
当开始使用外部代码或旧代码时,使名称更短是我必须执行的重构步骤。
添加单元测试
大多数类(和方法)都没有任何文档,尤其是当我们谈论的是闭源商业代码时。 如果这些班级或多或少具有描述性的名称并且规模小且具有凝聚力,我们将很幸运。
但是,我更喜欢处理单元测试,而不是文档。 他们更好地解释了代码并证明它有效。 当我不了解类的工作原理时,我会尝试为其编写单元测试。 在大多数情况下,由于许多原因,这是不可能的。
删除多个退货
我之前写过 ,在单个方法中存在多个return
语句并不是鼓励面向对象的编程。 相反,方法必须始终具有单个出口点,就像函数编程中的那些函数一样。
从Spring Boot的osbcpbBinder
类中查看此方法(那里有很多类似的示例,我随机选择了一个):
这么小的方法有五个return
语句。 对于面向对象的代码来说太多了。 程序代码没关系,我有时也会写。 例如,我们的这个Groovy脚本也有五个return
关键字:
但这是Groovy,不是一门课。 这只是一个过程,一个脚本。
重构和删除多个return
语句绝对有助于使代码更整洁。 通常是因为没有它们,有必要使用if/then/else
语句的更深层嵌套,然后代码开始看起来很难看,除非您将其分解为较小的部分。
摆脱NULL
空是邪恶的 ,这是众所周知的事实。 但是,它们仍然无处不在。 例如,Spring Boot v2.0.0.RELEASE和243K LoC中有4,100个Java文件,其中包含null
关键字7,055次。 这意味着每35行大约有一个null
。
相反,我几年前创建的Takes Framework具有771个Java文件,15.4万个LoC和58个null
关键字。 每2700行大约是一个null
。 看到不同?
当您删除NULL时,代码会变得更整洁,但这并不是那么容易。 有时甚至是不可能的。 这就是为什么我们在Takes中仍然有58个null
情况。 我们根本无法删除它们,因为它们来自JDK。
使对象不变
正如我前段时间所展示的 , 不变性有助于缩小对象。 我在处理的外部代码中看到的大多数类都是可变的。 和大。
如果查看jpeek分析的任何工件,您会发现在大多数对象中,大约80%的类是可变的。 从可变性到不变性是面向对象编程中的一大挑战,如果解决,它将带来更好的代码。
使事物不可变的重构步骤纯粹是有利可图的。
移除静电
如果您是过程程序员,则静态方法和属性很方便。 如果您的代码是面向对象的,则它们必须消失 。 在Spring Boot中,有7,482个static
关键字,这意味着每32行代码需要一个。 相反,在Takes中,我们有310个static
-s,每496行是一个。
将这些数字与有关NULL的统计数据进行比较,您会发现摆脱static
是一项更为复杂的任务。
应用静态分析
这是最后一步,也是最复杂的一步。 这很复杂,因为我将静态分析仪配置为最大潜力甚至更高。 我正在使用Qulice ,它是Checkstyle,PMD和FindBugs的聚合器。 这些家伙本身很坚强,但Qulice使他们变得更坚强 ,增加了几十个定制支票。
我用于静态分析的原理是0/100。 这意味着要么整个代码库都是干净的,没有Qulice投诉,要么是肮脏的。 中间没有东西。 这不是查看静态分析的非常典型的方法。 大多数程序员使用这些工具只是为了收集有关其代码的“意见”。 我将它们用作重构的指南。
观看此视频,该视频演示了Qulice对Spring Boot中的spring-boot-project/spring-boot
子模块的投诉(视频无休止,因为我在等待中失去了耐心):
当Qulice说一切都干净时,我认为代码库已准备就绪,可以进行维护和修改。 至此重构已经完成。
翻译自: https://www.javacodegeeks.com/2018/04/nine-steps-of-learning-by-refactoring.html
三维重构步骤