单一开发人员应该使用TDD的原因是什么?

时间:2008-10-01 13:57:11

标签: tdd methodology

我是一名有很多经验的合同程序员。我习惯于被客户雇用进入我自己的某种形式的软件项目,通常是从零开始。这意味着几乎每次都是干净的石板。我可以引入我开发的库来快速启动,但它们总是可选的。 (并且取决于在合同中获得正确的IP条款)很多时候我可以指定甚至设计硬件平台......所以我们在这里谈论严肃的自由。

我可以看到用于构建某些代码的自动化测试的用途:具有更多简单功能的库,具有大量引用的核心功能等。基本上,随着一段代码的价值在大量使用中上升,我可以看出,自动测试该代码会越来越有价值,以便我知道我不会破坏它。

然而,在我的情况下,我发现很难合理化任何东西。我会采用它们证明有用的东西,但我不会盲目跟随任何事情。

我发现我在'维护'中做的很多事情实际上都是小的设计变化。在这种情况下,测试不会为我节省任何东西,现在他们也必须改变。高度迭代,存根优先的设计方法对我来说非常有效。我无法通过更广泛的测试看到实际上节省了很多时间。

业余爱好项目更难以证明......他们通常都是从周末到月份的任何事情。边缘案例错误很少发生,它只是玩弄东西。

阅读诸如this one之类的问题,回答最多的回答似乎表明,在海报的经验/意见中,如果你的人数少于5人,TDD实际上会浪费时间(即使假设一定程度的能力/ TDD经验)。但是,这似乎涵盖了初始开发时间,而不是维护。目前尚不清楚TDD如何在项目的整个生命周期中叠加。

我认为TDD可以成为改善整个行业产品质量的有价值目标的一个很好的步骤。然而,理想主义本身不再能够激励我。

认为TDD对于大型团队或包含至少一个不可靠程序员的任何规模团队来说都是一个很好的方法。那不是我的问题。

为什么一个拥有良好记录的唯一开发者会采用TDD?

我很想知道在TDD上完成的任何指标(正式与否)......专注于独立开发人员或非常小的团队。

如果做不到这一点,你个人经历的轶事也会很好。 :)

请避免在没有经验的情况下陈述意见支持。让我们不要把它作为一场意识形态战争。此外,跳过更大的就业选择论点。 这只是一个效率问题。

21 个答案:

答案 0 :(得分:19)

  

我不会盲目跟随任何事情。

这是正确的态度。我一直都在使用TDD,但我并没有严格遵守它。

支持TDD的最佳论点(在我看来)是当你最终进入项目的重构和维护阶段时,你可以运行一组测试。如果这是您使用TDD的唯一原因,那么您可以随时编写测试,而不是盲目地遵循该方法。

我使用TDD的另一个原因是编写测试让我开始考虑我的API。在写这篇文章之前,我不得不考虑如何使用类。让我进入这个高水平的项目对我来说很有用。还有其他方法可以做到这一点,如果你发现其他方法(有很多)可以做同样的事情,那么我会说继续做对你有用的方法。

答案 1 :(得分:14)

我发现单独飞行时更有用。由于周围没有任何人可以反复提出想法并且没有人来执行同行评审,因此您需要确保您的代码是可靠的。 TDD / BDD将为您提供这种保证。但TDD有点反对。其他人可能完全不同意我的意思。

编辑:我可以补充一点,如果做得好,你可以在编写测试的同时为你的软件生成规范。这是BDD的一个很好的副作用。你可以让自己看起来像超级开发人员,如果你正在制定可靠的代码和规范,所有这些都是你自己的。

答案 2 :(得分:11)

