什么是重构
什么是重构
在不改变代码外在行为的前提下,对代码做出修改,以改进程序的内部结构。
重构对性能的影响
重构不是代码优化,重构注重的是提高代码的可理解性与可扩展性,对性能的影响可好可坏。
评估是否需要重构
如果需要给程序添加特性,但因为代码缺乏良好结构而难以更改,那可以先重构使其易于修改。
是需求的变化使重构必要,如果代码正常运行,不会再被修改,那完全可以不去重构。
重构的第一步
确保即将修改的代码拥有一组可靠的测试。
重构的过程
分小步走,每修改一小步,重新编译、测试、提交。
营地法则
保证你离开时的代码库一定比来时更健康。
重构的原则
理解重构
重构(名词):对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。
重构的关键在于运用大量微小且保持软件行为的步骤,一步步达成大规模的修改。
两顶帽子
代码开发过程中两种截然不同的行为,添加新功能和重构。
不应该经常变换帽子,每次只应该专注于其中一项工作。
为何重构
重构改进软件的设计
如果没有重构,程序的内部设计(或者叫架构)会逐渐腐败变质。
当人们只为短期目的而修改代码时,他们经常没有完全理解架构的整体设计,于是代码逐渐失去了自己的结构。
代码结质量的变质具有累计效应、破窗效应。
重构使软件更容易理解
合理的重构能让代码“自解释”。
比让计算机读懂代码更难的是,让“人”读懂代码。
重构帮忙找到bug
深入理解代码的所作所为,并立即把新的理解反映在代码当中,在这个过程中,bug自然会被发现。
重构提高编程速度
不同质量的设计,随着功能累计,添加新功能所需的时间。
需要添加新功能时,内部质量良好的软件让我可以很容易找到在哪里修改、如何修改。良好的模块划分使我只需要 理解代码库的一小部分,就可以做出修改。如果代码很清晰,我引入bug的可能 性就会变小,即使引入了bug,调试也会容易得多。理想情况下,我的代码库会逐步演化成一个平台,在其上可以很容易地构造与其领域相关的新功能。
“设计耐久性假说”:通过投入精力改善内部设计,我们增加了软件的耐久性,从而可以更长时间地保持开发的快速。
何时重构
见机行事的重构
预备性重构:让添加新功能更容易
重构的最佳时机就在添加新功能之前。
帮助理解的重构:使代码更易懂
当代码难以理解,使用重构来帮助理解。
捡垃圾式重构
在日常开发过程中,对不好的实现,通过重构进行清理。
项目计划上没有专门留给重构的时间,绝大多数重构都在做其他事(添加新功能或者修复bug)的过程中自然发生。
优秀的程序员知道,添加新功能最快的方法往往是先修改现有的代码,使新功能容易被加入。
有计划的重构
问题在某个区域逐渐累积长大,最终需要专门花些时间来解决。
分离重构和添加新功能的提交是比较有益的工作方式。
大规模的重构只在必要的时候进行,更推荐的方法还是随时随地重构工作相关的代码。
Branch By Abstraction
如果要替换掉一个正在使用的库,先引入抽象层,兼容新旧两个库的接口
Code Review时重构
和原作者一起结对编程,通过CR过程中提出的重构建议,提高代码的质量。
何时不应该重构
- 代码不需要被理解和修改时。
- 重写比重构容易时。
重构的挑战
延缓新功能开发?
重构的唯一目的就是让我们开发更快,用更少的工作量创造更大的价值。
有时候需要取舍,添加的功能很小但是需要做很大规模的重构时,可以先添加新功能。
代码所有权
推荐团队代码所有制,而不是细粒度的强代码所有制。
版本控制问题
如何解决在隔离的分支,集成回主线,需要解决大量冲突的问题。
采用持续集成(CI),基于主干开发的方法,每天至少向主线集成一次,确保主线随时处于健康状态。
测试
“不会改变程序可观察的行为”,要求代码应该有一套完备的测试套件,并且运行速度要快,能在一步小的重构后,马上验证程序的正确性。
重构、架构和YAGNI
一开始就完成完美的架构设计是不可能的,当拥有重构的时候,我们可以做简单设计(也称增量式设计或者YAGNI)。
只根据当前的需求来构造软件,同时把软件的设计质量做得很高。随着对用户需求的理解加深,我会对架构进行重构,使其能够应对新的需要。
重构与软件开发过程
敏捷开发的三大实践
- 自测试代码
- 持续集成
- 重构
重构与性能
短期看来,重构的确可能使软件变慢,但它使优化阶段的软件性能调优更容易,最终还是会得到好的效果。
性能优化的过程:度量->发现性能热点->去除热点。
大多数程序的性能都消耗在一小部分的代码上,要先对程序有清楚的理解,不要通过臆想进行性能优化。