TDD有多美?
InfoQ:请介绍你自己,以及TDD的实践经验。 熊节:ThoughtWorks公司总监咨询师,曾参与《重构:改善既有代码的设计(中文版)》、《J2EE核心模式(原书第2版)》、《Contributing to Eclipse中文版》等图书的翻译。目前正在从事Ruby on Rails的项目,并致力于敏捷方法与思想的推广。 鲍央舟:OutSofting的敏捷咨询师。在从事咨询工作之前,从事软件工程师的工作。接触、使用过一些TDD的实践,但是由于大环境的原因,没有深入使用。在从事咨询工作之后,和一些有经验的TDD高手做过Pair,也对TDD有了更深入的理解。 滕正宇:独立敏捷教练,InfoQ敏捷社区编辑,国内唯一的认证Scrum教练(Certified ScrumCoach)。从2005年接触到持续集成并开始实践,接下来开始接触并实践TDD以及Scrum等敏捷方法。 田乐:无限讯奇高级开发工程师,工作有7年,是一个前端后端都做的程序员。从07年开始使用TDD。 段念:Google中国高级测试经理,10来年软件开发与测试经验,主要工作方向在软件测试。在某些项目中实践过TDD,ATDD,在推动开发工程师的开发测试过程中对TDD有一些思考。 InfoQ:TDD跟Test是什么关系呢?TDD的T就是Unit Test吗? 熊节:可以是。也可以不是。关键在于,是不是都无所谓。我前两个星期就在干一个用Cucumber+Selenium直接写spec来驱动开发的项目,照样干得很清爽。 鲍央舟:TDD更是一种工作方式,编码观念,而Test是这种观念中的一部分实践。具体说来,TDD的观念是先明确下一步要做的一小样东西,然后恰到好处的实现要做的东西,最后审核所做的质量,以此循环。Test是明确下一步东西后的产出,对实现的正确引导,也是审核将来代码质量的一个工具。按术语来说,TDD的T确实是unit test。Unit test是跟代码质量,编码思路密切相关的。也有ATDD,BDD之类的,与代码的外部功能相关。 滕正宇:TDD跟测试的关系: 田乐:TDD是从Test开始的,驱动开发过程的动力是失败的测试,Test是驱动设计的工具。TDD肯定需要有Test,不过Test大部分的时候都不是为了TDD而写的。TDD的Test不是Unit Test,它可以是Acceptance test(ATDD)、Functional test等等。一般来说TDD可以穿透测试的几个水平分类。 段念:TDD并不是石头里蹦出来的孙悟空,DBC(Design By Contract)可以看作是TDD的前身。在DBC的观点里,设计应该以规约(Contract)的形势体现,规约定义了被开发对象的行为。延续这个观点到TDD,很容易就能理解,TDD中的T,在表现形式上是“测试”,但其实,它更应该被理解为“对被实现对象”的行为限定,也就是DBC中的规约。“测试”只是用来体现规约的形式。 InfoQ:你认为实施TDD需要怎样的前提条件?TDD难在哪儿? 熊节:要使用一种设计方法,你就必须(1)会做设计;(2)做设计。它难在有些项目不做设计,有些人不会做设计。 鲍央舟:实施TDD的前提是对TDD实践背后的观念有所理解,也需要有经验者的指导。TDD难在习惯和观念的转变。以前的工作方式已经在大脑和肌肉中固定下来,无法短期更改。另外,在短期可能呈现开发速度更慢的现象,需要管理层也对TDD以及质量有所理解,才能给予正确的支持。 滕正宇:前提条件很简单,就是了解这种工作方式(可以通过读书,可以通过跟教练一起结对等),然后去坚持。 田乐:前提条件就是需求明确,知道需求的边界,了解如何可以验收。另一方面TDD要经过一些练习。我觉得TDD的一个难点就是把它当作一个推动设计的工具,而不是停留在保证质量(如检查边界条件)这个层面。另外,由于TDD一般是从最外面的抽象开始的,所以我个人觉得TDD最开始的抽象模型选择也是一个难点。 段念:实施TDD是对开发者行为的比较大的改变,在我的经历中,遇到的主要难点应该是改变既有的开发工程师的开发习惯吧。TDD技术本身没有什么特别的要求,任何组织都可以直接应用。 InfoQ:TDD之于需求、设计、代码质量是怎样的关系和影响? 鲍央舟:对于需求来说,TDD更能引导开发人员做出真正符合需求的东西,不会过渡开发。对于设计来说,TDD的实践能帮你清理思路,但不能教会你做好的设计。对于质量来说,TDD保证所有的代码都有测试覆盖,肯定能提高质量。 滕正宇:需求方面根据2002年Standish Group的报告,我们软件系统中有65%的功能是客户从来不用或者很少用到的。传统意义上大家认为敏捷开发应该让我们的团队开发得更快,生产率更高,这其实是很大的误解。与提高效率相比,使用Scrum,TDD能够帮我们从整个需求中确定真正有用的那35%,而且往往这35%的功能往往实现起来并不是那么困难。因为做得少,所以做得更快。 田乐:TDD会让你减少无用功,因为它迫使你从需求验收的角度入手,你必须在进入细节之前找到这个需求的边界,找到那些验收条件。TDD会锻炼自顶向下的的抽象分解能力,这对仅习惯从细节入手的程序员来说很有帮助。TDD可以提高你的代码的可测试性,它的节奏还可以帮助你做到简单设计。还有大家常说的,TDD有助于提高代码的内部质量。 段念:ATDD可以向上直接追朔到需求,使用ATDD方式,可以避免功能镀金,这是TDD技术带来的一个大的好处。在设计方面,TDD并不追求在最开始的时候得到一个完备的设计,而是遵循“够用的设计”的原则,保证开发者可以在短时间内得到可用的设计与实现。“够用的设计”是一个在敏捷环境下非常有效的原则,当然,也有些人反对这个原则,认为随意的设计无法随着应用的复杂性增加则很好的适应。在我看来,由于需求本身的不确定性,很难期望在一开始的时候就能给出保证能满足将来需求的设计,既然这样,不如遵循“够用的设计”的原则,通过重构等方式不断修正和优化设计。TDD对代码质量本身没有明确的关注,但如果开发者自觉地不断应用重构技术消除代码中的bad smell,在组织级别设计强制的code review,以及对单元测试覆盖率给出明确要求,则可以在很大程度上让代码质量保持在高水平上。 InfoQ: 你认为实施TDD容易犯的错误是什么?TDD的不足在哪些方面? 熊节:错误?陈皓同学已经向我们展示了。当你使用一把锤子时,你能犯的最大的错误就是尝试用它把钉子撬出来而不是砸进去。 鲍央舟:过度编码!写完测试后,代码不止使新测试通过,还实现了很多别的东西。不足只是真正掌握比较难而已。 滕正宇:容易犯的错误: 田乐:我觉得TDD最容易出现的就是节奏问题,由于有的时候coding的非常尽兴,就没有遵循红绿红绿小步前进(baby step)的节奏,而是在没有失败的测试的时候就洋洋洒洒写下去。那样的做法其实就不完全是TDD了。TDD的不足是它不是万能的,不应该是强制的。不是所有的任务都需要TDD,那些临时的可抛弃的代码(如技术可行性试验)不需要TDD。强制的TDD和强制的单元测试一样,因为设计优略不容易量化,TDD也不能用TestCase的数量去量化,没法量化的实践不应该是强制的,否则会流于形式。TDD无法量化也是它被大规模推广的时候的一个不足。 段念:把TDD等同于单元测试,认为TDD只是“提前写单元测试”这种想法应该是很多不太了解TDD的人容易犯的错误吧。如果把TDD放到敏捷开发的大背景下,我倒不觉得TDD有什么明显的不足,但如果单独考量TDD在企业中的实践,TDD技术本身不关注代码的质量应该是一个明显的问题。应用TDD的企业通常需要采用持续的Code Review和Refactory方法保证通过TDD产生的代码的质量。 InfoQ:一般开发者需要多久能掌握TDD呢?请向读者推荐一下TDD的学习资料吧。 熊节:到他们掌握该怎么做设计时──which never happens to most people,请参阅《程序员的思维修炼》。 至于学习资料么,问豆瓣都比问我好。这事情也很悖论:能学会的人,读这些文字的价值约等于0,因为他只需要豆瓣搜索1分钟+阅读1小时──这是他anyway会做的事──就能得到同样的信息;读了这些文字觉得很有用的人,有鉴于Kent Beck那本书出版已经7年了,基本上,他已经没希望了。 鲍央舟:半年!网上一搜可以一大把资料,不过我觉得TDD光看是没用的,一定要和有经验的人pair! 滕正宇:多久才能掌握TDD呢?这不是一个“敏捷”的问题,因为每个人的学习能力,和对学习的投入程度是不一样的,因此学习的“速度”也不一样,因此很难说需要多场时间。在这里我采用敏捷计划与估计的做法,我们先确定一下范围,然后每个读者根据自己的学习速度,自然就可以算出需要多场时间。 田乐:不知道多久可以掌握。学习资料的话Kent Beck的TDD就很好,还有我觉得TDD很适合与设计的方法论一起看,如领域模型驱动设计等(《测试驱动的面向对象软件开发》就结合了这两个知识)。 段念:我们组织中有一些用于帮助开发工程师熟悉TDD的program,根据我的了解,一般的开发工程师可以在1-2周内掌握TDD工作方式,但一般需要更长时间来达到对TDD的熟练掌握和灵活应用。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |