重构并非设计的替代品

阅读数:1108 2009 年 2 月 10 日

话题:敏捷文化 & 方法

Stack overflow社区有人问了这样一个问题:“现在设计是重构的一个子集吗?”这个问题凸显了大家经常误解自然设计这种敏捷方法。敏捷中一个常用的信条是:“测试,编码,重构。如此反复!”然而这个方法并没有替代设计,只是把项目生命周期中的这种工作推广开来。

Phil H. 这样提出了他的问题:

新方法看上去是这样的:全心投入,把需要的东西编写出来,以完成特定范围内目标的第一阶段,然后根据需要重构,让解决方案显得优雅。代码库逐渐增加,永远 不会有很大的计划 / 分层设计这样的阶段。对我来说,这意味着软件设计被包含在重构之中,因为优雅的代码来自于重构的过程,而不是增量实现功能的过程。

难道我错了吗?



预先做大量的设计本身不是设计,它只是实现设计的一种方式。而敏捷实践者更倾向于另外一种方式,即当前的设计来自于实际要做的功能。设计是对系统需求的反应和适应,而系统需求本身会随着客户的需要在不断地发展和变化。

敏捷方法采用测试驱动,逐渐增加功能并演化系统设计,可以这样来表达:

  • 给新功能创建测试。
  • 运行测试,发现测试失败,因为功能还没有实现。
  • 编写恰好够用的代码实现需要的功能。
  • 运行测试,测试通过。
  • 重构代码,直到系统(包括新增的代码)变得优雅。

这种方法的本质是设计满足需要的功能就够了,不要受累去支持那些我们认为某天可能需要的功能。

Fabian Steeg 引用了 Kent Beck 的话,如此说道:

最终目标就是能够工作的简洁代码。[...] 首先我们解决“能够工作”这一部分,然后再解决“简洁代码”部分。这与架构驱动的开发恰恰相反,架构驱动的开 发中你首先解决“简洁代码”部分,然后当你解决“能够工作”的问题时,要从头开始,设法把你知道的东西集成到设计之中。

从字面意思上很容易让人误解这段话。有人就给了这样一个例子:

我在项目前期而不是中间就做很多决定,因为这时的成本最低。举例来说,如果早期我们使用平台依赖的技术开发程序,那么想替换该技术的话代价很高。如果开始编码前花时间考虑一下需要支持的平台,成本就低多了。

这个人就误解了“自然设计”的意思,认为敏捷开发人员预先根本不做思考。当前的设计需要综合考虑我们知道的所有信息。如果我们知道需要支持多个平台,就在设计中考虑到它。然而,如果确信只需要支持一个平台,我们不会因为‘某一天我们可能想移植’而更改设计。

敏捷的一些指导原则包括:

值得注意的是这些都是指导原则,不是值得盲目遵守的规则。之所以有这些原则是为了帮助熟练的开发人员做出决定,而不是告诉开发人员去做什么样的决定。

你是使用什么方法设计的呢?你怎样给代码和编码人员做架构的呢(没有毫无必要地限制它们)?欢迎留言与大家分享你的观点。

查看英文原文Refactoring Not a Substitute for Design