第2章 重新组织函数(2):内联函数、内联临时变量和查询函数
2016-10-07 11:42
232 查看
2. 内联函数(Inline Method)
2.1 动机
(1)在函数调用点插入函数本体,然后移除该函数。
(2)有时遇到某些函数,其内部代码和函数名称同样清晰易读,采用内联函数可以提供代码的执行速度(因为少掉了函数调用的开销)
(3)在Replace Method withd Method Object之前,将一些组织不合理的函数内联到一个大型函数,再从中提炼组织合理的小型函数时效果很好。
(4)使用太多的间接层时,特别是一部分函数只是对另一个函数的简单委托时,可同去掉一些无用的间接层。
2.2 做法
(1)检查函数,确定它不具有多态性。如果子类继承了这个函数,就不要将此函数内联,因为子类无法覆写一个根本不存在的函数。
(2)找出这个函数的所有被调用点。
(3)将这个函数的所有被调用点都替换为函数本体
(4)删除该函数的定义
2.3 范例
2.4 思考
(1)对于递归、多返回点不适合用内联函数来重构
(2)内联至另一个对象中,而该对象并无提供访问函数。这种情况也不适合使用这个重构手法。
3. 内联临时变量
3.1 动机
(1)内联临时变量多半是作为Replace Temp with Query的一部分使用,所以真正的动机出现在后者那儿。
(2)如果某个临时变量被赋值为某个函数的返回值。一般这个临时变量不会有任何危害,可以保留下来。但这样的变量会妨碍重构,使重构变成比较困难,所以可以将它内联化。
3.2 做法
(1)检查临时变量赋值的语句,确保等号右边的表达式没有副作用
(2)将该变量声明改为const变量,以确定该变量真的只被赋值一次。
(3)找到该临时变量的所有引用点,将它们替换为“为临时变量赋值的”表达式
(4)删除该临时变量的声明和赋值语句。
3.3 范例
4. 以查询取代临时变量(Replace Temp with Query)
4.1 动机
(1)临时变量的问题在于它们是暂时的,而且只能在所属函数使用。因此会导致写出来的函数更长,因为只有这样才能访问到需要的临时变量。可以将临时变量替换为一个查询,这将帮助我们编写更清晰的代码。
(2)Replace Temp with Query往往是ExtractMethod之前必不可少的步骤。因为局部变量会使代码难以被提炼,所以应尽可能将它们替换为查询函数。
4.2 做法
(1)找出只被赋值一次的临时变量。如果某个临时变量被赋值超过一次,考虑使用Split Temporary Variable将它们分割成多个变量。
(2)将该临时变量声明为const变量。然后编译,以确保只会被赋值一次
(3)将“对该临时变量赋值”之语句的等号右侧部分提炼到一个独立函数中。
(4)在临时变量身上实施Inline Temp。
4.3 范例
//重构前
//重构后
4.4 思考
(1)如果临时变量保存循环中的累加信息,则整个循环可以被提炼到一个独立函数中去。
(2)这种手法会导致性能问题,但这种影响一般很小。
2.1 动机
(1)在函数调用点插入函数本体,然后移除该函数。
(2)有时遇到某些函数,其内部代码和函数名称同样清晰易读,采用内联函数可以提供代码的执行速度(因为少掉了函数调用的开销)
(3)在Replace Method withd Method Object之前,将一些组织不合理的函数内联到一个大型函数,再从中提炼组织合理的小型函数时效果很好。
(4)使用太多的间接层时,特别是一部分函数只是对另一个函数的简单委托时,可同去掉一些无用的间接层。
2.2 做法
(1)检查函数,确定它不具有多态性。如果子类继承了这个函数,就不要将此函数内联,因为子类无法覆写一个根本不存在的函数。
(2)找出这个函数的所有被调用点。
(3)将这个函数的所有被调用点都替换为函数本体
(4)删除该函数的定义
2.3 范例
//重构前 int getRating() { return moreThanFiveLateDeliveries() ? 2 : 1; } bool moreThanFiveLateDeliveries() { return _numberOfLateDeliveries > 5; } //重构后 int getRating() { return (_numberOfLateDeliveries > 5) ? 2 : 1; }
2.4 思考
(1)对于递归、多返回点不适合用内联函数来重构
(2)内联至另一个对象中,而该对象并无提供访问函数。这种情况也不适合使用这个重构手法。
3. 内联临时变量
3.1 动机
(1)内联临时变量多半是作为Replace Temp with Query的一部分使用,所以真正的动机出现在后者那儿。
(2)如果某个临时变量被赋值为某个函数的返回值。一般这个临时变量不会有任何危害,可以保留下来。但这样的变量会妨碍重构,使重构变成比较困难,所以可以将它内联化。
3.2 做法
(1)检查临时变量赋值的语句,确保等号右边的表达式没有副作用
(2)将该变量声明改为const变量,以确定该变量真的只被赋值一次。
(3)找到该临时变量的所有引用点,将它们替换为“为临时变量赋值的”表达式
(4)删除该临时变量的声明和赋值语句。
3.3 范例
//内联临时变量 //重构前 double basePrice = anOrder.basePrice(); //basePrice只被赋值一次 return (basePrice > 1000) //重构后 return (anOrder.basePrice() > 1000);
4. 以查询取代临时变量(Replace Temp with Query)
4.1 动机
(1)临时变量的问题在于它们是暂时的,而且只能在所属函数使用。因此会导致写出来的函数更长,因为只有这样才能访问到需要的临时变量。可以将临时变量替换为一个查询,这将帮助我们编写更清晰的代码。
(2)Replace Temp with Query往往是ExtractMethod之前必不可少的步骤。因为局部变量会使代码难以被提炼,所以应尽可能将它们替换为查询函数。
4.2 做法
(1)找出只被赋值一次的临时变量。如果某个临时变量被赋值超过一次,考虑使用Split Temporary Variable将它们分割成多个变量。
(2)将该临时变量声明为const变量。然后编译,以确保只会被赋值一次
(3)将“对该临时变量赋值”之语句的等号右侧部分提炼到一个独立函数中。
(4)在临时变量身上实施Inline Temp。
4.3 范例
//重构前
//用查询替换临时变量 //重构前(目标:basePrice和discountFactor替换掉) double getPrice() { int basePrice = _quantity * _itemPrice; //_quantity和_itemPrice为成员变量 double discountFactor; if(basePrice > 1000) discountFactor = 0.95 else discountFactor = 0.98; return basePrice * discountFactor; }
//重构后
//重构后 double getPrice() { return basePrice() * discountPrice(); } //计算底价 double basePrice() { return _quantity * _itemPrice; } //打折因子(类中声明为private函数) double discountFactor() { //此处的basePrice()也是个查询函数,由于替换去除了临时变量 //使得discountFactor函数的重构成为可能! if(basePrice() > 1000) return 0.95; else return 0.98; }
4.4 思考
(1)如果临时变量保存循环中的累加信息,则整个循环可以被提炼到一个独立函数中去。
(2)这种手法会导致性能问题,但这种影响一般很小。
相关文章推荐
- 第2章 重新组织函数(3):引入解释性变量、分解临时变量和移除对参数的赋值
- 重新组织函数--以查询取代临时变量(Replace Temp with Query)
- 重新组织你的函数之三 :Inline Temp(将临时变量内联化)
- 重新组织函数--Split Temporary Variable(分解临时变量)
- 重新组织你的函数之五 :Introduce Explaining Variable(引入解释性变量)
- SQL查询时常用,但不熟悉的相关语句-----邮标,行号,临时表,类型转换,字符串函数,sql 判断语句,检查是不是数字,变量,sql split 函数
- 第2章 重新组织函数(4):函数对象、替换算法
- 第2章 重新组织函数(1):提炼函数
- 重新组织函数--Introduce Explaining Variable(引入解释性变量)
- 何时提炼函数 & 用查询取代临时变量
- 重新组织函数--Inline Method(内联函数)
- 作为函数参数的临时变量的引用必须是const的
- 第六章 重新组织你的函数
- 函数调用时的栈帧结构以及临时变量的深入研究
- 重新组织函数
- 函数内临时变量的释放时刻
- cgic中常用的函数和变量以及返回类型 (可作为工具查询)
- 重新组织函数
- PHP 杂谈《重构-改善既有代码的设计》之一 重新组织你的函数
- 将临时变量内联化 & 以查询代替临时变量