《重构 改善既有代码的设计》 读书笔记(十九)

6.2 内联函数(Inline Method)

如果一个函数本体和名称一样清楚易懂,就意味着这个函数没有什么作用,此时就可以去除函数调用,替换成函数中的内容。

动机

提炼函数有个度,过度提炼后,会发现小函数无处不在,特别频繁,此时就应该考虑,是不是有些函数可以合并起来呢?

提炼函数从某种意义来讲是一种间接性的体现,它可能带来帮助,但没必要的间接性会适得其反,反而加重了阅读代码的负担。

除此之外,还有一种需要使用内联函数的情况:当手头上的函数东一头西一头,逻辑很乱时,考虑将它们内联成一个大型函数,然后再分解成条理的小函数。

在进行以函数对象取代函数(6.8 Replace Method with Method Object)之前进行内联函数,会有好效果。

以函数对象取代函数(6.8 Replace Method with Method Object):将一群有强关联的函数都放到一个新类中去。当然,方法越少越好。

内联好处在于,能让人有个整体的感观,作为整体移动起来比较简单(如果间接层太多,互相调用过于频繁,会使得有些重构方法很难进行,所以,提炼函数请适可而止)

做法

  1. 检查函数,确定它不具多态性。

如果子类继承了这个函数,就不能把此函数内联。

  1. 找出这个函数的所有被调用点。

  2. 将这个函数的所有被调用点都替换为函数本体。

  3. 编译、测试。

  4. 删除该函数。

6.3 内联临时变量(Inline Temp)

你有一个临时变量,只被简单表达式赋值一次,而它妨碍了其他重构手法。

将所有对该变量的引用动作,替换为对它赋值的那个表达式本身。

double basePrice = anOrder.basePrice();
return (basePrice > 1000);

>>>
return (anOrder.basePrice() > 1000);

动机

这其实是很小的一个重构方法,和下一节所讲的以查询取代临时变量几乎一致,真正的动机也和下一节一样。

唯一单独使用内联临时变量的情况是:你发现某个临时变量被赋予某个方法调用的返回值。如果这个临时变量妨碍了提炼函数(6.1 Extract Method),那么就要将其内联化。

做法

  1. 检查给临时变量赋值的语句,确保等号右边的表达式没有副作用。

  2. 如果这个临时变量并未被声明为final,那就将它声明为final,然后编译。

这是为了检测该临时变量是否真的只被赋值一次。

  1. 找到该临时变量的所有引用点,将它们替换为”为临时变量赋值“的表达式。

  2. 每次修改后,编译并测试。

  3. 修改完所有引用点后,删除该临时变量的声明和赋值语句。

  4. 编译、测试。

6.4 以查询取代临时变量(Replace Temp with Query)

你的程序每少一个临时变量,就会多一个对某个表达式的引用点。

将这个表达式提炼到一个独立函数中。将这个临时变量的所有引用点替换为对新函数的调用。此后,新函数就可被其他函数使用。

double basePrice = quantity * itemPrice;
if(basePrice > 1000)
    return basePrice * 0.8;
else
    return basePrice * 0.9;

>>>
if(getPrice() > 1000)
    return getPrice() * 0.8;
else
    return getPrice() * 0.9;
...
double getPrice(){
    return quantity * itemPrice;
}

动机

首先从临时变量的作用域说起:它们只能在所属函数内使用。也就是说,如果这个变量从始至终贯穿整个方法,那么你就不得不写一个极长的函数来让它一直处于有效的作用域内。

此时,如果将它替换成一句查询,就意味着同一个类中的任意位置都能直接获取这个值,也就是说,我即便把方法分割开来,各部分都能够获取这句查询的值。

以查询取代临时变量往往在运用提炼函数(6.1 Extract Method)之前进行。

这个重构方法较为简单的情况是:临时变量只被赋值一次,或者赋值给临时变量的表达式不受其他条件印象。

但如果临时变量一直在改变,那么我们就不能直接使用这种重构方法,而是先运用分解临时变量(6.6 Split Temporary Variable)或者将查询函数和修改函数分离(10.4 Separate Query from Modifier)。

分解临时变量(6.6 Split Temporary Variable):如果这个临时变量中途被重新赋值(比如一开始a=1;,后来a=10这种直接赋值),那么重新赋值的这个点就可以分隔开,前后就应该分成两个截然不同的变量。

将查询函数和修改函数分离(10.4 Separate Query from Modifier):简单说就是,从前有个函数既修改了对象,又返回了值,那么就把它分成getter和setter两个方法。

这两种重构方法可以让临时变量的情况变得简单。(第一种能保证临时变量只被赋值一次,第二种没理解)

