重构-改善既有代码设计

  1. 重构是在不改变软件可观察行为的前提下,对代码做出修改,以改进程序的内部结构。本质上说就是在代码写好后改进它的设计
    重构每每意味着不了解软件行为下重构程序
    2.在设计前期使用模式经常致使过分工程,单凭对完美的追求没法写出实用的代码,而"实用"是软件压倒一切的要素
    《设计模式》指出:设计模式为重构提供类目标
    重构能够反"软件会慢慢腐烂"现象,经过重构,设计再也不是一切动做的前提,而是在整个软件开发过程当中逐渐浮现出来
    【29页】    若是你发现本身须要为程序添加一个特性,而代码结构使你没法很方便地达成目的,那就先重构那个程序,使特性的添加比较容易进行,而后再添加特性。
    【35页】 重构技术就是以微小的步伐修改程序。若是你犯下错误,很容易发现。
    【37页】 任何一个傻瓜均可以写出计算机能够理解的代码,惟有写出人类容易理解的代码,才是优秀的程序员。
    第二章:
    重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提升其可理解性,下降其修改为本。
    重构(动词):使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。
    两顶帽子:使用重构技术开发软件时,你把时间分配给两种大相径庭的行为:添加新功能,以及重构,添加新功能时只能添加新功能,不能修改已有代码;
        重构时,只管改进程序结构,不能添加新功能
    为什么重构?1.重构改进软件设计[防止软件腐烂]    2.重构使软件更容易理解[给人理解]    3.重构提升编程速度
    重构的时机:重构应该随时随地进行,你不能为了重构而重构,你之因此向重构,是由于你想作别的事情,而重构能够帮你把那件事作好
    三次法则:第一次作某件事时只管去作;第二次作相似的事会产生反感,但不管如何仍是能够去作;第三次再作相似的事,你就应该重构[事不过三,不然重构]
    A添加功能时重构    B修补错误时重构    C代码复审时重构[二人代码重构,多人则设计重构]
    《数据库重构》
    不要过早发布接口,请修改你的代码全部权政策,使重构更顺畅。
    【88页】什么时候不能重构
    1.原有代码压根不能正常运行    2.项目接近最后期限,项目接近后期时重构,为时已晚
    2.重构与设计,重构肩负一项特殊使命:重构与设计彼此互补
    【kent,XP,极限编程】:重构能够取代预先设计。这意思是你根本没必要作任何设计,只管按照最初想法开始编码,让代码有效运做,而后再将它重构
        成型。事实上这种办法真的可行。
    3重构与性能:咱们猜想的性能瓶颈每每不是消耗性能的真正所在,只有经过测试才能找到真正影响性能的地方,并把时间用在真正须要优化的地方
    第三章:"坏味道"<须要重构之处>    
    1.重复代码
    2.过长的函数
    3.过大的类[单个类作了不少的事情]
    4.过长的参数列
    5.发散式变化[一个类受多种变化的影响]
    6.三弹式修改[一种变化引发多个类的修改]
    7.依恋情节[一个类的某个函数使用的大部分数据来源于其余类]
    8.数据泥团[两个类中相同的字段,许多函数签名中相同的参数]
    9.基本类型偏执[或许你不肯意将一些基本数据类型转换为对象]【104页】
    10.switch惊悚现身[多态替换switch]
    11.平行继承体系[每当你为一个类增长一个子类的同时也须要为另外一个类增长子类]
    12.冗余的类[没什么实际做用的类]
    13.夸夸其谈的将来性[为了将来变化而准备的接口]
    14.使人迷惑的临时变量
    15.过分耦合的消息链[一个对象传递了很远才获得处理]
    16.中间人[一些类的大部分业务都是调用其余类实现的]
    17.狎呢关系[过分亲密的类,如继承]
    18.殊途同归的接口[功能相似的函数]
    19.不完美的库类
    20.数据类[简单包含字段和getter与setter方法的类]
    21.被拒绝的馈赠[子类不想继承所有的函数]
    22.过多的注释[尽可能用表意的方法签名代替注释]【当你感受须要撰写注释时,请先尝试重构,试着让全部注释多余】
    第四章:构筑测试体系
    4.1自测试代码的价值:xiug修复错误只须要很短的时间,但找到错误却须要不少的时间
    【确保全部测试都彻底自动化,让它们检查本身的测试结果】
    【一套测试就是一个强大的bug侦测器,可以大大缩短查找bug所须要的时间】
    【每当你收到bug,请先写一个单元测试来暴露bug】
    4.3添加更多测试
    【考虑可能出错的边界条件,把测试火力集中在那儿】[不要为每个函数写测试,只为那些可能出错的地方写测试]
    【不要由于测试没法捕捉全部的bug就不写测试,由于测试的确能够捕捉到大多数bug】
    第五章:重构列表
    5.2:寻找引用点[发射不能找到,继承覆盖不能找到]
    第六章:从新组织函数
    1.Extract Method-提炼函数:将代码放进一个独立函数中,并让函数名称解释该函数的用途
    2.Inline Method-内联函数:在函数调用点插入函数主体,而后移除该函数
    3.Inline Temp-内联临时变量:将全部对该变量的引用动做,替换为对他赋值的表达式自身
    4.Replace Temp with Query-以查询取代临时变量:将临时变量换成相应的赋值方法
    5.Introduce Explaining Variable-引入解释性变量:将复杂表达式的结果放进一个临时变量,以此变量名称来解释变量用途
    6.Split Temporary Variable-分解临时变量:[有些临时变量被屡次赋值],针对每次赋值都创造一个新符临时变量
    7.Remove Assignments to Parameters-移除对参数的赋值:[方法修改了参数]以一个临时变量取代该参数的位置
    8.Replace Method with Method Object-以函数对象取代函数:将这个函数放进一个单独的类中,如此一来局部变量就成了对象的字段。
        而后你能够在同一个对象中将这个大型函数分解为多个小型函数
    9.Substitute Algorithm-替换算法:将函数本体替换为另外一种算法
    第七章:在对象之间搬移特性
    1.Move Method-搬移函数:[一个类的某个函数与另外一个类交流更多,此时,该函数极有多是放错地方了]
        在该函数最常引用的类中创建一个有着相似行为的新函数。将旧函数变成一个单纯的委托函数,或是将旧函数彻底移除
    2.Move Field-搬移字段:[你的类的字段与另外一个类更多交流,此时,这个字段是否是放错地方了]
        在目标类新建一个字段,修改源字段的全部用户,令它们改用新字段
    3.Extract Class-提炼类:[某个类作了应该由两个类作的事]
        创建一个新类,将相关的字段和函数从旧类搬移到新类
    4.Inline Class-将类内联化:将一个类的全部特性所有搬到另外一个类中[这个类没干什么实事]
    5.Hide Delegate-隐藏委托关系:在服务类上创建所需的全部函数,用以隐藏委托关系[最少知识原则,例如System.out.print()]
    6.Remove Middle Man-移除中间人:某个类的大部分操做都是委托实现的,让调用者直接调用受托类
    7.Introduce Foreign Method-引入外加函数:在客户类中创建一个函数,并以第一参数形式传入一个服务类实例。
        [你须要为提供服务的类增长一个函数,但你没法修改这个类---不完美的库类]
    第八章:从新组织数据
    1.Self Encapsulate Field-自封装字段:为这个字段创建setter和getter函数[你直接访问一个字段,但与字段之间的耦合关系逐渐变得笨拙]
    2.Replace Data Value with Object-以对象取代数据值:将数据项变成对象[你有一个数据项,须要与其余数据和行为一块儿使用才有意义]
    3.Change Value to Reference-将值对象改成引用对象:将值对象改成引用对象
    4.Change Reference to Value-将引用对象改成值对象:将对象改成值对象[你有一个很小的对象,不可改变同时不易管理]
    5.Replace Array with Object-以对象取代数组:以对象替换数组。对于数组中每个元素,以一个字段表示[用数组表示不一样意义的数据]
    6.Duplicate Observed Data-复制"被监视数据":将该数据复制到一个领域对象中。创建一个Observed模式,用以同步领域对象和GUI对象内的重复数据
    7.Change Unidirectional Association to Bidirectional-将单向关联改成双向关联
    8.将双向关联改成单向关联:(尽可能除去不须要的关联)
    9.以字面量取代魔法数:常量的运用
    10.Encapsulate Field-封装字段:getter和setter封装public字段
    11.Encapsulate Collection-封装集合:(不要直接把集合从方法返回出去)
    12.Replace Record with Data CLass-以数据类取代记录:相似于数据库实体
    13.以类取代类型码:以一个新的类替换该数值类型码
    14.以子类型取代类型码
    15.以State/Strategy取代类型码
    16.以字段取代子类:[子类只返回一些状态字段]
    第九章:简化条件表达式
    1.分解条件表达式:从if,else,then中分别提炼出独立函数
    2.合并条件表达式:将相同处理状况的条件表达式合并,并用独立函数处理条件下的操做
    3.合并重复的条件判断:全部条件下都会执行的代码片断应该合并并提取为独立函数
    4.移除控制标记:用break,return等取代循环退出标记
    5.以卫语句取代嵌套条件表达式:使用卫语句表现全部的特殊状况(卫语句:特殊检查)
    6.以多态取代条件表达式
    7.引入Null对象
    8.引入断言
    第十章:简化函数调用
    1.Rename method-函数更名
    2.Add Parameter-添加参数
    3.Remove Paramter-移除参数
    4.Separate Query from Modifer-将查询函数与修改函数分离
    5.令函数携带参数:不一样的函数功能类似,添加参数进行区别
    6.以明确函数取代参数:针对参数的每个可能值,创建一个独立函数
    7.Preserve Whole Object-保持对象完整:参数改成整个对象[你须要对象中的某几个字段做为参数]
    8.以函数取代参数
    9.引入参数对象:某些参数老是同时出现
    10.Remove Setting Method-移除设值参数
    11.Hide Method-隐藏参数
    12.以工厂函数取代构造函数
    13.封装向下转型:不要让函数调用者转换函数函数的返回值
    14.异常取代错误码
    15.以测试取代异常
    第十二章:处理归纳关系
    1.Pull Up Field-字段上移:将字段移至超类[两个子类拥有相同字段]
    2.Pull Up Methid-函数上移:将函数移至超类[有些函数,在各个子类中产生彻底相同的结果]
    3.构造函数上移:在超类中新建一个构造函数,并在子类构造函数中调用它[各个子类的构造函数的本体几乎彻底同样]
    4.函数下移:将函数移到相关的子类去[超类中的某个函数只与部分(而非所有)子类有关]
    5.字段下移:将这个字段移到须要它的那些子类去
    6.提炼子类:[类中的某些特性只被部分实例用到]新建一个子类,将上面所说的那一部分特性移到子类中
    7.提炼超类:[两个类有类似特性]为这两个类创建一个超类,将相同特性移至超类
    8.提炼接口:[若干客户使用类接口中的同一子集,或者两个类的接口有部分相同]将相同的子集提炼到一个独立接口中
    9.折叠继承关系:[超类和子类之间并没有太大区别]将它们合为一体
    10.塑造模板函数:[你有一些子类,其中相应的某些函数以相同顺序执行操做,但各个操做上的细节上有所不一样]使用模板模式
    11.委托取代继承:[某个子类只使用超类接口中的一部分,或者根本不须要继承而来的数据]子类中保存超类的引用,操做委托超类,取消继承关系
    12.以继承取代委托:[你在两个类之间使用委托,并常常为整个接口编写许多极简单的委托函数]让委托类继承受托类
    第十二章:大型重构
    1.随时重构,而不是专门花时间作一些有风险的事
    1.梳理并分解继承体系:[某个继承体系同时承担两项责任]创建两个继承体系,并经过委托关系让其中一个能够调用另外一个
    2.将过程化设计转化为对象设计:[你手上有一些传统过程化风格的代码]将数据记录变成对象,将大块的行为分为小块,并将行为移入相关对象中
    3.将领域和表述/现实分离:[某些GUI类之中包含了领域逻辑]将领域逻辑分离出来,为它们创建独立的领域类
    4.提炼继承体系:[你有某个类作了太多工做,其中一部分工做是以大量条件表达式完成的]创建继承体系,以一个子类表示一种特殊状况
    第十五章:总结
    1.随时挑一个目标进行重构
    2.没把握就停下来
    3.学习原路返回
    程序员

相关文章
相关标签/搜索