测试驱动开发与观察循环
2014年5月9日 by Max Kanat-Alexander
今天在Kent Beck、Martin Fowler和David Heinemeier Hansson之间进行了一场关于测试驱动开发(TDD)本质和使用的有趣讨论。TDD是一种先写测试再写代码的开发方法。
对话中的每位参与者都有不同的个人编码偏好,这很合理。然而,从每位参与者的个人偏好中可以提取出一个相同的原则:“在做出决策之前,我需要观察一些东西。”
Kent经常(虽然不总是)喜欢先写测试,这样他可以在编码时观察测试的行为。David经常(虽然不总是)想先写一些初始代码,观察它来决定如何编写更多代码,依此类推。即使当他们谈论替代方法时(例如Kent谈到他不使用TDD的时候),他们仍然总是谈到将观察作为开发过程的内在组成部分。
观察循环:软件开发的基础模式
这个原则如此广泛,以至于你可以说所有软件开发的循环是:观察 → 决策 → 行动 → 观察 → 决策 → 行动 → 等等。
如果你想给这个循环起个名字,可以称之为"观察循环"或"ODA"。
实际示例
在TDD中,循环看起来像这样:
- 发现问题(观察)
- 决定解决问题(决策)
- 编写测试(行动)
- 查看测试并检查API是否看起来良好(观察)
- 如果看起来不好,决定如何修复(决策),更改测试(行动),并重复观察→决策→行动循环,直到对API满意
- 运行测试并看到测试失败(观察)
- 决定如何让测试通过(决策)
- 编写一些代码(行动)
- 运行测试并查看是通过还是失败(观察)
- 如果失败,决定如何修复(决策)并编写代码(行动),直到测试通过(观察)
- 根据软件设计原则、问题知识或在编写先前代码时获得的数据,决定下一步要做什么(决策)
另一种有效的方法是先编写代码。与上述序列的区别在于第3步将是"编写一些代码"而不是"编写测试"。然后你观察代码本身来做出进一步的决定,或者在代码之后编写测试并观察这些测试。
存在许多有效的开发过程。
开发过程与生产力
有趣的是,据我所知,每个有效的开发过程都将这个循环作为其主要指导原则。即使是像Agile这样覆盖整个团队的大规模过程也内置了这个循环。事实上,Agile在某种程度上试图让团队拥有比之前破碎模型(瀑布模型,即"前期大设计")更短的观察-决策-行动循环(每几周一次),而瀑布模型需要数月或数年才能完成一个循环。
因此,较短的循环似乎比较长的循环更好。事实上,开发人员生产力的大部分目标可能仅仅通过将ODA循环缩短到对开发人员、团队或组织合理的最小时间周期来实现。
通常,你可以通过专注于观察步骤来实现这些较短的循环。一旦你这样做了,循环的其他两个部分往往会自行加速。(如果它们没有加速,还有其他补救措施,但那是另一篇文章的内容。)
在观察中有三个关键因素需要解决:
- 信息传递给开发人员的速度(例如,拥有快速测试)
- 传递给开发人员的信息的完整性(例如,拥有足够的测试覆盖率)
- 传递给开发人员的信息的准确性(例如,拥有可靠的测试)
这有助于我们理解近几十年来某些开发工具成功背后的原因。持续集成、生产监控系统、性能分析器、调试器、编译器中更好的错误消息、突出显示不良代码的IDE——几乎所有"有效"的工具之所以有效,是因为它们使观察更快、更准确或更完整。
有一个注意事项——你必须以人们能够实际接收的方式传递信息。如果你向人们倾倒大量信息而不让他们容易找到他们关心的特定数据,那么数据就变得无用。如果没有人收到生产警报,那么它就无关紧要。如果开发人员从不确信接收到的信息的准确性,那么他们可能会开始忽略它。你必须成功传达信息,而不仅仅是生成信息。
第一个ODA循环
有一个"大ODA循环"代表了软件开发的整个过程——看到问题,决定解决方案,并将其作为软件交付。在那个大循环中,有许多较小的循环(看到功能需求,决定功能应该如何工作,然后编写功能)。其中还有更小的循环(观察单个变更的需求,决定实现方式,编写一些代码),等等。
最棘手的部分是任何这些序列中的第一个ODA循环,因为你必须在没有先前决策或行动的情况下进行观察。
对于"大"循环,可能看起来你开始时没有什么可观察的。还没有代码或计算机输出可看!但实际上,你至少可以从观察自己开始。你有周围的环境。你有其他人可以交谈,有一个世界可以探索。你的第一次观察通常不是代码,而是现实世界中需要解决的、以某种方式帮助人们的问题。
然后当你进行开发时,有时你会遇到必须决定"下一步该做什么?“的时刻。这就是了解软件设计法则可以帮助的地方,因为你可以将它们应用于你编写的代码和你观察到的问题,这让你能够决定工作的顺序。你可以将这些原则视为一种二手观察形式——数千人年的经验被压缩成法则和规则,可以帮助你现在做出决策。只要准确,二手观察是完全有效的观察。
你甚至可以将观察过程本身视为它自己的小ODA循环:观察世界,决定将注意力放在某件事上,将注意力放在那件事上,观察它,基于此决定观察其他事物,等等。
使用这个原则的方式可能是无限的;以上所有内容仅代表几个例子。
-Max