[读书笔记] 重构改善既有代码的设计(4)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/beyongwang/article/details/70880215

最近比较忙,偷闲整理下第六章的内容,关于重新组织函数的内容。

1. 提炼函数

比较简单但又很常用的手法,目的是把一段逻辑上紧密联系构成相对独立功能块的代码封装起来,通过函数名字清晰的表达其用途,这样潜在的提供了其他模块复用该函数的概率,同时也更加易于维护,因为原来嵌在一大段逻辑中的代码被抽离出来了,对其修改不必在去关系大范围的影响。实施这个重构手法时要注意涉及的上下文变量,可以通过参数,返回值,甚至是添加成员变量的形式进行转化。

2. 内敛函数(inline)

实际上是第一条的逆向,即将过于简单的函数消除掉,通过函数本身就可以清楚的表达函数的意思,这样可以消除不必要的间接性。一个例子是当函数中有调用函数,而调用者又没有做其他操作,只是单纯的调用,例如:

void A()
{
    B()
}
void B()
{
    C()
}

完全可以把C展开,B也展开,直接写成:

void A()
{
...//codes from C
}

3. 内敛临时变量

如果某个临时变量只是被简单的赋值了一次,然而他的存在会妨碍其他重构手法(例如第一条),那么消除该变量,直接使用赋值的来源。

4. 以查询取代临时变量

这个实际就是将临时标量封装成函数,这样就可以被其他地方调用,因为临时变量是暂时的,只能在其所属的函数内使用,而且这会驱使我们写入更长的函数,因为这样才能延长临时变量的生命周期,让更多的代码看到它,如果把临时变量封装成函数,就可以在类范围内共享它的信息。

5. 引入解释性变量

这个是引入临时变量的过程,比如有这样形式的代码if((…1) && (…2) && (…3)),其中…1,…2,…3中是相对复杂的逻辑运算,此时这个组合很容易让人迷惑,因为太多逻辑判断了,此时,就可以引入三个命名妥当的临时变量,改成如下形式:

logic1 = ...1;
logic2 = ...2;
logic3 = ...3;
if(logic1 && logic2 &&logic3)...

这样代码就清晰很多,而且便于调试,因为一旦发现这里的逻辑结果有问题,就可以分别来看到底是那一个分支出现问题。另一个常用场景是较长的算法中引入一些临时变量来解释某些中间结果。

6. 分解临时变量

是指某一个临时变量被多次赋值,而这些赋值之间是相对独立的,例如:

int temp = A();
...
temp = B();
...
temp = C()

此时应该针对不同的操作,创建同的变量:

int tempA = A();
...
int tempB = B();
...
int tempC = C()

这样更符合单一职责的原则,更加不容易出错,除非该变量是收集多次运算结果的,比如累加变量。

7. 移除对参数的赋值

这个是指某个参数被传递进来,函数中对该参数赋值,也就是改变了该参数的值,如果是要作为输出参数,那么要遵循所在团队的规范,例如输出参数全部放在参数坐后面等等,如果不是,则建立一个临时变量,接受该参数。

8. 以函数对象取代函数

如果在提取函数时,发现大量的局部变量,那么分解这个函数将非常困难,此时可以考虑将该函数提炼成为一个类,这样所有的局部变量可以变成成员变量。

9. 替换算法

这个很容易理解,当你发现某段复杂的处理方法,可以用另外一种功能上相同,却又更简单更易于理解,那么果断使用后者代替前者,当然,这个是基于你完全确定后者在功能上跟前者完全一致。

展开阅读全文

没有更多推荐了,返回首页