Please stop writing thousands of lines of classes and try these awesome refactoring techniques

Source: juejin.cn/post/6844904038383747086

Promise me, stop writing thousands of lines of classes, okay?

When I extended an existing project recently, I found that a class to be changed was 766 lines long and opened nearly 40 public interfaces. I finished changing it with tears.

In order to prevent such a tragedy from happening to me again, I think it is necessary to write a blog to let the majority of fellow programmers know the importance of code refactoring

If you have an ape that writes thousands of lines, be sure to forward this article to him

Why can't classes be too long?

The class is too long - can't read, can't expand

  • Can't read it - it takes several seconds to scroll directly with the scroll wheel. Even the original author may have difficulty understanding the whole class after a long time, let alone other readers.
  • Can't be extended - a class with too many interfaces can make it extremely difficult to extend the class.

Classes are too long - may have redundant code

At this point, the CV engineers fought a cold war

Redundant code is repeated code, usually from the hands of CV engineers who use Ctrl+C and Ctrl+V to produce code. Redundant code is very harmful:

  • Redundant code makes methods and classes too long and not concise
  • Redundant code will cause divergent modifications (when redundant code needs to be changed, every Ctrl+V needs to be modified)

Classes are too long - mostly too many responsibilities

A class opens dozens of interfaces, and there is definitely a problem of too many responsibilities. Just like Tom cat in the picture, there is a huge problem with too many responsibilities of a class:

1. Violation of the design principle - the single responsibility principle (the single responsibility principle requires a class to implement only one responsibility, for example, a Tom only does one thing of sweeping, mopping the table, and mopping the floor, and the implementation of other things can be transferred to history Pike dog or fat maid), violating this principle will lead to code problems such as divergent changes, divergent modifications, and classes that are too long, and it will also make your classes difficult to extend, and even make other programmers think you are unprofessional

2. Divergent changes (referring to many places that cause such modifications), if a class has many responsibilities, then its fan-in (callers) must be many, and the modification of each caller may make your class have to follow Modification of Divergent Change

就是说不管哪儿出了问题,你这个类都得遭殃

3、发散式修改(指此类修改引发修改的地方很多),相同的,如果一个类职责很多,那支撑它实现的下级,即扇出(被调用方)一定很多,如果此类逻辑发生变动,所有下级被调用者可能都得随之修改,也就是发散式修改

就是说你这个类出了问题,不管哪儿都会遭殃

4、难以扩展,如果你的一个类接口非常多,那它的子类怎么办?它的包装类怎么办?难道全部都要实现这么多接口,全部都要承担同样多的职责吗?扩展起来真的非常麻烦

5、触发机关【测试之怒】【运维之怒】

我已经写了几千行了,怎么办?

重构——抽取冗余代码

抽取冗余代码就是将重复代码抽取成一个独立的方法,之后再使用这段代码时就不再需要Ctrl + C,Ctrl + V,而是直接调用对应的方法即可

这样做也可以缩短原方法,使原方法更加简洁易懂

更值得一提的是如果这段代码需要修改,也只需修改一处,而不是发散式地到处修改

真是一箭三雕

使用IDEA进行冗余代码的抽取

1.找到重复代码

2.进行方法抽取 右键->选择重构->抽取->方法 (或者直接使用快捷键Ctrl + Alt + m)

自动检测出个别重复代码的细微差别,有些代码可能只改动一两个变量,IDEA会自动检测出来,并在抽取方法时提醒我们,选择左侧Accept Signature Change(接受签名变动)可以使抽取的方法自动替换更多的重复点

可以选择替换掉所有的重复代码(竟然有18处)

3.重构——更改方法签名

如果你对抽取出的方法的名字、参数、返回值或是修饰符不满意,不要使用Ctrl + R 修改,IDEA提供了重构方法——更改签名(快捷键Ctrl + F6)

注意:方法的名字指的是方法做了什么,而非怎么去做,最好是 动词+名词 格式

比如:

  • Tom.扫地() √
  • Tom.扫地With扫把() ×
  • Tom.用扫把扫地() ×

重构——转移成员变量+函数(转移职责)

将不应该由自己管理的成员变量和函数转移出去

那就要考虑两个问题:该转移谁?转移给谁?

来看一个图

  • 图中成员【偏A】被类【A】调用两次,而只被它所在的类【过长类】调用1次,因而应该转移给【A】去管理
  • 由于函数【偏A】与成员【偏A】的亲密度较高(只调用了【偏A】),因而应与【偏A】共进退,同去留,转移给【A】
  • 成员【偏B】和函数【偏B】也是相同道理
  • 职责1(函数【1】和成员【偏职责1】)和职责2(函数【2】和成员【偏职责2】)由于找不到可转移的合适的类,所以应抽取出一个新的类

注意,先决定移动哪个成员变量,然后再决定移动哪个函数

使用IDEA转移成员变量和函数

1.移动成员变量,鼠标选择成员变量->右键->Refactor->Move,然后选择转移至哪个类

2.移动函数(与移动成员变量步骤相同)

重构——抽取类

当你发现要转移的成员变量和函数找不到合适的类时(转移职责却找不到下家),要想起来,这里是程序世界,而我们程序猿就是类和对象的造物主,是时候创建一个新的类,让它来替我们分担职责(成员变量和函数)了

使用IDEA抽取类

1.重构

选中要搬的成员变量和函数,右键->Refactor->Extract->Delegate(抽取一个委托者,委托他来管理这部分变量和函数,如果只有变量或只有函数,可以抽出参数对象Paramater Object或方法对象Method Object)

不推荐抽取参数对象,因为一般参数对象是给参数多的方法用的(用参数对象取代一长溜的参数),而且如果成员变量抽取了也不会影响任何函数的话,那就是无用对象了,不如直接把他们删除掉

2.为新类起个名,选个包吧

3.注意

抽取的函数和成员一定要符合一个原则,那就是被抽取函数使用被抽取成员的次数一定高于剩余函数的次数,不然违反亲密性原则(成员应归于调用它最多的类,没有理由你用的比我多还让我来管理)

4.一些小问题

由于抽取的函数直接使用了未抽取的对象而导致重构失败,涉及到另一个重构(使用get方法而非直接使用私有成员变量),使用此重构即可解决

技术不分领域,思想一脉相承


本文分享自微信公众号 - JAVA高级架构(gaojijiagou)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324148811&siteId=291194637