好友
阅读权限10
听众
最后登录1970-1-1
|
象相合
发表于 2017-12-24 18:56
本帖最后由 象相合 于 2017-12-24 19:03 编辑
大家好,这次给大家带来《重构》的最后一部分了,以下是本帖的内容概要:
一、更新的重构原则【完结】
二、简化函数调用系手法。
三、处理概括关系的手法。
四、大型重构系手法。
五、一些瞎扯。
本来想写成一个大家一看就懂的重构手法集合,但是因为水平有限,写成了一个“根据不同情况使用不同重构手法”的索引。在此向各位致歉。
对于大型重构手法,可能会比较笼统,因为它一句话已经完成了概括,再去添话又显多余。因此,还需各位自行下载本书观摩手法。
那么以下是整理内容:
一、更新的重构原则【完结】
- 为即将修改的代码建立一组可靠的测试环境。
- 临时变量助长冗长而复杂的函数。
- 最好不要再另一个对象的属性基础上运用switch语句。如果要switch也要在类自己的数据上使用。
- 事不过三,三则重构。
- 首先写出可调的程序,然后调整它以求获得足够速度。
- 一个好的名字可以省去读函数内容的操作。
- 每当需要注释说明时,可以被写进一个函数里,并以用途命名,关键不在函数长度,而在函数做什么,怎么做。
- 条件和循环也是提炼信号。
- 针对外界变化的所有相应修改,应该只发生在单一类中,这个类的所有内容随外界变化。
- 一个函数使用几个类的功能,它应该被放在最多被此函数使用的数据一起。
- 对于出现在不同类/方法内的一些绑在一起的数据,应该给它们设置对象。
- 少用switch,switch代表重复。
- 两个帽子原则:不要边写代码边重构,带上写代码的帽子,觉得需要重构了,再带上重构的帽子去做,如此反复。
- 注释多写为什么这样,过多注释不一定是好,尝试重构。
- 先编写测试代码可以将关注点放在接口而非实现。
- 每当出现一个BUG,先写一个测试单元测试BUG。不要修改以前的测试单元,因为它可能会在修复BUG后出错。
- 测试:异常,边界
- 测试太多带来的效益呈现递减态势。但是我们尽量测试大多数BUG。
- 小步前进,频繁测试。
- 即使想要提炼的函数非常简单,只要新函数名能更好地示意代码意图,也应该提炼它。
- 重构出来的函数优先使用private修饰,日后可以慢慢放开。
- 重构时可能会有性能问题,但这不是主要问题,如果没有重构,好的优化方案就可能与你失之交臂。性能实在太糟糕,临时变量放回去也很容易。
- 临时变量如果被赋值多次,尽量使它们只使用一次。
- JAVA只采用按值传递参数,因此对参数赋值一般不可取,不要对参数赋值。
- public不是java的全部,java值得封装的东西有很多。
- 先写测试,再写类。
- 去除控制标记,语句会清晰明了。
- “每一个函数只能有一个入口和一个出口”的观念会使人陷入代码的坏味道。
- 条件反转有时候可以帮助写清晰的代码。
- if then else也代表重复,尽量不要写。
- 使用空对象可以方便的处理很多东西,它一定是常量。非常适合使用Singleton模式。
- 一个好习惯:明确地将“修改对象状态”的函数(修改函数)和“查询对象状态”的函数(查询函数)分开设计。
- 继承是避免重复行为的一个强大工具。
- 对于辣鸡代码,不必一开始就完成整个系统的重构,只需要满足需求就行了,反正之后还可以回来重构。
二、简化函数调用系手法。
- 函数的名称未能揭示函数的用途。修改函数名称。
- 改函数名能帮助后来者理解程序。在这个手法里你甚至可以修改参数顺序。
2. Add Parameter添加参数 300
- 某个函数需要从调用端得到更多信息:为此函数添加一个对象参数,让该对象带进函数所需信息。
- 使用这个手法会增加过多参数的坏味道。
3. Remove Parameter移除参数 302
- 函数本体不再需要某个函数。将该参数去除。
- 函数的无用参数可以去除,多态的无用参数可以保留。
4. Separate Query from Modifier将查询函数和修改函数分离 304
- 某个函数即返回对象状态值,又修改对象状态:建立两个不同的函数,其中一个负责查询,另一个负责修改。
- 将动作分开,浪费一点性能,但是很好看。
5. Parameterize Method令函数携带参数 308
- 若干函数做了类似的工作,但在函数本体中却包含了不同的值:建立单一函数,以参数表达那些不同的值。
6. Replace Parameter with Explicit Methods以明确函数取代参数 310
- 你有一个函数,其中完全取决于参数值而采取不同行为:针对该参数的每一个可能值,建立一个独立函数。
- 参数在一个方法内被重复使用,可以针对参数提取一个方法。
7. Preserve Whole Object保持对象完整 313
- 你从某个对象中取出若干值,将它们作为某一次函数调用时的参数:改为传递整个对象。
- 与其对象的属性设为参数,不如直接传送对象。在里面调参。
- 如果想使用这个手法前没有对象,先使用Introduce Parameter Object
8. Replace Parameter with Methods以函数取代参数 317
- 对象调用某个函数,并将所得结果作为参数,传递给另一个函数。而接受该参数的函数本身也能够调用前一个函数:让参数接受者去除该项参数,并直接调用前一个函数。
- 去除冗余调用函数的参数。
9. Introduce Parameter Object引入参数对象 320
- 某些参数总是很自然地同时出现:以一个对象取代这些参数。
10. Remove Setting Method移除设值函数 325
- 类中的某个字段应该在对象创建时被设值,然后就不再改变:去掉该字段的所有设值函数。
11. Hide Method隐藏函数 328
- 有一个函数,从来没有被其他任何类用到:将这个函数修改为private。
12. Replace Constructor with Facotry Method以工厂函数取代构造函数 329
- 你希望在创建对象时不仅仅是做简单的建构动作:将构造函数替换为工厂函数。
- 工厂函数产生的对象可以做更多事情。
13. Encapsulate Downcast封装向下转型 333
- 某个函数返回的对象,需要由函数调用者执行向下转型(downcast):将向下转型动作移到函数中。
- 向下转型应尽量少做,但有时候要告诉客户转型类型,这时也是必须的。
- 使用这个手法前,应先考虑是否可以以模板类代替。
14. Replace Error Code wtih Exception以异常取代错误码 335
- 某个函数返回一个特定的代码,用以表示某种错误情况:改用异常。
- 灵活使用异常不仅方便理解,也提供方便的处理方式。
15. Replace Exception with Test以测试取代异常 340
- 面对一个调用者可以预先检查的条件,你抛出一个异常:修改调用者,使它在调用函数之前先做检查。
- 与其catch异常,不如先if把异常情况过滤。
三、处理概括关系的手法。
2. Pull Up Method函数上移 347
- 有些函数,在各个子类中产生完全相同的结果:将该函数移至超类。
3. Pull Up Constructor Body构造函数本体上移 350
- 你在各个子类中拥有一些构造函数,它们的本体几乎完全一致:在超类中新建一个构造函数,并在子类构造函数中调用它。
- 如果过于复杂,使用Replace Constructor with Factory Method。
4. Pull Down Method函数下移 353
- 超类中的某个函数只与部分子类有关:将这个函数移到相关的那些子类去。
- public声明可以改为protected
5. Push Down Filed字段下移 354
- 超类中的某个字段只被部分子类用到:将这个字段移到需要它的那些子类去。
6. Extract Subclass提炼子类 355
- 类中的某些特性只被某些实例用到:新建一个子类,将上面所说的那一部分特性移到子类中。
7. Extract Superclass提炼超类 361
- 2个类有相似特性:为这2个类建立一个超类,将相同特性移至超类。
8. Extract Interface提炼接口
- 若干客户使用类接口中的同一子集,或者2个类的接口部分相同:将相同的子集提炼到一个独立接口中。
- 提炼接口能帮助看清子类里的东西。
9. Collapse Hierarchy折叠继承体系 369
10. Form TemPlate Method塑造模板函数 370
- 你有一些子类,其中相应的某些函数以相同的顺序执行类似的操作,但各个操作的细节不同:将这些操作分别放进独立的函数中,并保持它们都有相同的签名,于是原函数也就变得相同了,然后将原函数上移至超类。
- 继承是避免重复行为的一个强大工具。
11. Replace Inheritance with Delegation以委托取代继承 377
- 某个子类只使用超类接口中的一部分,或是根本不需要继承而来的数据:在子类中新建一个字段用以保存超类;调整子类函数,令它改而委托超类;然后去掉2者之间的继承关系。
- 如果接受传统说法:子类可以只使用超类功能的一部分。会导致意图南辕北辙,应该将他去除。使用委托可以很好解决这种情况。
12. Replace Delegation with Inheritance以继承取代委托 380
- 你在2个类之间使用委托关系,并经常为整个接口编写许多极简单的委托函数:让委托类继承受托类。
- 与11相反。
四、大型重构系手法。
- Tease Apart Inheritance梳理并分解继承体系 387
- 某个继承体系同时承担两项责任:建立两个继承体系, 并通过委托关系让其中一个可以调用另一个。
2. Convert Procedural Design to Objects将过程化设计转化为对象设计
- 你手上有一些传统过程化风格的代码:将数据记录变成对象, 将大块的行为分成小块, 并将行为移入相关对象中.
3. Separate Domain from Presentation将领域和表述/显示分离
- 某些GUI类之中包含了领域逻辑:将领域逻辑分离出来, 为它们建立独立的领域类.
4. Extract Hierarchy提炼继承体系 400
- 你有某个类做了太多工作, 其中一部分工作是以大量条件表达式完成的:建立继承体系, 以一个子类表示一种特殊情况.
五、一些瞎扯。
可能有些同学会觉得看不懂,可能是 我认为作者的第一条介绍已经提供了清晰的方法,不需要再去加内容。(也可能是作者的图文介绍太过清晰,而整理的文字介绍过于严谨,导致我能够看懂,而没有将关键解释出来)。
另外,感谢matchcolor与RedRain提供的内容手法为码字节约时间:
http://www.cnblogs.com/matchcolor/archive/2010/08/12/1786451.html
https://www.jianshu.com/p/d64b0ba76b31
最后,祝各位同学学习进步!
|
免费评分
-
查看全部评分
|
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。 |
|
|
|
|