testing驱动开发的缺点?

采用testing驱动devise会损失什么?

仅列出底片; 不要列出以负面forms写的好处。

几个缺点(我没有声称没有任何好处 – 特别是在编写项目的基础时 – 最终会节省很多时间):

  • 大时间投资。 对于简单的情况,你会失去大约20%的实际执行情况,但是对于复杂的情况你会损失更多。
  • 额外的复杂性。 对于复杂的情况你的testing用例很难计算,我build议在这种情况下尝试使用自动引用代码,这些代码将在debugging版/testing运行中并行运行,而不是最简单情况下的unit testing。
  • devise影响。 有时候,devise在开始时并不清晰,随着进展而发展,这将迫使您重新进行testing,这将导致大量的时间浪费。 我会build议在这种情况下推迟unit testing,直到你有一些devise的把握。
  • 连续调整。 对于数据结构和黑匣子algorithm,unit testing是完美的,但对于往往会改变,调整或微调的algorithm,这可能会导致大量的时间投入,人们可能认为这是不合理的。 所以,当你认为它适合系统时,请使用它,不要强迫devise适合TDD。

如果你想做“真正的”TDD(阅读:首先testing红色,绿色,重构步骤),那么当你想testing积分点时,你也必须开始使用模拟/存根。

当你开始使用模拟,一段时间后,你会想开始使用dependency injection(DI)和控制反转(IoC)容器。 要做到这一点,你需要使用接口的一切(本身有很多陷阱)。

在一天结束的时候,你必须编写更多的代码,而不是像“简单的老式”那样。 而不仅仅是一个客户类,你还需要编写一个接口,一个模拟类,一些IoCconfiguration和一些testing。

并且请记住testing代码也应该被维护和关心。 testing应该像其他所有的一样可读,编写好的代码需要时间。

许多开发人员不太明白如何做到“正确的方式”。 但是因为每个人都告诉他们TDD是开发软件的唯一真正方法,他们只是尽其所能。

这比想象的要难得多。 通常使用TDD完成的项目最终会有许多没有人真正理解的代码。 unit testing经常testing错误的东西,错误的方式。 没有人同意一个好的testing应该是什么样子,甚至不是所谓的大师。

所有这些testing都会让系统的行为“变化”(与重构相对)变得更加困难,简单的更改变得过于困难和耗时。

如果你阅读TDD文献,总会有一些非常好的例子,但是在现实生活中经常需要用户界面和数据库。 这是TDD变得非常困难的地方,而且大多数来源都不能提供很好的答案。 如果他们这样做,它总是涉及到更多的抽象:模拟对象,编程到一个接口,MVC / MVP模式等,这又需要大量的知识,并且…你必须编写更多的代码。

所以要小心……如果你没有一个热心的团队,至less有一个有经验的开发人员知道如何编写好的testing,也知道一些关于优秀架构的东西,那么在进入TDD之前,你必须三思而行。

当你有大量testing时,更改系统可能需要重新编写一些或全部testing,具体取决于哪些testing被更改无效。 这可能会将相对较快的修改转化为非常耗时的修改。

此外,您可能会更多地基于TDD做出devise决策,而不是基于实际的优秀devise原则。 鉴于你可能有一个非常简单,简单的解决scheme,不可能testingTDD的需求,你现在有一个更复杂的系统,实际上更容易出错。

我认为对我来说最大的问题是“接近它”所花费的时间的巨大损失。 我在开始TDD之旅的时候还是很在行的(如果你有兴趣的话,请参阅我的博客,了解我的testing冒险的最新消息),而且我已经花了几个小时开始了。

把你的大脑变成“testing模式”花费很长时间,编写“可testing代码”本身就是一个技巧。

TBH,我非常不同意Jason Cohen关于私有化方法的评论 ,这不是这个意思。 我的新工作方式比以前没有更多的公开方法 。 但是,它确实涉及架构变更,并允许您“热插拔”代码模块,以使其他所有内容更易于testing。 你应该让你的代码的内部更容易做到这一点。 否则,我们又回到了一个公开的东西,封装在哪里呢?

所以,(IMO)简而言之:

  • 思考的时间(即实际testing )。
  • 知道如何编写可testing代码所需的新知识。
  • 了解使代码可testing所需的体系结构更改。
  • 提高你的“TDD编码器”的技能,同时努力提高我们的光荣编程工艺所需的所有其他技能:)
  • 组织您的代码库,包括testing代码,而不用拧你的生产代码。

PS:如果你想链接到正面,我已经问及回答了几个问题,检查我的个人资料 。

在我练习testing驱动开发的几年中,我不得不说,最大的缺点是:

把它卖给pipe理层

TDD最好是成对完成。 首先,当你知道如何编写一个if / else语句时,很难抵制只写实现的冲动。 但一双会让你继续任务,因为你让他保持任务。 可悲的是,许多公司/pipe理者不认为这是一个很好的资源利用。 为什么要支付两个人写一个function,当我有两个function需要在同一时间完成?

把它卖给其他开发者

有些人只是没有耐心编写unit testing。 有些人为自己的工作感到自豪。 或者,有些人就像看到复杂的方法/function在屏幕的末尾stream血一样。 TDD不适合每个人,但我真的希望是这样。 这将使那些inheritance代码的可怜灵魂更容易维护。

维护testing代码以及​​您的生产代码

理想情况下,只有当你做出错误的代码决定时,你的testing才会中断。 也就是说,你认为这个系统是一种方法,事实certificate它没有。 通过打破一个testing,或一个(小)testing,这实际上是个好消息。 你确切知道你的新代码将如何影响系统。 然而,如果你的testing写得不好,紧密耦合,或者更糟的是( 咳嗽 VStesting),那么维护你的testing可以很快成为合唱团。 而且,在足够多的testing开始导致更多的工作,而他们正在创造的感知价值,那么testing将是第一个东西被删除,当时间表被压缩(例如,它的关键时刻)

编写testing,以便覆盖所有内容(100%的代码覆盖率)

理想情况下,如果您坚持使用方法论,您的代码默认会被100%testing。 通常情况下,我想代码覆盖率达到了90%以上。 这通常发生在我有一些模板样式体系结构,并且基础已经过testing的时候,我尝试去偷工减料,而不是testing模板自定义。 另外,我发现当我遇到一个我以前没有遇到的新障碍时,我有一个学习曲线来testing它。 我会承认写一些代码行旧的skool的方式,但我真的很喜欢有这个100%。 (我想我在学校是成功的,呃skool)。

然而,我想说的是,TDD的好处远远超过了一个简单的想法,即如果你能够获得一套覆盖你的应用程序但不是非常脆弱以至于改变了所有应用程序的testing,你会能够像第一天一样,在项目的第300天不断添加新的function。所有那些尝试TDD的人都不会想到这是所有错误代码的灵丹妙药,所以他们认为它可以工作,时间。

就我个人而言,我发现使用TDD编写更简单的代码,我花更less的时间辩论某个特定的代码解决scheme是否可行,而且我不担心要更改任何不符合标准的代码行团队。

TDD是一门很难掌握的学科,而且我已经学了几年了,而且我仍然一直在学习新的testing技术。 这是一个很长时间的投资,但从长远来看,如果没有自动化的unit testing,您的可持续性将会大大增加。 现在,如果只有我的老板可以弄清楚这一点。

在您的第一个TDD项目中,有两个重大的损失,时间和人身自由

你失去了时间,因为:

  • 创build全面的,重构的,可维护的单元和验收testing套件为项目的第一次迭代增加了大量时间。 从长远来看,这可能会节省时间,但是同样也可以不用时间。
  • 您需要select并成为一套核心工具的专家。 unit testing工具需要通过某种模拟框架进行补充,并且都需要成为自动化构build系统的一部分。 您还需要select并生成适当的指标。

你失去个人自由,因为:

  • TDD是一种非常有纪律的编写代码的方法,它倾向于与技能规模的顶部和底部的那些人进行比较。 总是以某种方式编写产品代码,并让您的工作持续进行同行评审,可能会使您最糟糕的和最好的开发人员感到厌烦,甚至导致人员stream失。
  • embeddedTDD的大多数敏捷方法都要求你不断地与客户谈论你想要完成的事情(在这个故事/每天/无论什么)以及什么是交易。 再次,这不是每个人的茶,无论是在围墙和客户的开发者方面。

希望这可以帮助

TDD要求您在编写代码来通过这些testing之前计划您的类将如何运行。 这是一个加号和一个减号。

在任何代码写入之前,我发现很难在“真空”中编写testing。 根据我的经验,当我写作我自己写的初级testing时忘记的课程的时候,我不可避免地想到了一些事情,所以我倾向于考试。 那么现在是时候不仅要重构我的课程,而且还要testing我的课程。 重复这个三四次,可能会感到沮丧。

我更喜欢写我的课程草稿,然后写(并维护)一组unit testing。 我草稿之后,TDD对我来说工作的很好。 例如,如果有错误报告,我会编写一个testing来利用这个错误,然后修复代码,以便testing通过。

使用TDD时,原型devise可能非常困难 – 当您不确定要采取何种解决scheme时,预先编写testing可能很困难(非常广泛)。 这可能是一个痛苦。

