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

入职以来,被tuangou-goods折磨到不行,一直琢磨着要怎么重构它。因此在动大工之前,决定先恶补一下重构的理论知识。
于是,强烈推荐大家也读一读Martin Fowler大神的这本书。
 
 
 
***************我是分隔符,以下是我总结的干货***********************
 
 
 
 
一、什么是重构?
  • 对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
 
二、为什么要重构?
  1. 重构改进软件设计
    • 通过不断重构,可以发现并修改软件项目中不合理的地方,提升软件的设计,使软件始终处于一种可维护的状态
  2. 重构帮助找到bug
    • 通过重构,可以发现软件中设计复杂和不合理的地方,往往代码逻辑特别复杂的地方就是bug常常产生的地方
  3. 重构提高编程速度
    • 重构能提高代码质量,改善设计、提升可读性、减少错误
    • 良好的设计维持开发速度的根本——重构可以帮助软件维持健康的状态
 
三、何时重构?
  1. 首先,不提倡专门划出时间和计划来重构,重构应该随时进行
  2. 当你多次做同样的事时(三次法则),你就应该重构
  3. 添加功能时重构:重构可以使项目更加易于添加新功能
  4. 修补错误时重构:bug产生的一大原因就是代码设计的不合理,而这往往意味着需要重构
  5. 复审代码时重构:Code Review能帮助项目知识的传播,当然也能在传播过程中暴露项目的问题(一个特殊的例子就是结对编程)
 
四、何时不重构?
  1. 项目实在是太烂,烂到开发一个新的都比重构快。。。
  2. 项目进度很紧,接近最后期限时
 
五、如何说服项目经理和产品经理项目需要重构?
咳咳。。。本文算不算
 
六、重构的基础
  1. 良好的测试环境和测试框架
  2. 重构建立在测试基础之上,由重构的定义可以看出,需要保持项目重构前后的可观察的外部逻辑行为不变
  3. 因此,每做一点重构之前,第一步就是测试覆盖
  4. 重构流程:测试一小点->重构一小点->测试一小点->重构一小点。。。循环往复,不断迭代
 
七、重构与性能
  • 先通过重构写出可调的软件,再通过计量软甲测试系统性能,做到有针对性的优化。因此,重构可以提高系统的可优化性,间接提高系统性能。
 
七、什么样的代码需要重构?
  1. Duplicated Code(重复代码)
    • 重复的代码会难以维护,违反了DRY原则
  2. Long Method(过长函数)
    • 使用小函数能提高代码的解释能力、共享能力和选择能力;
    • 现代的OO语言已经完全免除了进程内的函数调用开销——性能无忧
    • 每当你觉得需要通过写注释来说明的时候,就是应该写一个独立函数的时候
    • 良好的函数名能能够帮助理解
    • 注释、条件表达式、循环、过多的内部变量 值得关注
  3. Large Class(过大的类)
    • 过大的类意味着逻辑并没有良好的拆分
    • 不利于代码的维护
  4. Long Parameter List(过长的参数列表)
    • 太长的参数难以理解
    • 太多的参数会造成前后不一致、不易使用
  5. Divergent Change(发散式变化)
    • 当一个对象因为多种变化而修改时,就是发散式变化
    • 一般来说,每个对象只应该因一种变化而需要修改
  6. Shotgun Surgery(霰弹式修改)
    • 一个类受多种变化的影响
    • 变化和修改应该是一一对应关系
  7. Feature Envy(依恋情结)
    • 函数对某个类的兴趣高过对自己所处的类的兴趣
    • 根本原则:总是将一起变化的东西放在一起
  8. Data Clumps(数据泥团)
    • 两个类中相同的字段,函数签名里经常一起出现的相同参数
    • 意即具有相关性的数据参数
    • 需将这些具有极强相关性的数据提炼到一个类中
  9. Primitive Obsession(基本类型偏执)
    • 大量的基本类型数据其实含有内在逻辑,无需偏执
    • 可以将相关的组成对象,并赋予一定的逻辑
  10. Switch Statement(Switch语句)
    • 有Switch的地方常常意味着这个地方可以使用多态
    • 显然,多态更好维护,具有更好的扩展性
  11. Parallel Inheritance Hierarchies(平行继承关系)
    • 当不同的继承体系之间实际上有内在关联性时
    • 一般策略:让一个继承体系的实例引用另一个继承体系的实例
  12. Lazy Class(冗赘类)
    • 并没有什么用类,或实际功能用到很少的类
  13. Speculative Generality(夸夸其谈未来性)
    • 过度设计,代码中出现了所谓的“未来会用到的”代码
    • 会造成系统难以维护和理解(一堆没用的代码写在那里,读的人肯定一头雾水的啊)
  14. Temporary Field(令人迷惑的临时字段)
    • 对象内某个实例变量仅为某种特定情况而设定
  15. Message Chains(过度耦合的消息链)
    • 用户向A请求B,再通过B请求C,然后很长。。。
    • 意味着客户代码和查找过程中的导航结构紧密耦合
  16. Middle Man(中间人)
    • 自己没干什么,大部分的函数都委托给别的类
  17. Inappropriate Intimacy(狎昵关系)
    • 两个类之间过多的关注对方的private成分
  18. Alternative Classed with Different Interfaces(异曲同工的类)
    • 两个干着差不多事情的类。。。
  19. Incomplete Library Class(不完美的类库)
    • 所引用的类库功能不全或不完美
  20. Data Class(纯稚的数据类)
    • 过分单纯的数据类,应将部分相关逻辑加入这些数据类
  21. Refused Bequest(被拒绝的遗赠)
    • 子类通过继承体系拿到了它不愿拥有的成员变量和函数
    • 此时证明继承体系的设计有问题
  22. Comments(过多的注释)
    • 当需要一大堆注释来说明一个函数或字段时,那就说明了其复杂性
    • 此时就需要合理的逻辑拆分和重构

 

***********我是干货的分隔符********************

具体的针对不同重构场景的重构技术,将在下一篇里总结。

持续学习中。。。

 

posted @ 2015-11-26 21:18  CodeBaker  阅读(147)  评论(0编辑  收藏  举报