在吗吗吗–》不要慌,我还在
经典重读:改善既有代码的设计
一、重构的定义
重构:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
重构:使用一些列重构手法,在不改变软件可观察行为的前提下,调整其结构。
二、重构的时机
1、如果你发现自己需要为程序添加一个特性,而代码结构使你无法很方便的达成目的,那就先重构那个程序,使特性的添加比较容易进行,然后再添加特性。
2、重构前,先检查自己是否有一套可靠的测试机制。这些测试必须有自我检验能力。
3、重构技术就是以微小的步伐修改程序。如果你犯下错误,很容易便可发现它。
4、任何一个傻瓜都能写出计算机可以理解的代码。唯有写出人类容易理解的代码,才是优秀的程序员。
5、事不过三,三则重构。
6、不要过早发布接口。请修改你的代码所有权政策,使重构更顺畅。
7、当你感觉需要写注释时,请先尝试重构,试着让所有注释都变得多余。
8、确保所有测试都完全自动化,让它们检查自己的测试结果。
9、一套测试就是一个强大的bug侦听器,能够大大缩减查找bug所需要的时间。
10、频繁的运行测试。每次编译请把测试也考虑进去–每天至少执行每个测试一次。
11、每当你收到bug 告,请先写一个单元测试来暴露这只bug。
12、编写为臻完善的测试并实际运行,好过对完美测试的无尽等待。
13、考虑可能出错的边界条件,把测试火力集中在那里。
14、当事情被大家认为应该会出错时,别忘了检查是否抛出了预期的异常。
15、不要因为测试无法捕获所有bug就不写测试,因为测试的确可以捕获到大多数bug。
三、代码坏味道
四、重构的方法
大的分类共用7种类型 1)重新组织函数;2)在对象之间搬移特性;3)重新组织数据;4)简化条件表达式; 5)简化函数调用;6)处理概括关系;7)大型重构;
1、重新组织数据
1)自封装字段(不要直接访问一个字段,请使用取值和设置函数)
2)以对象取代数据值
3)将值对象改为引用对象(享元模式)
4)将引用对象改为值对象(上一条的反向动作)
5)以对象取代数组(更易读)
6、将单向关联改为双向关联(就像双向链表,某些情况下有奇效)
7、将双向关联改为单向关联(降低复杂度)
8)以字面量取代魔法数(常量的定义)
9)封装字段,面向对象三大特性之一:封装性
10)封装集合(用起来更方便)
2、在对象之间搬移特性
1)搬移函数(将函数放到最合适的位置)
2)搬移字段(将字段放到最合适的位置)
3)提炼类(类的单一职责原则)
4)将类内联化(与提炼类 相反)
5)隐藏“委托关系”
(兄弟们这不就是 迪米特法则吗,不要和陌生人说话,这就是中介者模式啊)
6)移除中间人
(这个就是和解除”委托关系“的意思,大量的委托也是有缺点的,所以要根据不同场景来灵活运用)
7)引入外加函数(在客户类中增加一个额外函数)
8)引入本地扩展
本质就是对已有类库进行扩展,两种方式 1)继承,在子类中增加额外扩展方法 2)使用组合的方式扩展(组合优于继承原则,装饰器模式、包装器模式、代理模式)
3、重新组织函数
1)提炼函数,这可能是最常用的重构手段之一:好处1)每个函数都像一个注释,有助于理解高层代码2)被复用的机会更大 3)函数的覆写更容易
2)内联函数(提炼函数的反向操作,用的机会不多)
3)内联临时变量,可以减少代码行数
4)以查询取代临时变量,提高代码复用的概率,但可能存在重复计算的性能问题,要根据实际情况选择
5)引入解释性变量,提高代码可读性
6)分解临时变量,临时变量被多次赋值,代码可理解性下降,出错概率会增加,还有入参一般都声明为final就是为了防止被重新赋值,导致出错概率增加
7)移除对参数的赋值,大佬写的代码,入参往往是final修饰的(一般用在长函数和复杂函数中,简单函数可以不考虑)
1)以临时变量取代对参数的赋值动作 2)为参数加上final修饰,强制遵守“不对参数赋值”的惯例
8)以函数对象取代函数,主要应对局部变量过多,提取函数需要过多参数的情况
9)替换算法
替换一个巨大而复杂的算法是非常困难的,只有先将它分解为较简单的小型函数,然后你才有把握进行算法替换工作。
4、简化条件表达式
1)分解条件表达式(提取函数呗)
2)合并条件表达式(提取函数呗)
3)合并重复的条件判断(逻辑想明白了才能写出更简洁的代码)
4)移除控制标志
重构为:
重构为:
5)以卫语句取代嵌套条件表达式(显然可读性更强)
6)以多态取代条件表达式(策略模式)
7)引入Null对象
8)引入断言
5、简化函数调用
1)函数改名 rename method
2)添加参数,增加参数的个数或者用对象替换参数
3)移除参数
4)将查询函数和修改函数分离(避免在一个查询函数中进行修改操作,函数职责要单一)
5)令函数携带参数(合并类似工作的函数)
6)以明确函数取代参数(和上一条“令函数携带参数”相反的操作,用在参数化并不能增加代码复用度的情况,这时候还不如分离开)
7)保持对象完整
8)以函数取代参数(减少不必要的传参)
9)引入参数对象(同时参数相关的行为也可以转移到参数对象中)
重构之后的效果:将参数提取到 DateRange对象中,并将相关行为 提取到DateRange对象中。
10)移除设值函数(当对象一旦创建后不希望再改变其内容,同时将字段设值为final类型,就将设值函数移除或者隐藏)
11)隐藏函数
12)以工厂函数取代构造函数
引入工厂函数
改进工厂函数
进一步改进工厂函数
以明确函数创建子类来代替工厂函数
13)封装向下转型
14)以异常取代错误码
15)以测试取代异常(提前校验参数的合法性)
6、处理概括关系
1)字段上移
2)函数上移
3)构造函数本地上移
4)函数下移
5)字段下移
6)提炼子类
7)提炼超类
8)提炼接口
9)折叠继承体系
10)塑造模板函数(模板方法设计模式啊)
11)以委托取代继承
12)以继承取代委托
7、大型重构
1)梳理并分解继承体系
2)将过程化设计转化为对象设计
3)将领域和表述/显示 分离(MVC设计模式)
4)提炼继承体系
四、重构的本质
就是使程序代码质量更高,可读性更强,应对需求变化的能力更强,修改扩展更轻松,延长软件的生命周期,创造更多的价值。
五、重构的阻碍
1、你不知道如何重构;
2、如果这些利益是长远的,何必现在付出这些努力呢远看来,说不定当项目收获这些利益时,你已经不在职位上了;
3、代码重构是一项额外工作,老板付钱给你,主要是让你编写新功能;
4、重构可能破坏现有程序;
六、重写、补丁与重构
重写整个程序是一种极端,一直凑合打补丁是另一种极端。
中庸之道是在软件开发与演进过程中及时的进行重构,消除代码坏味道与架构设计的不合理之处。?
文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91536 人正在系统学习中
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!