重构的定义:重构只改变内部结构,不改变外部行为(对外部原本是怎么样现在依旧是怎么样)。
代码层级的重构
-
使用空格,让代码可读性提升。
-
对于一个方法
-
移除不再使用的代码dead code
-
移除重复代码
-
重复代码很多时候idea都可以检测到。
-
但是更多的是逻辑的重复,例如对于一个int的排序方法和另一个对于object的排序方法,这两个方法是重复的。
Creating a template method eliminates this duplication by merging the shared
algorithm steps in a superclass and leaving just the differences in the subclasses.
-
-
符号命名可读性提升
-
切分代码:减小一个方法的代码数量
- (切分一个方法中的代码,如果它的职责和其他的不同)。
- 如果一个方法根据参数的参数选择执行的逻辑,那么把不同逻辑代码封装成不同的方法。
- 如果一部分代码的逻辑已经够简单,请不要把它切分出去。例如判断大于5.
-
传入的参数
- 参数不要过多
- 传入的参数最好在方法内创建一个本地变量copy一份传入的参数,因为很多时候传入的参数是reference,最好不要修改原本的数据。
-
如果有一个常量,最好定义成
public static final GRAVITY_CONSTANT = 9.8
-
-
为代码添加测试。
-
封装私有数据,提供getter,setter方法。注意不是所有的都需要两个方法。
更高层级的重构
-
Switch语句在面向对象的范式中是不好的,如果根据一个类是什么子类来执行对应的方法,那么就应该抽象一个父类定义这个抽象方法,让子类各自去实现不同的逻辑。
-
类的单一职责原则:不仅仅是一个类的方法,如果一个类的属性包含了不属于它的属性。比如一个用户的电话,PhoneAreaCOde,这连个应该交给phone类去管理。
-
对于接口的分解,如果一个接口的方法在某些子类需要,在某些子类不需要,那么最好的方法就是把这个方法分离出原本的接口,让需要改方法的子类去实现新的接口。
-
方法提取的两种思维:
-
如果所有子类都需要使用一个方法(或一部分共同的属性,方法),那么把该方法(或方法)提取到父类。
- 如果两个子类有一个方法,完成相同的步骤,但是具体步骤做的事情不同,那么可以把这个方法用相同的函数签名放到父类的抽象方法。
-
如果父类的一个方法只有一部分子类使用,那么把该方法从父类中移除,放入需要的子类。如果需要的子类很多,那么建立一个中间的抽象类,例如flyBird。
并且这个也适用于属性的提取,如果父类的一些属性只有一些子类需要,那么把这些属性移动到需要的子类就可以。同理可以提取抽象层。
-
-
提取template method的方法
- 首先要把类的相同逻辑的代码提取到一个方法。
- 提取子类相同的方法逻辑到父类。
- 测试pull up方法自身是不是work。
- 使用相同的方法调用,但是调用不同的子类逻辑
- 再次integrated测试。
- 对于原本的方法使用pull up
- 再次测试。
-
类之间方法移动:如果一个类的某个方法传入的参数是另一个类,并且这个方法被调用的次数明显多于这个类对于它的干涉,那么就把这个方法移动到另一个类。
-
对于一个对象,想要用null来做一些逻辑。那么最好就是去实现一个nullObject,来继承父类实现一些逻辑,让比较的时候来判断是不是nullObject而不是和null比较。
-
在面向对象中,使用自定义Exception来处理一些情况,而不是像C这种面向过程的语言用返回-1来表示错误。
For Big Refactoring
推荐阅读/视频链接: