昨天晚上看了CoolShell陈皓同学对TDD的描述《TDD并不是看上去的那么美》和InfoQ上的虚拟座谈会《TDD有多美》,以及陈皓同学写的《再谈敏捷和ThoughtWorks中国咨询师》。陈皓同学首先用自己的实战经验例举了TDD的各种使用缺陷,从而来描述了TDD并不是看上去的那么美。接着InfoQ举行了一个虚拟座谈会,邀请了ThoughtWorks的熊节同学和其他几位同学,来描述什么是TDD,TDD实施的难点,TDD的“美”以及我们多久才能这么“美”。最后,陈皓同学又在《TDD有多美》之后写了一篇文章《再谈敏捷和ThoughtWorks中国咨询师》,在这里谈了一下自己针对敏捷的观点和对于ThoughtWorks咨询师的批评观点。这些文章挺有意思,在这里我根据自己的经验并在综合各位大师的基础上谈一下对TDD的看法。
首先,我并不追求敏捷,我只追求“1 如果采用正确的方法来寻求我做的事情是正确的; 2 如果采用正确的方法来确保正确的实现这件认为是正确的事情”。这也是我座右铭“道法自然”所提倡的,即寻找正确的规律。不过,这个完美的座右铭,实施起来却相当的困难,因为我永远也无法下定一个绝对的结论,对自己说我这样做绝对正确。引用我在Sybase的Manager的话,就是“有些事情,等你死的那天你都无法明白是对还是错”。所以,对于敏捷和TDD,我并没有去刻意的追求什么,崇拜什么,但我想正确的来设计我的产品,正确的实现我的产品,这是最关键的。我追求的方法论,就是“合适的方法”的方法论。
其次,对于TDD,我认同陈皓同学的很多观点,也认同ThoughtWorks的熊节的很多观点,在这里我引用熊节的一句话来说明TDD,并在后面的篇幅根据我自身的经验来谈一谈我为什么这样想的。引用TW熊节观点并不是为了捧TW,虽然我对TW非常有好感,在这里,我更想来探究我们该怎样使用正确的方法来做正确的事情。
“熊节:……TDD的前提是要使用一种设计方法,你就必须(1)会做设计;(2)做设计。它难在有些项目不做设计,有些人不会做设计。……”“熊节:……关键在于,TDD的T,是什么测试都无所谓。它就是设计。……”
我个人认为,TDD的精髓在于提倡所谓的“设计驱动开发”,即我们必须先清楚我们要干什么,然后我们需要用Code写下来最终提供给用户的使用方法(即TestCase)。随着产品研发/项目的推进,我们需要根据自身的认知来迭代的更新给用户提供的功能,即TestCase,然后更新我们的代码并进行适当的重构。以我的个人经验,我非常的认同这样的方法学。
我先简单描述一下我过去的经历:不到30岁,经验显然是不足的;2000年上本科,2004年上研究生,2007年进入Sybase工作,后来辞职创办西安尤埃信息技术有限公司。我的软件开发始于2003年,在本科期间的后2年,给学校/单位/个人开发了6个项目,自己也做一些类似党员管理/成绩管理的实验品,这阶段,做的最好的项目就是基于微软Exchange Server 2003开发的工作流审批系统了。从2004年到2007年上研期间,做的项目有十几个,上十万的项目有3个,身兼数职。为了满足项目中无休止的需求变更,我自己设计了控件关系映射组件、通用窗体框架组件(满足团队并行开发协作的模块化框架原型)、对象映射组件等通用组件,并在毕业时将自己的成果写成一篇《企业MIS体系结构研究及应用》的论文,里面用自己设计的框架和组件来支撑个人设计的软件体系结构。在这一阶段,我对自己说的就是,我受够了需求不确定性/无休止变更给我们带来的痛苦,于是我从此思索该如何降低这样的痛苦与折磨,并开发了OSGi.NET产品——尤埃开放服务平台(UIOSP)。
研究生毕业后,我加入了Sybase,在Sybase工作过程中,我工作性质最大的变化就是,在这里,我做的是一个产品。产品的首要条件就是设计,设计的内容就是我们非常强调的《××××功能规范》。当时,我们团队有一条铁律,凡是对某个Bug的修复/对某个功能的改进/添加了新的功能,如果这些功能会改变/影响用户的使用习惯,那么,我们就必须严格写下功能规范。在功能规范里面,我们必须清楚的描述我们到底要提供什么功能,这些功能让用户如何使用,描述内容甚至要精细到每一个文本框允许用户输入多少文字,如果输入不正确或者文字超过了规定,该给用户什么样的提示。然后,我们团队里的人会对功能规范进行Review,当团队Review差不多了,我们的Manager会邀请其它相关Team的人和QA的人来一起做Review,当这个功能规范通过所有的Review后,QA会给我们发送一份TestPlan,寻求我们对测试规范的意见。我们所做的所有的事情,目标只有一个,就是给用户提供易用性很强的产品。经过上面的过程,产品最终还要经过一个Section 508的测试,这份测试是针对残障人士使用我们产品的易用性测试,估计很多人如果是第一次看到的话,可能都会说“天啊!”。没错,我当时就是那种感觉。功能规范设计评审仅是软件产品设计的一个小小的环节,我们还需要构建完善的质量保证体系,包括缺陷跟踪/持续集成等等,使用各种手段来保证我们做的事情是正确的且我们能够正确的实施。可以这么说,这里所采取的各种复杂的措施、手段和策略都是为了降低我们在软件开发/交付/持续改进的过程中所受的痛苦与折磨,从而保证正确性。
后来,我从Sybase辞职,创办了一家小公司,主要做OSGi.NET产品和SaaS应用商店开放平台产品。因为当初创业设定的目标是以产品为目标。从自己的工作中以及从微软的《Framework Design Guideline》我学到了很多的东西。在产品实施中,我必须确保能够正确的开发一个让用户喜欢的产品,并且能够在后续的更新升级中保持一个较为平滑的渐进过程。在这里,我所处的角色比较复杂,首先是公司的创始人,其次我是产品的设计师,我还要负责产品架构并为产品构建一个质量保证体系。通俗的讲,我需要来采取各种手段来保证产品的正确性。因此,我非常注重产品的功能设计和质量保证。功能设计主要面向用户,它包括:1 概念设计,通过在白板上描绘出我们要给用户带来什么,然后做一个讨论。 2 功能设计,用文档来描述我到底要给用户提供什么样的功能,用户怎么来使用这些功能的,这样的设计文档可能是功能规范也可能是用户场景设计规范。用户场景规范是源自于微软《Framework Design Guideline》中描述的一种针对微软.NET类库所有API的设计方法,而功能规范更倾向于类似于通过UI来体现的交互性功能。对于OSGi.NET产品,我们的用户场景设计规范多于功能规范。产品实施的其它的环节我在这里不描述了,你可以查看《[产品开发经验总结] 软件产品背后的冰山一角》这一文章来了解更多的环节。下面我们就来看一下其中关于《ShortCut功能》的场景设计。在这里,我们为用户设计了各种使用场景,这些场景的设计遵循2/8原则,从简单到复杂来设计。
你有没有发现上面的用户场景就像TDD里面所说的“TestCase”呢?没错,这是一致的,当用户场景设计经过讨论定稿后,它其实就是一个测试用例了。我们以用户为中心,来驱动整个软件的开发,首先要做的就是设计好我们到底要给用户提供什么样的功能和怎样来提供。这些经过讨论的文档也就自然而然的变成了TDD中的“T”。这样的TDD,其好处就不言而喻了,那就是一旦我们把目标设计好之后,即有了“T”作为保障,那么我们的软件产品一定程度上就能够保证软件的实现与软件的设计上的一致性,并能够保留我们的设计现场和讨论现场,这估计也是为什么TDD提倡不需要文档的原因了。因此,我赞同熊节观点“TDD的前提是:首先要学会设计,其次要会做设计”。没有设计的话,“T”就不知道该从何而来了。
这么说来,TDD应该是美的了?没错,TDD确实美,而且是完美的美。问题来了,有多少产品/项目/人真正能够做到像Sybase那样的设计呢?有多少的程序员能够掌握这种“设计”呢?个人认为这正是为什么“TDD用起来不太美”的根源。因为这东西的初衷看起来太完美了,当你想在不完美的现实来实现完美的目标,最终的结果就是这玩意太不美了。陈皓同学也谈了TDD的各种缺陷了。这里我也谈一下我的。
从上述的言语中,你可能认为我们就应该是TDD的完美实现者了,NO!我们并没有细到为所有的实现都做这样的设计,就连Sybase也是仅对给用户提供的那部分做完美设计而已,何况我们还仅是创业的小团队而已。我们所采取的TDD,确切的讲,应该是BDD,即行为驱动开发。BDD描述的开发方法是以用户场景来驱动的,它能够更准确的来描绘我们的整个软件系统要实现的功能,更能够准确的保持设计与实现的一致性。我们为BDD还搭配了持续集成,即确保软件产品在持续更新改进的过程中,不会对提供给用户的功能产生破坏,一旦某一个Bug的代码Checkin,持续集成系统将自动构建所有的程序、跑完所有的测试并可根据需要生成产品的安装包,这样,我可以不同太担心产品的这部分核心功能遭到破坏。
最后,我来总结一下我个人的观点:1 TDD重在有设计,我非常喜欢这种理念; 2 TDD很完美不过实施困难,但不是没有价值或者忽悠,对于我们而言,在于吸取其中的理念并适当应用。不过,说真的,这比TDD的理论要更难了,需要你根据需要去探索一条适合自己“国情”的路子,特别是当我们面对的情况还处在“发展中且一百年不动摇”的阶段!
本文转自道法自然博客园博客,原文链接:http://www.cnblogs.com/baihmpgy/archive/2011/08/27/2155493.html,如需转载请自行联系原作者