老实说,我认为绝大多数项目的“核心发展”不存在真正的缺点, 它通常被那些相信自己的代码足够好以至于不需要testing的人(从来不是这样)以及那些只是普通的人不会被困扰的人写下来而被低估了。

那么,这个扩展,你需要debugging你的testing。 而且,编写testing也有一定的成本,尽pipe大多数人都认为这是一个预先投资,在节省的debugging时间和稳定性方面都能在应用程序的整个生命周期中得到回报。

但是,我个人最大的问题是,要开始写实验。 在一个团队,尤其是一个老牌团队中,很难说服他们花费的时间是值得的。

在testing所有代码之前,您已经失去了说“完成”的能力。

在运行之前,您将失去编写数百或数千行代码的能力。

你失去了通过debugging学习的机会。

你失去了运送你不确定的代码的灵活性。

你失去了将模块紧密结合的自由。

您将无法跳过编写低级devise文档的选项。

你失去了所有人都害怕改变的代码的稳定性。

你失去了“黑客”的称号。

TDD的缺点是它通常与“敏捷”方法密切相关,它重视系统的文档,而是理解为什么testing“应该”返回一个特定的值而不是其他任何其他值只存在于开发者的头。

只要开发者离开或忘记testing返回一个具体的价值,而不是其他的原因,你拧了。 TDD是好的,如果它有充分的文件logging,并且被世界变化和应用程序需要的5年内可以引用的人类可读的(即尖头的pipe理器)文档包围。

当我提到文档时,这不是代码中的事情,这是应用程序外部的官方文章,例如经理,律师和需要更新的可怜的SAP人员可以参考的用例和背景信息你的代码在2011年。

如果你的testing不够彻底,你可能会因为testing通过而陷入“一切正常”的错觉。 从理论上讲,如果你的testing通过了,代码正在工作。 但是如果我们能够在第一次完全写代码的时候不需要testing的话。 这里的道德是在完成任务之前确保自己做一个完整的检查,而不是只依靠testing。

在这一点上,如果你的理智检查发现一些没有经过testing的东西,一定要回去写一个testing。

我遇到过几个TDD让我发疯的情况。 举一些:

  • testing用例可维护性:

    如果你在一个大企业,很多机会是你不必自己写testing用例,或者当你进入公司时至less大部分都是别人写的。 应用程序的function会不时发生变化,如果您没有适当的系统(如HP Quality Center)来跟踪这些function,您很快就会发疯。

    这也意味着要花费新的团队成员相当多的时间来抓住testing用例。 反过来,这可以转化为更多所需的资金。

  • testing自动化复杂度

    如果您将部分或全部testing用例自动化为机器可运行的testing脚本,则必须确保这些testing脚本与其相应的手动testing用例同步,并符合应用程序更改。

    此外,您将花时间debugging帮助您发现错误的代码。 在我看来,这些错误大部分来自testing团队未能反映自动化testing脚本中的应用程序更改。 业务逻辑,GUI和其他内部的东西的变化可以使你的脚本停止运行或不可靠的运行。 有时这些变化非常微妙,难以察觉。 一旦我所有的脚本报告失败,因为他们根据表1的信息进行计算,而表1现在是表2(因为有人在应用程序代码中交换了表对象的名称)。

最大的问题是不懂如何编写适当的unit testing的人。 他们编写相互依赖的testing(他们使用Ant运行得很好,但是当我从Eclipse运行它们时突然失败,只是因为它们以不同的顺序运行)。 他们编写不testing任何东西的testing – 他们只是debugging代码,检查结果,并将其更改为testing,称之为“test1”。 它们扩大了类和方法的范围,仅仅是因为编写unit testing会更容易。 unit testing的代码是可怕的,所有的经典编程问题(重耦合,500行长的方法,硬编码值,代码重复),是一个地狱维护。 出于某种奇怪的原因,人们把unit testing看作不如“真实”代码的东西,他们根本不关心它们的质量。 🙁

你花了很多时间写testing。 当然,在项目结束的时候可以通过更快地捕捉错误来保存。

最大的缺点是,如果你真的想要正确地使用TDD,那么在你成功之前,你将不得不失败很多。 鉴于有多less软件公司工作(美元每KLOC),你最终会被解雇。 即使你的代码更快,更清洁,更容易维护,并且有更less的错误。

如果您在一家由KLOC支付给您的公司工作(或实施的要求 – 即使未经testing),请远离TDD(或代码评审,配对编程或持续集成等)等。

我第二个关于初始开发时间的答案。 没有testing的安全性,你也失去了安逸的工作能力。 我也被描述为一个TDD螺母,所以你可能会失去一些朋友;)