好的轮到我了...我甚至可以自己做TDD(非尖峰/实验/原型代码),因为

  • 在你跳跃之前思考:在我开始编写代码之前,强迫我思考我想要完成的事情。我想在这里完成什么......'如果我认为我已经有了这件作品......我怎么能期望它起作用呢?'鼓励对象的界面设计。
  • 更容易更改:我可以放心地进行修改。'当我改变第5步时,我在步骤1-10中没有破坏任何东西。'回归测试是即时的
  • 出现更好的设计:如果没有我在设计活动中投入精力,我发现了更好的设计。 test-first + Refactoring导致松散耦合,最小的类,最少的方法..没有过度工程..没有YAGNI代码。这些类具有更好的公共接口,小方法并且更具可读性。这是一种禅宗的事情......你只会注意到你得到它时会得到它。
  • 调试器不再是我的拐杖:我知道我的程序做了什么......而不必花费数小时来通过我自己的代码。现在如果我花了超过10分钟的调试器..心理警报开始振铃。
  • 帮助我准时回家我注意到自TDD以来我的代码中的错误数量显着减少..即使断言类似于控制台跟踪而不是xUnit类型AT。
  • 生产力/流量:它帮助我确定下一个离开的婴儿步骤,它将带我完成...保持滚雪球滚动。 TDD帮助我更快地进入节奏(或XPers呼叫流程)。每单位时间我完成了比以前更大的质量工作。红绿重构循环变成了......一种永动机。
  • 只需按一下按钮即可证明我的代码可以
  • 练习做得很完美我发现自己在学习和学习更快地发现龙..在我的腰带下有更多的TDD时间。也许是不和谐..但我觉得TDD让我成为一个更好的程序员,即使我没有先测试。发现重构机会已成为第二天性......

如果我再想一想,我会更新......这是我在最后2分钟的反思中提出的。

答案 3 :(得分:6)

我也是合约程序员。这是我的12 Reasons Why I Love Unit Tests

答案 4 :(得分:3)

我对TDD的最佳体验是围绕pyftpdlib项目。大部分的开发都是由原作者完成的,我做了一些小的贡献,但它本质上是一个独立的项目。该项目的测试套件非常全面,并测试了FTPd库的所有主要功能。在签入更改或发布版本之前,将检查所有测试,并且在添加新功能时,测试套件也会始终更新。

作为这种方法的结果,这是我曾经做过的唯一一个项目,它没有在新发布后出现showstopper错误,检查了更改,破坏了一个主要功能,等等。代码非常在项目的整个生命周期中,很少有错误报告被打开,我一直对此印象深刻。我(和原作者)将这一成功的大部分归功于综合测试套件以及随意测试每个主要代码路径的能力。

从逻辑角度来看,您编写的任何代码都必须进行测试,如果没有TDD,您将自己手动测试。另一方面是pyftpdlib,错误数量和主要问题频率最差的代码是开发人员和QA手动尝试新功能的代码。由于时间紧缩或从裂缝中掉落,事情没有得到测试。旧的代码路径被遗忘,即使是最古老的稳定功能也最终会破坏,主要版本最终会失去重要的功能。手动测试对于验证和测试的一些随机化至关重要,但根据我的经验,我认为必须同时进行手动测试和精心构建的单元测试框架。在这两种方法之间,覆盖范围的差距较小,只能减少问题发生的可能性。

答案 5 :(得分:2)

您是否是唯一的开发者并不重要。您必须从应用程序的角度来考虑它。所有应用程序都需要正常工作,所有应用程序都需要维护,所有应用程序都需要减少错误。当然,某些情况下TDD方法可能不适合您。这是截止日期非常快,没有时间进行单元测试。

无论如何,TDD不依赖于独奏或团队环境。这取决于整个应用程序。

答案 6 :(得分:2)

我没有丰富的经验,但我有过看到与测试方法截然不同的经验。

在一项工作中,没有自动化测试。 “测试”包括在应用程序中四处寻找,尝试一下你头脑中的任何东西,看它是否破了。毋庸置疑,破解代码很容易到达我们的生产服务器。

在我目前的工作中,有很多自动化测试和完整的CI系统。现在,当代码被破坏时,它立即显而易见。不仅如此,但在我工作时,测试确实记录了我的代码中有哪些功能,以及尚未实现的功能。它让我对能够添加新功能充满信心,知道如果我打破现有功能,它就不会被忽视。

所以,对我来说,这不仅取决于团队的规模,还取决于应用程序的规模。你能跟踪应用程序的每个部分吗?每个要求?您需要运行哪些测试以确保应用程序正常运行?如果您没有测试来证明应用程序是“正常工作”,它甚至意味着什么呢?

只需我0.02美元。

答案 7 :(得分:2)

