通用步骤
1.首先应该阅读代码,理解代码的基本含义。
2.对原本的代码编写单元测试,如果测试能通过,进行commit。
必须要有单元测试!!!单元测试全部通过才算重构完成!!!
神秘命名(Mysterious Name)
方法或变量名不表义,很难看懂是什么意思
3.利用ide重构原有的神秘命名代码。
4.跑测试,如果测试能通过,则变更引用原代码的位置的引用方法。
5.如果测试通过,小步提交commit。
重复代码(Repeat Code)
两个或多个函数包含了多行重复代码
3.利用ide重构原有的重复代码,抽出为公共方法。
4.将原有的重复代码替换为公共方法,跑测试。
5.如果测试通过,小步提交commit。
过长函数(Long Function)
单一函数过长
3.对原本过长函数中的逻辑,按照其做的事情进行抽取,抽成符合其名字的小方法。
4.跑测试。
5.如果测试通过,小步提交commit。
过长参数列表(Long Parameter List)
常见的坏参数有
1.标记参数,例如isXXX这种变量,实际上一个函数方法中可能就包含了两种逻辑,在这种情况下,完全可以将两种逻辑分离,写为两个单独的方法,增加代码可读性。
2.通用性变量,实际上可以将多个参数的变量抽取到一个类中,与业务无关的逻辑也可以在类中实现。
全局数据(Global Data)
全局都能用到的数据,或者说全局都可能会用到的数据,不能提供其对外暴露的修改接口,因为全局都能进行调用修改的情况下,定位问题将变成一件非常困难的事情。
可变数据(Mutable Data)
发散式变化(Divergent Change)
一个函数中包含了多条逻辑,如果需要进行修改,例如一个商品计算价格,首先计算总价,然后计算折扣后价格,如果都放在同一个函数中,那么如果计算逻辑改变,就需要在大函数中进行修改,在此过程中可能计算会出现问题,因此可以将计算总价,计算折扣价格抽取成两个不同的方法,如果后期业务逻辑改变只需要修改两个对应小方法中的代码即可。
其实这就是面向对象设计原则中的单一职责原则
依恋情节(Feature Envy)
一个类中的成员变量包含了另一个类的对象,且针对这个对象实现了某一个具体函数方法,那么此时的函数方法就应该转移到另一个类中,在类中只需要通过其对象调用方法即可。
数据泥团(Data Clumps)
例如以下这个person类,函数telephoneNumber由officeAreaCode和officeNumber组成,那么如果officeNumber被删除,telephoneNumber也就失去了他的意义,且所有引用到它的地方都会出现问题,这样的情况就是数据泥团,即多个数据混合在一起
class Person {
constructor(name) {
this._name = name;
}
get name() {
return this._name;
}
set name(arg) {
this._name = arg;
}
get telephoneNumber() {
return `(${this.officeAreaCode}) ${this.officeNumber}`;
}
get officeAreaCode() {
return this._officeAreaCode;
}
set officeAreaCode(arg) {
this._officeAreaCode = arg;
}
get officeNumber() {
return this._officeNumber;
}
set officeNumber(arg) {
this._officeNumber = arg;
}
}
对于这种情况我们可以将两个强关联的变量抽取到一个类当中。
基本类型偏执(Primitive Obsession)
循环语句(Loop)
尽可能的使用Stream流进行逻辑处理