按照软件工程大神Martin Fowler的定义,重构就是在不改变软件现有功能的基础上,通过调整程序代码改善软件的质量、性能,使其程序的设计模式和架构更趋合理,进而提高软件的可扩展性和可维护性。这是重构的定义,简单来说就是不改变软件的功能,优化软件设计和代码,让软件更易于扩展和维护,当然也包括易于复用。Martin Fowler等人总结出了一些常用的重构技术,将其写成了一本面向对象领域的经典著作——《重构:改善既有代码的设计》。
软件开发大师Robert C. Martin【Bob大叔】在《程序员的职业素养》(The Clean Coder)一书中也提到要勇于整理代码,通过整理代码让它们更易于理解,更易于修改,也更易于扩展。这样,代码的bug也会随之减少,不应该让代码劣化而视若不见。我觉得Bob大叔说的很好,这就是重构的意义。因此我常常跟学生们说,如果想成为一名合格的面向对象开发人员,设计模式和重构是你必须要学的两项基本技能。
重构和设计模式之间的关系很紧密,在Martin Fowler的《重构》一书中也提到了好几种使用设计模式来进行重构的手段。另外,还有一本书,名为《重构与模式》(Refactoring to Patterns,个人感觉翻译为“面向模式的重构”、“模式导向重构“或”重构到模式”更合适,),作者是Joshua Kerievsky,这本书获得了第15届Jolt生产效率大奖。在这本书中提到了27种以模式为导向的重构,包括在设计中实现模式、趋向模式和去除模式。很客观地对一些设计模式进行了评价,既告诉我们如何通过设计模式来提高代码质量,又告诉我们如何在代码中去除一些不合理的模式应用。该书大部分重构方案还是实现和趋向模式的,例如将创建知识搬移到Factory、将聚集操作搬移到Visitor、用Strategy替换条件逻辑、用State替换状态改变条件语句等。每一种重构方案都提供了相应的实例,让你做一次重构的操练。当然,在读这本书之前,我建议大家还是先把设计模式好好学一下,否则里面有一些重构方案就没有办法理解了,毕竟这本书不是专门讲设计模式的。建议大家在学完设计模式之后再看这本书,既能够学到如何在实际项目中运用设计模式,又能学到如何在不同情况下选择设计模式,这本书也是我研究团队成员必读书籍之一。
在Bob大叔的《程序员的职业素养》一书中提到:当你发现修改软件不像你预想的那样简单时,你便应该改进设
计,使后续修改变简单。让软件保持固定不变是危险的,如果一直不重构代码,等到最后不得不重构时,将会发现代码已经很僵化。因此,要将重构变成一种习惯,每一次在阅读代码或者检入代码时都要考虑对代码进行改善与优化。如果你希望自己的代码灵活可变,那就应该时常修改它!我觉得这就是对重构时机最好的回答。如果你发现代码太僵硬,不易于扩展(你可以扩展一下试试),特别是那些在需求文档或者客户嘴里多次提到的需要改变的地方,一定要尽量灵活,当缺少这种灵活性时,你应该马上重构。个人觉得,衡量是否需要重构的标准就是现有设计方案或者代码是否不易扩展?复用性是否存在问题?将来是否会增加维护成本?如果存在这些问题,为了将来,应该重构,立即,马上!
很多人明知设计方案或者代码有问题,却不愿意去重构,这里面也存在很多原因,我觉得很多人之所有害怕重构,最大的问题在于担心重构之后会引入新的问题,难于测试。关于这一点,Bob大叔和我的想法不谋而合,尽量实现重构和测试的自动化。由于重构主要还是代码级的,对应的测试也主要是单元测试,单元测试的自动化程度在所有的测试中应该是最高的,因此只要我们有一套完整的测试用例,重构之后可以对应修改少许的测试代码就可以马上实施回归测试了。我个人觉得这个问题还是可以解决的,但是对于测试代码不完善或者根本没有测试代码的项目,实现起来恐怕会比较麻烦。因此,培养良好的开发习惯很重要,建议大家有空看看测试驱动开发(TDD)方面的资料,我相信对于所有一线开发人员还是挺有帮助的。
当然也有人觉得重构麻烦,不愿意重构,觉得功能都没有问题了,没有必要再进行重构,担心重构之后的功能会出现问题。有这种想法的人缺乏一种专业精神,我个人觉得要想成为一名专业的程序员,应该掌握一些常用的重构技巧并经常在项目开发中使用它们,可能开始会比较麻烦一点,但是当重构成为你开发技能一部分,就像写for、if语句一样很平常,你就不会觉得这是一种麻烦。在现在主流的IDE,例如Eclipse、Visual Studio中,重构都已成为菜单的一部分,可见业界对于重构已达成共识,很多人把重构当做写注释一样,是一个很平常的提高代码质量的操作而已。
还有一个影响重构的因素是项目进度、成本等受到制约。明明知道要重构,但是项目工期很短,没有时间和精力来重构,各种赶工很常见,后果有时候也很严重,代码质量很差,在维护和二次开发时大量代码可能需要推倒重写。对于这个问题,只能尽量去跟客户或领导们交涉了,建议适当延长时间或者缩减功能。如果交涉失败确实很麻烦,只能想办法记录一下哪些地方需要重构,存在哪些问题,寄希望于有时间能够把这些地方重构一下或者在维护阶段再进行重构。
专家建议,将重构当做一种习惯,发现有需要时就应该考虑重构。