测试允许您自信地重构您没有破坏系统。首先编写测试允许测试定义系统的工作行为。根据定义,测试未定义的任何行为都是副产品,并且在重构时允许更改。首先编写测试也可以使设计朝着良好的方向发展。为了支持可测试性,您会发现需要解耦类,使用接口并遵循良好模式(例如,控制反转)以使代码易于测试。如果您之后编写测试,则无法确定是否已涵盖测试中系统的所有预期行为。您还发现有些东西因设计而难以测试 - 因为它可能是在没有测试的情况下开发的 - 并且很容易吝啬或省略测试。

我一般都是单独工作,而且大多数都是做TDD的 - 我不在的地方就是我没有辜负我的做法,或者还没有找到一种适合我做TDD的好方法,例如使用Web界面。

答案 8 :(得分:1)

TDD不是关于编写代码的测试。因此,它甚至为单个开发人员提供了许多好处。对于许多开发人员而言,编写更强大的代码是一种精神错误。例如,您多久会想到“现在这段代码怎么会失败?”在没有TDD编写代码后?对于许多开发人员来说,这个问题的答案是没有。对于TDD实践者来说,它会将思维模式转变为在执行某些操作之前检查对象或字符串是否为空,因为您正在编写测试以专门执行此操作(中断代码)。

另一个主要原因是变化。无论何时与客户打交道,他们似乎都无法下定决心。唯一不变的是变化。 TDD帮助作为“安全网”找到可能破坏的所有其他区域。即使是小型项目,这也可以防止您在调试器中浪费宝贵的时间。

我可以继续,但我认为TDD更多的是编写代码而不是任何足以证明它作为唯一开发人员的用途。

答案 9 :(得分:1)

TDD让我更清楚地定义了脑海中的问题。这有助于我专注于实现所需的功能,仅此而已。它还有助于我创建更好的API,因为在编写代码之前我正在编写“客户端”。我也可以重构,而不必担心破坏任何东西。

答案 10 :(得分:1)

我倾向于同意你的观点对于“一个开发者”或“爱好”项目的TDD开销的有效性,而这些项目并不能证明费用的合理性。

但是,如果长期一致地应用大多数最佳实践,那么大多数最佳实践都是相关且有用的。

例如,TDD在长时间内保存您的测试/错误修正时间,而不是在您创建第一次单元测试后的5分钟内。

您是合同程序员,这意味着您将在完成后离开当前项目并切换到其他项目,最有可能是在另一家公司。您当前的客户必须维护和支持您的应用程序。如果你不让支持团队成为一个好的框架,他们就会被困住。 TDD将帮助该项目实现可持续发展。它将增加代码库的稳定性,因此其他经验较少的人不会在尝试更改时不会造成太大的损害。

同样适用于爱好项目。你可能已经厌倦了,并希望将它传递给某人。你可能会在商业上取得成功(想想Craiglist),除了你之外还会有5个人在工作。

即使只是获得了经验,在正确的过程中投资总能得到回报。但大多数时候,当你开始一个新项目时,你会感激不尽,

在做某事时,您必须考虑 OTHER 。您必须提前考虑,计划增长,计划可持续性

如果你不想这样做 - 坚持牛仔编码,这样就简单了。

P.S。同样的事情也适用于其他做法:

  • 如果你没有评论你的代码并且你有理想的记忆你会没事的,但其他人不会阅读你的代码。
  • 如果您没有记录与客户的讨论,那么其他人对您做出的关键决定一无所知

等无限广告

答案 11 :(得分:1)

如果没有合理的单元测试,我不再重构任何东西。

我不首先使用单元测试进行全面的TDD,然后进行第二次代码测试。我做CALTAL - Code A LIttle,Test A Little - development。通常,代码优先,但并非总是如此。

当我发现我必须重构时,我确保我已经有足够的测试,然后我完全相信我不需要保持整个旧架构变成 - 我脑海中的新建筑计划。我只需要让测试再次通过。

我重构了重要的部分。获取现有的测试套件。

然后我意识到我忘记了一些东西,而且我又回到了CALTAL开发的新东西。

然后我看到我忘记删除的内容 - 但是他们真的在任何地方都没有使用过吗?删除它们并查看测试中的失败。

就在昨天 - 通过大规模重构的一部分 - 我意识到我仍然没有完全正确的设计。但测试仍然需要通过,所以在我完成第一次重构之前,我可以自由地重构我的重构。 (哇!)这一切都很顺利,因为我有一套测试来验证变化。

飞行独奏TDD是我的副驾驶。