如果你想要替换的临时变量是用来收集结果的(例如循环累加值),就需要把这部分代码也加到查询函数中。(总之就是要通过查询拿到最后结果)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
第1章 重构,第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组Statemen 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 2.2 为何重构 2.3 何时重构 2.4 怎么对经理说 2.5 重构的难题 2.6 重构设计 2.7 重构与性能 2.8 重构起源何处 第3章 代码的坏味道 3.1 Duplicated Code(重复的代码) 3.2 Long Method(过长函数) 3.3 Large Class(过大类) 3.4 Long Parameter List(过长参数列) 3.5 Divergent Change(发散式变化) 3.6 Shortgun Surgery(霰弹式修改) 3.7 Feature Envy(依恋情结) 3.8 Data Clumps(数据泥团) 3.9 Primitive Obsession(基本型别偏执) 3.10 Switch Statements(switch惊悚现身) 3.11 Parallel Inheritance Hierarchies(平行继承体系) 3.12 Lazy Class(冗赘类) 3.13 Speculative Generality(夸夸其谈未来性) 3.14 Temporary Field(令人迷惑的暂时值域) 3.15 Message Chai (过度耦合的消息链) 3.16 Middle Man(中间转手人) 3.17 Inappropriate Intimacy(狎昵关系) 3.18 Alternative Classes with Different Interfaces(异曲同工的类) 3.19 Incomplete Library Class(不完善的程序库类) 3.20 Data Class(纯稚的数据类) 3.21 Refused Bequest(被拒绝的遗赠) 3.22 Comments(过多的注释) 第4章 建立测试体系 4.1 自我测试码的价值 4.2 JUnit测试框架 4.3 添加更多测试 第5章 重构名录 5.1 重构的记录格式 5.2 寻找引用点 5.3 这些重构准则有多成熟 第6章 重新组织你的函数 6.1 Extract Method(提炼函数) 6.2 Inline Method(将函数内联化) 6.3 Inline Temp(将临时变量内联化) 6.4 Replace Temp With Query(以查询取代临时变量) 6.5 Introduce Explaining Variable(引入解释性变量) 6.6 Split Temporary Variable(剖解临时变量) 6.7 Remove Assignments to Paramete (移除对参数的赋值动作) 6.8 Replace Method with Method Object(以函数对象取代函数) 6.9 Substitute Algorithm(替换你的算法) 第7章 在对象之间移动特性 7.1 Move Method(搬移函数) 7.2 Move Field(搬移值域) 7.3 Extract Class(提炼类) 7.4 Inline Class(将类内联化) 7.5 Hide Delegate(隐藏「委托关系」) 7.6 Remove Middle Man(移除中间人) 7.7 Introduce Foreign Method(引入外加函数) 7.8 Introduce Local Exte ion(引入本地扩展) 第8章 重新组织你的数据 8.1 Self Encapsulate Field(自封装值域) 8.2 Replace Data Value with Object(以对象取代数据值) 8.3 Change Value to Reference(将实值对象改为引用对象) 8.4 Change Reference to Value(将引用对象改为实值对象) 8.5 Replace Array with Object(以对象取代数组) 8.6 Duplicate Observed Data(复制「被监视数据」) 8.7 Change Unidirectional Association to Bidirectional(将单向关联改为双向) 8.8 Change Bidirectional Association to Unidirectional(将双向关联改为单向) 8.9 Replace Magic Number with Symbolic Co tant (以符号常量/字面常量 取代魔法数) 8.10 Encapsulate Field(封装值域) 8.11 Encapsulate Collection(封装群集) 8.12 Replace Record with Data Class(以数据类取代记录) 8.13 Replace Type Code with Class(以类取代型别码) 8.14 Replace Type Code with Subclasses (以子类取代型别码) 8.15 Replace Type Code with State/Strategy (以State/Strategy取代型别码) 8.16 Replace Subclass with Fields(以值域取代子类) 第9章 简化条件表达式 9.1 Decompose Conditional(分解条件式) 9.2 Co olidate Conditional Expression(合并条件式) 9.3 Co olidate Duplicate Conditional Fragments (合并重复的条件片段) 9.4 Remove Control Flag(移除控制标记) 9.5 Replace Nested Conditional with Guard Clauses (以卫语句取代嵌套条件式) 9.6 Replace Conditional with Polymorphism(以多态取代条件式) 9.7 Introduce Null Object(引入Null对象) 9.8 Introduce Assertion(引入断言) 第10章 简化函数呼叫 10.1 Rename Method(重新命名函数) 10.2 Add Parameter(添加参数) 10.3 Remove Parameter(移除参数) 10.4 Separate Query from Modifier(将查询函数和修改函数分离) 10.5 Parameterize Method(令函数携带参数) 10.6 Replace Parameter with Explicit Methods(以明确函数取代参数) 10.7 Preserve Whole Object(保持对象完整) 10.8 Replace Parameter with Method(以函数取代参数) 10.9 Introduce Parameter Object(引入参数对象) 10.10 Remove Setting Method(移除设值函数) 10.11 Hide Method(隐藏你的函数) 10.12 Replace Co tructor with Factory Method(以工厂方法取代构造函数) 10.13 Encapsulate Downcast(封装「向下转型」动作) 10.14 Replace Error Code with Exception(以异常取代错误码) 10.15 Replace Exception with Test(以测试取代异常) 第11章 处理概括关系 11.1 Pull Up Field(值域上移) 11.2 Pull Up Method(函数上移) 11.3 Pull Up Co tructor Body(构造函数本体上移) 11.4 Push Down Method(函数下移) 11.5 Push Down Field(值域下移) 11.6 Extract Subclass(提炼子类) 11.7 Extract Superclass(提炼超类) 11.8 Extract Interface(提炼接口) 11.9 Collapse Hierarchy(折叠继承体系) 11.10 Form Template Method(塑造模板函数) 11.11 Replace Inheritance with Delegation(以委托取代继承) 11.12 Replace Delegation with Inheritance(以继承取代委托) 第12章 大型重构 12.1 Tease Apart Inheritance(疏理并分解继承体系) 12.2 Convert Procedural Design to Objects(将过程化设计转化为对象设计) 12.3 Separate Domain from Presentation(将领域和表述/显示分离) 12.4 Extract Hierarchy(提炼继承体系) 第13章 重构,复用,与现实 13.1 现实的检验 13.2 为什么开发者不愿意重构他们的程序 13.3 再论现实的检验 13.4 重构的资源和参考数据 13.5 从重构联想到软件复用和技术传播 13.6 结语 13.7 参考文献 第14章 重构工具 14.1 使用工具进行重构 14.2 重构工具的技术标准 14.3 重构工具的实用标准 14.4 小结 第15章 总结 参考书目 要点列表 索引

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NewReErWen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值