它变慢了。 从长远来看,悲伤并不是真的,它会为你省去麻烦,但是你最终会写更多的代码,所以可以说你花时间在“testing不编码”上了。 这是一个有缺陷的论点,但你曾经问过!

你将失去多重责任的大class。 你也可能会失去多重责任的大方法。 你可能会失去一些重构的能力,但是你也会失去一些重构的需要。

杰森·科恩(Jason Cohen)表示:TDD需要一个特定的组织来完成你的代码。 这在架构上可能是错误的; 例如,由于私有方法不能在类之外调用,所以必须使方法非私有才能使其成为可testing的。

我说这表示一个错过的抽象 – 如果私有代码真的需要testing,它应该可能在一个单独的类。

戴夫曼

您必须以不同的方式编写应用程序:使其可testing的应用程序。 你会很惊讶这是多么困难的一开始。

有些人在写太难之前就会想到自己要写什么的概念。 诸如嘲笑的概念对于一些人来说也可能是困难的。 传统应用中的TDD可能非常困难,如果它们不是为了testing而devise的。 TDD围绕TDD友好的框架也可能是一个难题。

TDD是一种技能,所以初级开发者最初可能会挣扎(主要是因为他们没有被教导这样工作)。

总的来说,当人们变得技术娴熟,你们最终将“臭”的代码抽象出来,并且拥有一个更加稳定的系统的时候,这些缺点就会得到解决。

重新集中于难以预料的要求是程序员不断的诅咒。 testing驱动的开发迫使你把注意力集中在已经知道的世俗需求上,并将你的开发限制在已经想象的范围内。

想想看,你很可能会针对具体的testing案例进行devise,所以你不会有创意,并开始思考“如果用户可以做X,Y和Z,这将是很酷的”。 因此,当用户开始对潜在的冷却要求X,Y和Z感到兴奋时,您的devise可能过于拘泥于已经指定的testing用例,并且难以调整。

这当然是一把双刃剑。 如果你花费你所有的时间去devise一个用户可能想要的每一个可以想象的,可以想象的X,Y和Z,你将不可避免地完成任何事情。 如果你做了一些事情,任何人(包括你自己)都不可能知道你在代码/devise中做了什么。

这需要一段时间才能进入,有时候在一个项目中开始,但是…当我发现一个愚蠢的错误,自动化testing可能发现非常快时,我总是后悔没有做一个testing驱动的方法。 另外,TDD改进了代码质量。

  • unit testing的代码写得比较多,因此前期开发成本较高
  • 这是更多的代码来维护
  • 需要额外的学习

很好的答案。 我会添加一些方法来避免TDD的黑暗面:

  • 我已经编写了应用程序来做自己的随机自我testing。 编写特定testing的问题是,即使你写了很多,他们只涵盖你想到的情况。 随机testing发生器发现你没有想到的问题。

  • 大量的unit testing的概念意味着你有可能进入无效状态的组件,比如复杂的数据结构。 如果远离复杂的数据结构,那么testing的数量就会减less很多。

  • 在您的应用程序允许的范围内,请避开依赖于通知,事件和副作用的正确sorting的devise。 那些可以很容易地下降或搅乱,所以他们需要大量的testing。

TDD需要一个特定的组织来处理你的代码。 这可能是低效或难以阅读的。 甚至在架构上是错误的; 例如,由于private方法不能在类之外调用,所以必须使方法非私有才能使其成为可testing的,这是错误的。

当代码改变时,你也必须改变testing。 随着重构,这可能是很多额外的工作。

编写像XML-feeds和数据库这样的“随机”数据的testing可能会很困难和耗时(不那么困难)。 最近我花了一些时间处理天气数据。 对于这个写作testing来说,这是相当混乱的,至less我没有太多的TDD经验。

让我补充一点,如果将BDD原则应用于TDD项目,则可以缓解这里列出的一些主要缺陷(混淆,误解等)。 如果你不熟悉BDD,你应该阅读Dan North的介绍。 他提出了这个概念,以回答在工作场所应用TDD时出现的一些问题。 丹的BDD介绍可以在这里find。

我只是提出这个build议,因为BDD解决了这些不利因素,并且作为一个缺口。 收集您的反馈意见时,您需要考虑这一点。

你必须确保你的testing总是最新的,当你开始忽略红灯的时候,testing变得毫无意义。

您还必须确保testing是全面的,或者是一个大错误出现的时刻,您终于确信让您花时间编写更多代码的闷闷不乐的pipe理types将会抱怨。

教我的团队敏捷开发的人不相信计划,你只写最小的要求。

他的座右铭是重构,重构,重构。 我开始明白,重构意味着“不提前计划”。

开发时间增加:每个方法都需要testing,如果你有一个大的应用程序依赖,你需要准备和清理你的数据进行testing。