答案 12 :(得分:0)

我觉得作为一个项目的独立开发者,特别是一个更大的项目,你往往会变得非常薄 您正处于大型重构的过程中,突然发现一些关键错误,这些错误由于某些原因在预发布测试期间未显示出来。在这种情况下,你必须丢弃所有东西并修理它们,在花了两周时间撕掉你的头发之后你终于可以回到你以前做的任何事情了。
一个星期后,你的一个最大的客户意识到他们绝对必须拥有这个很酷的新亮点功能,否则他们就不会下订单他们应该在一个月前订购的那些1M单位。
现在,三个月后你甚至都不记得你为什么开始重构,更不用说你重构的代码应该做什么了。感谢上帝,你在编写这些单元测试方面做得很好,因为至少他们告诉你,你的重构代码仍然在做它应该做的事情。
泡沫,冲洗,重复。

过去6个月我的生活故事。 : - /

答案 13 :(得分:0)

激发自我兴趣。

就我而言,唯一的开发人员会转换为小企业主。我写了一些合理数量的库代码(表面上)让我的生活更轻松。很多这些例程和类都不是火箭科学,因此我可以非常肯定它们能够正常工作(至少在大多数情况下)通过查看代码,一些现场测试和调试方法来确保它们的行为方式我认为他们做到了。蛮力,如果你愿意的话。生活很美好。

随着时间的推移,这个库会增长并在不同客户的更多项目中使用。测试变得更加耗时。特别是我(希望)修复错误和(甚至更有希望)不破坏其他东西的情况。这不仅仅是我代码中的错误。我必须小心添加功能(客户不断要求更多“东西”)或确保代码在移动到我的编译器(Delphi!),第三方代码,运行时环境或操作系统的新版本时仍然有效。

采取极端的做法,我可以花更多的时间来审查旧代码而不是处理新的(读取:可计费的)项目。可以把它想象成软件的休止角度(在未经测试的软件崩溃之前,你可以将它堆叠多高)。

像TDD这样的技术为我提供了更经过精心设计,更全面测试的方法和类(在客户获得之前),并且需要更少的维护。

最终,它意味着更少的时间进行维护,花更多的时间来做更有利可图,更有趣(几乎任何事情)和更重要的事情(比如家庭)。

答案 14 :(得分:0)

以下是一些模因和我的回答:

“TDD让我想到它会如何失败,这让我成为一名更好的程序员”

如果有足够的经验,高度关注失败模式应该自然而然地成为你的过程的一部分。

“应用程序需要正常运行”

这假设您能够完全测试所有内容。您首先要正确地覆盖所有可能的测试,而不是正确地编写功能代码。 “应用程序需要更好地工作”是一个更好的论据。我同意这一点,但它是理想主义的,并不足以让我尽可能多地激励。指标/轶事在这里会很棒。

“我的<库组件X>”

非常适合

我在问题中说过,我在这些案例中看到了价值,但感谢轶事。

“想想下一个开发者”

这可能是我最好的论据之一。然而,下一个开发人员很可能也不会练习TDD,因此在这种情况下它将是浪费甚至可能是负担。后门传福音就是那里的。我很确定TDD开发人员真的会指出它。

当您继承一个已弃用的必备方法时,您会欣赏多少项目? RUP,有人吗?想想TDD对于下一个开发者来说意味着什么,如果TDD没有人人想象的那么大。

“重构更容易”

重构是一项与其他技能一样的技能,迭代开发当然需要这种技能。如果我认为新设计从长远来看会节省时间,我倾向于丢弃大量的代码,并且感觉会丢失大量的测试。哪个更有效率?我不知道。

...

我可能会向任何新人推荐一定程度的TDD ...但是我已经遇到过几次已经出现过障碍的人的好处。我可能会开始向库中添加自动化测试。这样做之后,我可能会看到更多的价值。

答案 15 :(得分:0)

我认为TDD作为一种方法论不仅仅是“在进行更改时进行测试”,因此它不依赖于团队或项目规模。这是关于注意到一个人对一个代码/一个应用程序的作用的期望在一个人开始真正思考如何实现所述行为之前。 TDD的主要焦点不仅是为编写代码进行了测试,而且编写了更少的代码,因为您只是做了使测试成为绿色(以及稍后重构)的内容。

