《重构-改善既有代码的设计》系列读书笔记(六、简化函数调用)

简化函数调用

Rename Method (函数改名)

动机
  • 函数名称应该准确表达它的用途,在给函数命名时,首先考虑给这个函数写上一句怎样的注释,然后根据这句注释来命名。
  • 警惕以“将就用”的动机起名。

Add Paramenter(添加参数)

某个函数需要从调用端得到更多信息。

动机
  • 只有在其他方式不能提供更多的信息时,才可以采用这种重构方式,添加参数意味着增加接口复杂度。

Remove Paramenter(移除参数)

函数本身不再需要某个参数

动机
  • 移除参数和添加参数同样重要
  • 多态函数需要谨慎

Seperate Query from Modifier(将查询函数和修改函数分离)

某个函数既返回对象状态值,又修改对象状态值

动机
  • 任何有返回值的函数,都不应该有看得到的副作用。
  • 函数的单一职能原则。

Parameterize Method (令函数携带参数)

若干函数做了类似的工作,但在函数本体中却包含了不同的值。

动机
  • 将多个类似的函数合并,通过参数控制具体执行逻辑,可以简化问题,消除重复。

Replace Paramenter with Explicit Methods(以明确函数取代参数)

你有一个函数,其中完全取决于参数值而采取不同行动

动机
  • 函数单一职能原则
  • 参数决定函数行为时,参数的合法判断可能并未在文档中提出,导致理解和调用困难
做法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// before
static final int ENGINEER = 0;
static final int SALESMAN = 1;
static final int MANAGER = 2;
static Employee create(int type) {
switch (type) {
case ENGINEER:
return new Engineer();
case SALESMAN:
return new Salesman();
case MANAGER:
return new Manager();
default:
...
}
}
Employee kent = Employee.create(ENGINEER);
//after
static Employee createEngineer() {
return new Engineer();
}
static Employee createSalesman() {
return new Salesman();
}
static Employee createManager() {
return new Manager();
}
Employee kent = Employee.createEngineer();

Preserve Whole Object(保持对象完整)

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

动机
  • 以对象作为参数可能会让函数参数列更稳固,并能提高代码的可读性。
  • 如果以对象作为参数对类的依赖关系影响较大,则不应该采取这种方式。
  • 是否使用只取决于依赖关系是否复杂,而不应该依赖所需的参数的数量。

Replace Parameter with Methods(以函数取代参数)

参数的实参来自于一个函数

动机
  • 如果函数能够通过其他方式拿到参数值,那么它就不应该再通过参数传递的方式取值。
  • 多此一举,增加一个参数反而增加了代码的复杂性。
  • less is more。
做法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public double getPrice() {
int basePrice = _quantity * _itemPrice;
int discountLevel;
if (_quantity > 100) discountLevel = 2;
else discountLevel = 1;
double finalPrice = discountedPrice(basePrice,discountLevel);
return finalPrice;
}
private double discountedPrice(int basePrice,int discountLevel) {
if (discountLevel == 2) return basePrice * 0.1;
else return basePrice * 0.05;
}
// after
private double getDiscountLevel() {
if (_quantity > 100) return 2;
else return 1;
}
private double getBasePrice() {
return _quantity * _itemPrice;
}
public double getPrice() {
if (getDiscountLevel() == 2) return getBasePrice() * 0.1;
else return getBasePrice() * 0.05;
}

Introduce Parameter Object(引入参数对象)

某些参数总是很自然的同时出现

动机
  • 同时出现的一组参数往往形成“数据泥团”
  • 对象的引入可以减少重复的代码

Remove Setting Method 移除设值函数

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

动机
  • 如果你为某个字段提供了设值函数,就暗示这个字段可以被改变。
  • 如果你保留了间接访问变量的方法,就可能经常有程序员盲目的使用他们。

Hide Method(隐藏函数)

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

动机
  • 重构往往促使你修改函数的可见度,根据实际情况提高或者降低函数可见度。

Replace Constructor with Factory Method(以工厂函数取代构造函数)

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

动机
  • 较典型的应用场景是在派生类的过程中以工厂函数取代类型码
做法
  • 工厂一:所有类型公用同一个方法,根据类型创建不同实例。
  • 工厂二:为每一个子类型创建属于自己的工厂方法,只返回自身实例。

Encapsulate Downcast(封装向下转型)

Replace Error Code with Exception(以异常取代错误码)

Replace Exception with Test(以测试取代异常)