项目总结

重构不应改变软件外在的可观察行为,但通过优化软件的内部结构,我们提高了代码的可维护性,实际上是有效地降低了出 bug 的概率。此外,实施重构的另一个好时机是在添加新特性之前:通过对现有代码进行目标明确的重构,往往可以使得新特性的添加更加简单。

刚拿到 BugsZero 的代码时,我们看到的是一个很大的Game类,里面包含了所有的代码,充斥着各种各样的细节,比如问题的初始化、玩家数据数组的初始化与更新等等。为了理解程序如何运行,我们不得不阅读全部的代码;为了添加一些新的特性,我们更是得通读所有代码,并在多处地方做出修改;如果不仔细阅读,我们甚至很难察觉到程序里面还有 bug 的存在……

面对这样的情况,我们可以尝试在测试的保护下做些适当的重构:先做些简单的清理(类型声明、重命名等),再消除一些明显的坏味道(重复代码、依恋情结等),以此作为我们开始的起点。之后,我们再观察,新特性的添加是否简单,如果不是,下一个重构的目标应该是使这个特性变得更加简单,更不容易出错。如此一来,我们既能控制重构的规模,又能提供高质量的特性交付。

在这个清理的过程中,我们做了这些练习:

  • 巩固了先对代码做简单清理的习惯

  • 通过“提炼函数”消除了简单的重复代码

  • 通过“提炼变量”消除了耦合的硬编码

  • 通过“以对象取代基本类型”创建了领域对象,消除了“基本类型偏执”坏味道

  • 通过“搬移字段”“搬移函数”等手法消除了“依恋情结”“发散式变化”坏味道

  • 体会了代码结构随着重构浮现的节奏感

在重构过程中,我们仍然保持小步前进的优良传统,这样出错时可以很快地回滚代码到上一个可工作的状态。并且,我们带着明确的目标来开展重构工作:要么是为了消除一个明显的坏味道,要么是为了让新特性的添加变得简单。有了这个节奏,加上小步前进带来的随时停止的能力,我们就可以有条不紊地把握重构的起止,在“添加新特性”和“重构”这两顶帽子间随时切换。这样既不会耽误新特性的开发,又可以一步步地慢慢清理旧代码,让代码库越来越好。

Last updated