0. 本章内容导图
1. 什么是重构
重构:对软件内部结构的一种调整,目的是在不改变软件可观察行为的前提下,提高其可理解性,降低其修改成本。(名词性定义)
重构:使用一系列重构手法,在不改变软件可观察行为的前提下,调整其结构。(动词性定义)
重构的目的是使软件更容易被理解和修改;重构不改变软件的可观察行为。
2. 为什么重构
(1)重构改进软件设计
当人们只为短期目的,或是在没有完全理解整体设计之前就贸然修改代码,程序就会慢慢失去其原有的结构,这种结构的流失是累积性的,越难理解程序的意图,设计就腐败的越快。经常性的重构有助于帮助代码维持其原有的设计形态。
(2)重构使软件更容易理解
一方面,重构的目的本来就是为了使程序更容易被理解,通过不断重构,使代码更易读,结构更理想,使得代码本身就可以表达出所做的事情。
另一方面,可以通过重构来协助理解不熟悉的代码。对于不熟悉的代码,一开始所做的重构可能都是停留在细枝末节上,但随着代码渐趋简洁,就可以慢慢看到一些设计层面的东西,将对代码的理解提高到更高层次上。
(3)重构帮助找到bug
通过不断重构,可以越来越深入地了解代码的意图,对代码意图了解的越深入,就越容易发现代码中潜藏的bug。
(4)重构提高编程速度
良好的设计是快速开发的根本,重构可以阻止系统腐败变质,甚至提高设计质量,从而帮助更快速地开发程序。
3. 什么时候重构
(1)边开发边重构
不应该专门拨出时间进行重构,重构应该随时随地进行。当完成一个函数、一个类时就可以停下来审视一下设计是否合理,是否可以通过重构使其更容易被理解。
两顶帽子:
使用重构技术开发软件时,把时间分配给两种截然不同的行为:添加新功能,以及重构。添加新功能时,不应该修改既有代码,只管添加新功能。重构时就不能再添加新功能,只管改进程序结构。
(2)三次法则
事不过三,三则重构。
(3)添加功能时重构
添加新功能时,常常会为了急于实现功能而选择最容易实现的方式进行修改,这种在没有完全理解代码整体设计之前的修改,是代码逐渐腐败变质的原因,在添加功能时,通过重构,使新功能可以自然地融入系统。
(4)修补错误时重构
出现错误的地方很可能是因为代码不够清晰,不能让人一眼就看出bug。所以在bug出现的地方就该考虑可否通过重构使其更清晰明了。
(5)复审代码时重构
代码评审时可以收到很多有用的建议来指导重构。另外,代码是用来阅读交流的,别人未能很快理解的地方可能也说明代码本身不够简洁易懂,也透露着需要重构的味道。
4. 什么时候不该重构
重构之前,代码需要能够在大部分情况下可以正常运作。如果现有代码根本不能正常运作,那就需要重写了。
另外在项目已近最后期限,也应该避免重构,先要保证完成项目目标功能。
5. 重构与设计
重构与设计彼此互补。
在软件开发过程中,唯一不变的就是变。基本不可能通过预先设计就建造一个可以应对各种变化的灵活的解决方案。尤其是在移动开发过程中,用户的需求是不确定且可能还是不断变化的,软件需求会随着迭代的进行做各种调整。因此,仅仅通过预先做好设计,是很难满足移动开发和敏捷开发需求的了。
一些极限编程的支持者认为可以不做任何设计,只管按照最初想法开始编码,让代码有效运作,然后再将它重构成型,最终获得设计良好的软件。这种做法确实可行,但并不是最有效的途径。
更有效的做法是依然做预先设计,但不必一定找出正确的解决方案,只需要先设计一个足够合理的解决方案就够了,在实现这个解决方案的时候,对问题的理解也会逐渐加深,可能会察觉最佳解决方案和当初设想的有所不同,再通过重构,使得预先设计方案逐渐演变为最佳的解决方案。
6. 重构与性能
重构使代码容易理解和修改,从而使得性能优化变得容易。
程序耗时的部分往往集中在一小部分代码上,对性能做优化,就是主要对这一部分耗时代码的优化。短期来看,重构可能使软件变慢,但它使优化阶段的软件性能调整更容易,最终得到好的效果。
在性能优化阶段,首先应该用一个度量工具来监控程序的运行,找到程序中哪些地方在大量消耗时间和空间。这样就可以找出性能热点所在的一小段代码。然后集中关注这些性能热点,并使用持续关注法中的优化手段来优化它们。简言之就是:发现热点,去除热点。