zoukankan      html  css  js  c++  java
  • 《重构》读书笔记

    笔记的目的是方便自己查阅。
    有些重构方法不在笔记中,可能是因为:
    1、该方法在工作中已经熟练使用,不需要记录
    2、该方法自己还不能灵活运用,需要再积累些经验
    3、该方法自己并不认可(比如replace temp with query)
    4、该方法在我的工作中不适用(比如适用于GUI的方法,现在都使用设计良好的框架)
     
    第一章:重构,第一个案例
    重构的时机:
    重构第一步:测试环境
    分解大函数,extract method
    改变量名
    move method:函数应该放在它所使用的数据的所属对象内。保险的做法,是保留旧函数,由旧函数调用新函数。
    重构可能会牺牲性能。考虑重构+优化,而不是放弃重构
    如果某个属性上有大量条件判断,考虑采用状态机或策略模式
     
    第二章 重构原则
    想清楚自己戴的哪顶帽子——重构时不改功能,改功能时不重构。开发过程中两件事常常交替进行。
     
    第三章 代码的坏味道
    坏味道:重复代码,长函数,大类,长参数列,发散式变化,。。。
     
    当一段(甚至一行)代码,感觉需要注释来说明它干什么时,就可以extract,并用良好的函数名说明其用途。
    局部变量过多,函数参数过长,类太多实例变量,都可以把相关变量提炼到一个对象中。
     
    第六章 重新组织函数
    这一章主要有两类内容:
    1、extract method以易读性为指导原则
    2、处理局部变量
    6.5 introduce explaining variable:将复杂表达式的结果放入临时变量,变量名可以解释表达式的用途。该临时变量应声明为final。当这类局部变量较多时,使用introduce explaining variable;只有少数时使用extract method(但我个人不喜欢replace temp with query方法,所有无论使用哪种方式,如果表达式结果使用多次,都需要引入一个临时变量)
     
    6.8 replace method with method object: 大型函数,有很多局部变量。将大函数放入一个对象,局部变量作为对象字段,然后对大函数进行extract method
     
    第七章 在对象之间搬移特性
    随着系统发展,类容易变得越来越臃肿,承担太多责任,或责任不清晰。
    7.1-7.2 move method/field:划清责任。
    一个函数使用另一个对象的次数,比自己所驻对象的次数还多。某个字段被另一个类更多地用到。
    7.5 hide delegate: 在服务对象中建立委托函数,而不是公开被委托对象。这样一单委托关系发生变化,改变和可以只在服务对象中处理,而不需要client知晓。
     
    7.7-7.8  introduce foreign method / introduce local extension: 当需要为某个类添加特性,但无法修改这个类时:
    如果只添加一两个特性,introduce foreign method,将这个类的实例作为意义参数传入foreign method,并用注释表明这是个foreign method;
    如果添加多个特性,设计一个子类或包装类。(个人倾向于始终使用包装类或util类 。《effective java》中说“复合优于继承”)
     
    第八章 重新组织数据
    8.1 self encapsulate field: 即使在类内部,也使用get, set访问自己的属性。(有争议,可根据实际情况灵活运用)
    8.2 replace data value with object: 如果一个数据项,需要和其他数据和行为一期使用才有意义。(比如,表示“订单”的类中,有“顾客姓名”,“顾客性别”两个字段,应该将它们替换成“顾客”对象)。
    8.3 change value to reference : 使用工厂函数代替构造函数,对象可以预先创建好(比如Collections.EmptyList),或动态创建。
    8.11 encapsulate collection : 取值函数不该返回集合自身,因为这会让用户得以修改集合的内容,而集合拥有者却一无所知。建议返回集合的只读副本,并提供公开的add, remove函数。
    8.13 replace type code with class : 用类型类的静态实例代替基本类型的type code,并可能封装部分行为(例如获取类型的文字描述)。
    8.14 replace type code with subclass: 不同类型的对象有不同行为,则一个类型是一个子类,避免复杂的条件判断。
    8.15 replace type code with state/strategy: 如果对象的类型是可变的,就不能使用subclass。
     
    第九章 简化条件表达式
    9.1 decompose conditional : 将复杂的条件表达式提炼成bool函数(其实是一种extract method)
    9.5 replace nested conditional with guard clauses: 前提是每个分枝都可以直接break或return。可以配合extract method将条件语句提炼成独立函数。
    9.6 replace conditional with polymorphism
     
    第十章 简化函数调用
    这一章的关键在于,使接口更加容易理解和使用。
    10.4 separate query from modifier : 一个get函数不应该有任何副作用。
    10.5-10.6 parameterize method(to replace explicit methods)/ replace parameter with explicit methods : 关键在于函数的行为差异有多大
    10.12 replace constructor with factory method:当创建对象时需要额外的动作
    10.13 encapsulate downcast : 个人觉得这个说法太理想化了。重新解读为“在尽量低的层次上进行向下转型”
     
    第十一章 处理概括关系
    概括关系(generalization) 即继承关系。
    11.1-11.8 字段/函数上移/下移,提炼子类/超类/接口
    11.11 replace inheritance with delegation :某个子类只使用超类接口或属性中的一部分(逻辑上并不属于超类的一个具体类型),改为委托关系。
    11.12 replace delegation with inheritance : 存在大量简单的委托时。
     
    第十二章 大型重构
    重新梳理下这章的内容,将“方法列表”重新梳理为“场景——方法”结构。
    12.2 当手上有太多过程化风格的代码时,需要convert procedural design to object。
    综合使用replace data value with object,replace method with method object,extract method
    12.4 extract hierarchy:其实就是replace conditional with polymorphism的大规模运用? 
     
  • 相关阅读:
    SpringBoot学习笔记
    2021牛客多校第一场 I题(DP)
    CSS小结
    AOP小结
    IOC容器小结
    Educational Codeforces Round 56 (Rated for Div. 2) G题(线段树,曼哈顿距离)
    Codeforces Round #656 (Div. 3) E. Directing Edges(拓扑排序)
    Educational Codeforces Round 101 (Rated for Div. 2) E
    [FJOI2017]矩阵填数 (容斥原理)
    优秀代码样板收集计划(python)
  • 原文地址:https://www.cnblogs.com/night1989/p/9527158.html
Copyright © 2011-2022 走看看