您如何使用TDD设计复杂系统?

时间:2010-08-16 16:01:29

标签: unit-testing tdd

Does TDD mean not thinking about class design?类似,我无法考虑传统的“设计”阶段适合TDD的位置。

根据保龄球游戏Kata(“对话”版本,其链接逃脱了我的目前),TDD似乎忽略了早期做出的设计决定(丢弃框架对象,滚动对象等)。我可以在这个例子中看到,遵循测试并忽略你最初的设计思路是一个好主意,但是在更大的项目或你想要为扩展/定制留下空间的那些项目中,放入的东西不是更好您没有立即测试或不需要立即测试,以避免以后进行耗时的重写?

简而言之 - 在进行TDD时设计的数量是多少,在编写测试和传递代码的代码时,我应该遵循多少设计(忽略我的设计只是担心通过测试)?

或者我是否担心什么,只是为了跟随测试编写的代码是而不是(在实践中)如果你被画到一个角落很难重写或重构? 或者,我是否忽略了这一点,当我来测试新的功能部分时,我应该期待重写部分代码?

4 个答案:

答案 0 :(得分:9)

我会根据您的初始设计进行测试。在许多方面,TDD是一个发现过程。您可以期望确认您的早期设计选择,或者发现您可以做出更好的选择。尽可能多地提前设计。有些人喜欢坐在椅子的座位上进行高级设计,并使用TDD来充实设计。虽然其他人喜欢先把纸上的东西都拿在纸上。

TDD的一部分是重构。

答案 1 :(得分:7)

当TDD被解释为“测试驱动设计”而不是“测试驱动开发”时,有关“设计大型复杂系统”的内容不应与TDD相关联 - 尤其是

在“开发”环境中,使用TDD将确保您编写可测试的代码,该代码提供了有关TDD的所有好处(早期检测错误,高代码:测试覆盖率,更轻松的未来重构等)等等。)

但在“设计”大型复杂系统中,TDD并未特别解决系统架构中固有的以下问题

  1. (工程)性能
  2. 安全
  3. 可扩展性
  4. 状况
  5. (和所有其他'能力')
  6. (即上述所有问题都没有通过“首先编写一个失败的测试用例,然后是工作实现,重构 - 泡沫,冲洗,重复...”配方)神奇地“出现”。

    • 对于这些,您需要通过在需求和问题空间所施加的约束条件下对系统的高级细节和低级细节进行白板处理来解决问题。

    • 上述一些考虑因素相互竞争,需要通过编写大量单元测试来进行谨慎的权衡,而这些因素并没有“出现”。

    • 一旦定义了关键组件及其职责, 据了解,TDD可用于 实现这些 部件 即可。重构和持续的过程 审查/改进您的代码将确保低级设计 这些组件的细节都精心制作。

    我还没遇到过以测试驱动的设计 风格完成的非常复杂的软件(例如编译器,数据库,操作系统)。以下博客文章非常清楚地论述了这一点(Compilers, TDD, Mastery

    另外,请检查以下videos on Architecture,这为思维过程增添了许多常识。

答案 2 :(得分:3)

从粗略的设计理念开始,选择第一个测试并开始编码,在测试后进行绿色测试,让设计出现,与初始设计相似或不相似。初始设计的多少取决于问题的复杂性。

必须注意并倾听和嗅探代码,检测重构机会和代码味道。

严格遵循TDD,SOLID principles将使代码清晰,可测试且灵活,以便可以轻松地重构,利用单元测试作为脚手架来防止回归。

答案 3 :(得分:2)

我发现了三种使用TDD进行设计的方法:

  • 允许设计自然地出现,因为重复和复杂性已被删除
  • 使用模拟结合单一责任原则,预先创建完美的设计
  • 务实。

实用主义似乎是大多数时候的最佳选择,所以这就是我的所作所为。如果我知道一个特定的模式非常适合我的问题(例如,MVC),我会直接去模拟并假设它有效。否则,如果设计不太清楚,我会允许它出现。

我认为需要重构紧急设计的交叉点是它不容易改变的重点。如果一段代码没有完美设计,但另一个代码可能很容易自己重构,那就足够了。如果代码变得如此复杂以至于它不再对另一个开发者显而易见,那么就该重构它。

我喜欢Real Options,重构一些完美的东西对我来说就像是在没有任何实际需要的情况下承诺设计。我反思“足够好”;这样,如果我的设计证明自己错了,我就没有浪费时间。如果你以前从未在类似的环境中使用它,那么假设你的设计是错误的。

这也让我可以比完美的代码更快地获取代码。话虽如此,我试图让代码更完美,这就教会了我的界限!