如果你像我一样,并且发现很难想到部分/整个应用程序的功能而不考虑如何实现它,我认为在代码之后编写测试并因此让代码“很好”推动“测试。

如果您的问题不是关于测试优先(TDD)或测试优先(良好的编码?),我认为测试应该是任何开发人员的标准做法,无论是单独的还是在一个大团队中,谁创建代码生产时间超过三个月。在我的经验中,即使原始作者必须仔细思考这些二十行复杂的,超级优化的,但是稀疏文档的代码真正代码所做的事情。如果你已经完成了测试(涵盖了代码中的所有路径),那么就更少思考了 - 甚至更少的ERR,甚至几年之后......

答案 16 :(得分:0)

您的客户在交付产品时是否拥有源代码?如果您能说服他们通过单元测试交付产品可以增加价值,那么您就可以向上销售服务并提供更好的产品。从客户端的角度来看,测试覆盖率不仅可以确保质量,还可以让未来的维护者更容易理解代码,因为测试将功能与UI隔离开来。

答案 17 :(得分:0)

唯一的开发人员应该在他的项目中使用TDD(跟踪记录无关紧要),因为最终这个项目可以传递给其他开发人员。或者可以引进更多的开发人员。

如果没有测试,新人将非常难以使用代码。他们会打破局面。

答案 18 :(得分:0)

首先编写测试的重点是它强制执行您正在制定的要求和设计决策。当我修改代码时,我想确保它们仍然是强制执行的,并且很容易在没有编译器或运行时错误的情况下“破坏”某些东西。

我有一个测试优先的方法,因为我希望对我的代码有很高的信心。当然,测试需要进行良好的测试,否则他们不会执行任何操作。

我有一些非常庞大的代码库,我正在处理这些代码库,并且还有许多非常重要的内容。当X永远不会发生时,很容易做出波动和突然发生X的变化。我的测试多次使我免于犯了一个可能被人类测试人员忽视的关键(但微妙)错误。

当测试失败时,他们有机会查看它们和生产代码并确保它是正确的。有时设计会发生变化,需要修改测试。有时我会写一些通过100次测试中的99次的东西。那个没有通过的测试就像一个同事在审查我的代码(在某种意义上),以确保我仍在构建我应该构建的东西。

答案 19 :(得分:0)

我会很快回答这个问题,希望你会开始看到一些推理,即使你仍然不同意。 :)

如果你足够幸运能够参与一个长期运行的项目,那么有时你会想要在向上移动堆栈之前首先编写数据层,然后编写业务层。如果您的客户端随后需要更改需要在数据层上重新处理的需求,那么对数据层进行一系列单元测试将确保您的方法不会以不合需要的方式失败(假设您更新测试以反映新的需求) )。但是,您可能也会从业务层调用数据层方法,并且可能在多个位置调用。

假设你有3次调用业务层中的方法,但你只修改2.在第三种方法中,你可能仍然从数据层获取看似有效的数据,但可能会破坏某些方法您之前几个月编码的假设。此级别(及以上)的单元测试应该设计为发现破坏的假设,如果失败,他们应该向您强调有一部分代码需要重新访问。

我希望这个非常简单的例子足以让你更多地思考TDD,它可能会产生一个让你考虑使用它的火花。当然,如果你仍然没有看到这一点,并且你对自己跟踪成千上万行代码的能力充满信心,那么我没有地方可以告诉你应该启动TDD。

答案 20 :(得分:-1)

我们都是拥有良好记录的开发人员。毕竟,我们都在阅读Stackoverflow。而且我们许多人都使用TDD,也许这些人有很好的记录。我之所以被录用,是因为人们希望有人编写出色的测试自动化并可以将其教给他人。独自一人工作时,我在家中对编码项目进行TDD,因为我发现如果不这样做,我会花时间进行手动测试甚至调试,谁需要它。 (也许这些人只有良好的跟踪记录。我不知道。)

当要成为一名优秀的驾驶员时,每个人都认为自己是“良好的驾驶员”。这是所有驾驶员的认知偏见。程序员有自己的偏见。 Agile Thoughts podcast series涵盖了OP之类的开发人员不进行TDD的原因。播客归档文件中还包含有关测试自动化概念(例如test pyramid)的内容,以及关于什么是TDD以及为什么要从podcast archive的第9集开始编写测试的简介。