写点什么

《重构 改善既有代码的设计 3》代码的可理解性应该是我们虔诚追求的目标

用户头像
极客good
关注
发布于: 刚刚

你从某个对象中取出若干值,将它们作为某一次函数调用时的参数。


改为传递整个对象。


「动机」


有时候,你会将来自同一对象的若干项数据作为参数,传递给某个函数。这样做的问题在于:万一将来将被调用函数需要新的数据项,你就必须查找并修改对此函数的所有调用。如果你把这些数据所属的整个对象传给函数,可以避免这种尴尬的处境,因为被调用函数可以向那个参数对象请求任何它想要的信息。


除了可以使参数列表更加稳定之外,还能提高代码的可读性。过长的参数列表很难使用,因为调用者和被调用者都必须记住这些参数的用途。

8、以函数取代参数

让参数接受者去除该项参数,并直接调用前一个函数。


「动机」


如果函数可以通过其他途径获取参数值,那么它就不应该通过参数取得该值。过长的参数列表会增加阅读者的理解难度,因此我们应该尽可能缩短参数列的长度。

9、引入参数对象

某些参数总是很自然的同时出现,以一个对象取代这些参数。

10、移除设值函数

类中的某个字段应该在对象创建时就被设值,然后就不再改变。


去掉该字段的所有设值函数。

11、隐藏函数

有一个函数,从来没有被其他任何类用到。


将这个函数修改为 private。

12、以工厂函数取代构造函数

你希望在创建对象时不仅仅是做简单的建构动作。


将构造函数替换为工厂函数。


Employee(int type){


_type = type;


}


static Employee create(int type){


return new Employee(type);


}

13、封装向下转型

某个函数返回的对象,需要由函数调用者向下转型,将向下转型的操作转移到函数中。


Object lastReading(){


return readings.lastElement();


}


Reading lastReading(){


return (Reading)readings.lastElement();


}

14、以异常取代错误码

某个函数返回一个特定的代码,用以表示某种错误情况,改用异常。


代码的可理解性应该是我们虔诚追求的目标。


非受控异常


class Account{


void withdraw(){


Assert.isTrue("sufficient funds",amount <= _balance);


_balance-= amount;


}


}


class Assert{


static void isTrue(String comment, boolean test){


if(!test){


throw new RuntimeException("Assertion failed:"+comment);


}


}


}


15、以测试取代异


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码



面对一个调用者可以预先检查的条件,你抛出一个异常。


修改调用者,使它在调用函数之前先做检查。


「动机」


异常只应该被用于异常的、罕见的行为,也就是哪些产生意料之外的错误的行为,而不应该成为条件检查的替代品。如果你可以合理期望调用者在调用函数之前先先插某个条件,那么就应该提供一个测试,而调用者应该使用它。


第十一章 处理继承关系



1、字段上移

两个子类拥有相同的字段,将该字段移至超类。

2、函数上移

有些函数,在各个子类中产生完全相同的结果,将该函数移至超类。

3、构造函数本体上移

你在各个子类中拥有一些构造函数,它们的本体几乎完全一致。


在超类中新建一个构造函数,并在子类构造函数中调用它。


class Manager extends Employee{


public Manager(String name, String id, int grade){


_name = name;


_id = id;


_grade = grade;


}


}


//改变为


class Manager extends Employee{


public Manager(String name, String id, int grade){


super(name, id);


_grade = grade;


}


}

4、函数下移

超类中的某个函数只与部分子类有关,将这个函数移到相关的那些子类中去。

5、字段下移

超类中的某个字段只被部分子类用到,将这个字段移到需要它的那些子类中去。

6、提炼子类

类中的某些特性只被某些实例用到。


新建一个子类,将上面所说的那一部分特性移到子类中。

7、提炼超类

两个类有相似的特性,为这两个类建立一个超类,将相同特性移至超类。


「动机」


重复代码时系统中最糟糕的东西之一。如果你在不同地方做同一件事情,一旦需要修改那些动作,你就得平白做更多的修改。


重复代码的某种形式就是:两个类以相同的方式做类似的事情,或者以不同的方式做类似的事情。对象提供了一种简化这种情况的机制,那就是继承。但是,在建立这些具有共通性的类之前,你往往无法发现这样的共通性,因此经常会在具有共通性的类出现之后,再开始建立其间的继承关系。


另一种选择就是提炼类,这两种方法之间的选择其实就是继承和委托之间的选择。如果两个类可以共享行为,也可以共享接口。

8、提炼接口

若干个客户使用类接口中的同一子集,或者两个类的接口有部分相同。


将相同的子集提炼到一个独立接口中。

9、折叠继承体系

超类和子类之间无太大区别,将它们合为一体。

10、塑造模板函数

「动机」


继承是避免重复行为的一个强大工具,无论何时,只要你看见两个子类之中有类似的函数,就可以把它们提升到超类。但是如果这些函数并不完全相同该怎么办?


我们仍然有必要尽量避免重复,但又必须保持这些函数之间的实质差异。


常见的一种情况是:


两个函数以相同顺序执行大致相近的操作,但是各操作不完全相同。这种情况下我们可以将执行操作的序列移至超类,并借助多态保证各操作仍得以保持差异性。这样的函数被称为模板函数。

11、以委托取代继承

12、以继承取代委托

在两个类之间使用委托关系,并经常为整个接口编写许多极简单的委托函数,让继承取代委托。


第十二章 大型重构



1、梳理并分解继承体系

某个继承体系同时继承两项责任,建立两个继承体系,并通过委托关系让其中一个可以调用另一个。


继承是个好东西,它可以明显减少子类中的代码量,函数的重要性可能并不和它的大小成正比,在继承体系中尤然。

2、将过程化设计转化为对象设计

将数据记录变成对象,将大块的行为分成小块,并将行为移入相关对象之中。

3、将领域和显示分离

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
《重构 改善既有代码的设计 3》代码的可理解性应该是我们虔诚追求的目标