吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3335|回复: 7
收起左侧

[Java 转载] 《重构-改善既有代码的设计》【10-12】章学习分享【完结】

[复制链接]
象相合 发表于 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模式。
  • 一个好习惯:明确地将“修改对象状态”的函数(修改函数)和“查询对象状态”的函数(查询函数)分开设计。
  • 继承是避免重复行为的一个强大工具。
  • 对于辣鸡代码,不必一开始就完成整个系统的重构,只需要满足需求就行了,反正之后还可以回来重构。


              二、简化函数调用系手法。

  • Rename Method函数改名 298
  • 函数的名称未能揭示函数的用途。修改函数名称。
  • 改函数名能帮助后来者理解程序。在这个手法里你甚至可以修改参数顺序。

   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把异常情况过滤。


              三、处理概括关系的手法。

  • Pull Up Field字段上移 345
  • 2个子类拥有相同的字段:将该字段移至超类。


   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
    最后,祝各位同学学习进步!
   

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
暗夜未央 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

silverkey 发表于 2017-12-24 19:11
这东西习惯了,对代码重复利用大有好处
头像被屏蔽
Yixinfz 发表于 2017-12-24 19:51
Try0oo 发表于 2017-12-24 22:35
 楼主| 象相合 发表于 2017-12-24 23:03
silverkey 发表于 2017-12-24 19:11
这东西习惯了,对代码重复利用大有好处

是的,此外,还有封装代码逻辑,使团队成员读代码更爽;其中也利用了部分设计模式,提升代码能够快速添加新需求的能力;虽然有时候会牺牲部分性能,但是我们主张“该重构的时候重构,该优化的时候优化”可以解决这个问题。
 楼主| 象相合 发表于 2017-12-24 23:06

C#与JAVA同样具有三大特性。语法有些许异同,因此掌握基本原则,重构手法,可以触类旁通的。
zedwei 发表于 2017-12-25 15:12
作为菜鸟的我,略懂
暗夜未央 发表于 2018-5-4 11:09
买过这本书,却没看过几次。。。为我的懒惰感到惭愧
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 15:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表