好友
阅读权限10
听众
最后登录1970-1-1
|
象相合
发表于 2017-12-9 15:03
本帖最后由 象相合 于 2017-12-9 15:06 编辑
大家好,我又来了。这一周介绍以下内容与大家分享:
这篇文章整合了《重构-改善既有代码设计》5-7章的一些信息。主要有
1. 更新了分析整理的重构原则。
2. 对于操作“方法”的一些重构手法。
3. 对于操作“对象”的一些重构手法。
4. GitHub项目分享。
分享给大家,希望大家喜欢。链接:电子书。
一、重构原则:
- 为即将修改的代码建立一组可靠的测试环境。
- 临时变量助长冗长而复杂的函数。
- 最好不要再另一个对象的属性基础上运用switch语句。如果要switch也要在类自己的数据上使用。
- 事不过三,三则重构。
- 首先写出可调的程序,然后调整它以求获得足够速度。
- 一个好的名字可以省去读函数内容的操作。
- 每当需要注释说明时,可以被写进一个函数里,并以用途命名,关键不在函数长度,而在函数做什么,怎么做。
- 条件和循环也是提炼信号。
- 针对外界变化的所有相应修改,应该只发生在单一类中,这个类的所有内容随外界变化。
- 一个函数使用几个类的功能,它应该被放在最多被此函数使用的数据一起。
- 对于出现在不同类/方法内的一些绑在一起的数据,应该给它们设置对象。
- 少用switch,switch代表重复。
- 两个帽子原则:不要边写代码边重构,带上写代码的帽子,觉得需要重构了,再带上重构的帽子去做,如此反复。
- 注释多写为什么这样,过多注释不一定是好,尝试重构。
- 先编写测试代码可以将关注点放在接口而非实现。
- 每当出现一个BUG,先写一个测试单元测试BUG。不要修改以前的测试单元,因为它可能会在修复BUG后出错。
- 测试:异常,边界
- 测试太多带来的效益呈现递减态势。但是我们尽量测试大多数BUG。
- 小步前进,频繁测试。
- 即使想要提炼的函数非常简单,只要新函数名能更好地示意代码意图,也应该提炼它。
- 重构出来的函数优先使用private修饰,日后可以慢慢放开。
- 重构时可能会有性能问题,但这不是主要问题,如果没有重构,好的优化方案就可能与你失之交臂。性能实在太糟糕,临时变量放回去也很容易。
- 临时变量如果被赋值多次,尽量使它们只使用一次。
- JAVA只采用按值传递参数,因此对参数赋值一般不可取,不要对参数赋值。
- public不是java的全部,java值得封装的东西有很多。
- 先写测试,再写类。
二、对于操作“方法”的一些重构手法:
1. Extract Method(110)
- 一个过长的需要注释的代码出现时使用。
- 返回变量多余一个:挑选另一块代码提炼。
- 用Replace Temp with Query(120)/Replace Method with Method(135)减少临时变量。
2. Inline Method(内联函数)
- 手上有一群组织不合理的函数:先内联到大型函数,再提炼出小型函数。
- 委托太多:使用内联函数,找出有用/无用的间接层。
- 不能具有多态性。
- 遇到递归调用,多返回点,内联至另一个对象而该对象无提供访问函数等复杂情况不该使用这个手法。
3. Inline Temp(内联临时变量)
- Replace Temp with Query(120)的一部分。
4. Replace Temp with Query(以查询取代临时变量)
- 局部变量变成查询式可以方便看清函数构造。
- 临时变量赋值多次的情况:先使用Split Temporary Variable(128)或Separate Query from Modifier(279)使情况变简单。
5. Introduce Explaning Variable引入解释性变量
- 引入final解释性变量增强理解。
- 一般使用Extract Method解释代码更有意义。
- 在Extract Method需要大量工作量时,使用它清理代码。
6. Split Temporary Variable分解临时变量
- 临时变量被多次使用时使用它分解为多个final临时变量。临时变量使用多次会引起歧义。
- 如果临时变量有[i=i+表达式](引用自身)形式,它就是结果收集变量,不该分解。
7. Remove Assignments to Parameters移除对参数的赋值
- JAVA只采用按值传递参数:使用它移除对参数赋值,实在要赋值使用[.方法]修改。
- 面对出参数类型的语言可以无视这个手法。
- 在较长的函数中使用final修饰参数,防止参数被修改。
8. Replace Method with Method Object以函数对象取代函数(函数中的大杀器)
- 局部变量导致无法提取函数使用:把函数放进对象中,在同一对象将大型函数分解成多个小型函数。
- 新类->final字段->构造函数->建立compute()函数->编译->拆分。
9. Substitute Algorithm替换算法
- 有时候壮士断腕,直接替换更便捷的算法可以减少修改成本。
- 对于测试用例,以新旧算法执行,观察结果是否相同,可以快速确定问题所在。
二、对于操作“对象”的一些重构手法:
1. Move Method搬移函数
- 函数与另一个类有更多引用。
- 如果无法决定是否移动一个函数,先放着看看其他函数。
- 特性随着函数搬移。以特征为基点搬移函数。
- 原函数可以删除,也可以委托,这需要决断。
2. Move Field搬移字段
- 某个字段被其所驻类外另一个类更多使用。
- 如果移动的是频繁访问的字段函数,先使用SelfEncapsulate Field也许更有帮助。
- 源字段的引用替换为目标函数调用。
- 先生成构造方法Self Encapsulate Field(171),再做委托更好用。
3. Extract Class提炼类
- 当某个类做了两个类该做的事:使用它提炼新的类。
- 提炼的类最好不要双向连接。
- 提炼完成后,考虑权限问题。
4. Inline Class将类内联化
- 某个类没做太多事情:使用它移到另一个类里。与Extract Class相对。
5. Hide Delegate隐藏“委托关系”
- 客户通过委托调用另一个对象,在服务类建立客户所需函数,隐藏委托关系。
- 考虑访问权限。
6. Remove Middle Man移除中间人
- 某个类过多简单委托动作,让客户直接调用受托类。Hide Delegate的反面。
7. Introduce Foreign Method引入外加函数
- 为提供服务类增加一个函数,但无法修改这个类:建立一个函数,并以第一参数传入服务类实例。
8. Introduce Local Extension引入本地扩展
- 需要为服务类提供额外函数,但无法修改这个类:建立一个新类,使它包含额外函数,让这个扩展名成为源类的子类或包装类。
- 建立拓展类->加入转型构造函数->加入新特性->将原对象替换扩展对象->原始类定义的外加函数搬移到扩展类。
- 一般不要重新复写函数,使用扩展类可以很好解决问题。便于查找。
四、GitHub项目分享:https://github.com/EleComb/Reconstruction
以上,理论需要实践的基础提供,自己动手做一遍肯定比看一遍来的实在。最后,祝大家学习进步! |
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|