【编者按】时至今日,作为敏捷开发核心实践之一的TDD(测试驱动开发),对大多数软件从业者来说应该已经不是什么新鲜事物了。即便你再孤陋寡闻,面对各大技术媒体、论坛和出版商的轮番轰炸,要想完全不知道,恐怕也非易事。若情况真是如此,请将你的经验共享出来,好让我也学习一下,自动屏蔽那些令人厌烦的信息。好了,玩笑话就说到这里,现在还是回到本系列的正题:书评,本篇的主角就是这本《测试驱动开发的艺术》。
\严格的讲,这是一本面向Java开发者的 TDD书籍,书中的大量示例以及言及的工具无一例外都是针对Java领域的,而且主要针对的是企业开发领域。虽然我相信使用其他工具和处于其他领域的开发者同样也能从中受益,但相关的工具和信息就只能靠自己去寻找和摸索了。若是你所在的公司主营业务并非是企业开发,需要自己领悟和转化的内容就更多,而且对于阅读者本身的要求也相应的会提高。话虽如此,但正因为它把读者群限定为一个特定的范围,反而更凸显了其自身的价值,加之如今Java开发者人数众多,其影响力也自然是水涨船高。
\本书对于那些有意了解和采纳TDD的Java开发者,尤其是企业开发者,无疑相当于一本福音书。为什么这样讲?我在这里列出了三个理由,对不对可以由你自己判断:
\- TDD绝非是掌握使用JUnit编写单元测试这么简单。相信很多读者都读过一些介绍TDD的材料,而且对于JUnit也都有一定的基础,可到了真正要完全从测试开始写出一个完整应用来的时候,总觉得束手束脚,不得要领。甚至可能会觉得以前读过的书都白读了,挫败感是此时唯一的感受。本书的第2、 3章就是这时你最需要的指导!这两章的内容是我看过的最具价值的介绍如何采用TDD的素材,而且相比起来也是最真实的内容。\
- 如果说第一部分是在广度上对TDD进行了介绍的话,那第二部分则是对于TDD的深度历险。短短四章内容,你可以了解如何使用TDD开发典型的功能组件:\
- 第5章:Web开发,重点谈到了MVC中的V和C的TDD。\
- 第6章:数据访问,涉及JDBC/Hibernate,同时也谈到了集成测试。\
- 第7章:时间和多线程。\
- 第8章:Swing。\
也许你在其他地方多少还能看到第5、6和8章的内容,但专门讨论如何对难以预测的行为进行TDD的内容就并不多见了。个人认为第7章可以算得上是本书的一个亮点。
\- ATDD是本书最后一部分内容的主角,在这一部分,你可以真正看到采用敏捷方法开发项目的全貌。当然,工具介绍是避免不了的。但让我觉得更有价值的是对于相关策略的介绍,不论是执行ATDD的策略,还是推广TDD的策略。\
本书适合各种层次的读者,内容的3个部分大致可以粗略的对应低、中、高三个层次的读者;书中介绍的大量工具更是节省了自己去寻找的时间和麻烦;至于书中穿插的作者自己的经验之谈,恐怕就只有靠读者自己在实践中去体会和领悟了。
\让我想想,是否还漏掉了什么?哦,对了,翻译。作为一本引进书籍,自然不能不谈其翻译的质量。正如你不想为一本劣质的翻译作品掏冤枉钱一样,我也不想为一本翻译得磕巴,说的话不像中文的书籍进行评论!一言以蔽之:翻译质量过硬。对于一本能让我从头一气读到尾的翻译作品,实在不用再多说些什么了!
\如果你的目标是要提高TDD的技能,学习别人的经验,那这本书就是你必读的书籍,我在这里假定你是一名Java开发者,主要从事企业开发。书中众多的知识点对于初涉Java领域的开发者来说,确实是设置了不低的门槛,可这并非就说明初学者不能从中获益。在此,我建议精读第一部分,对于其余部分略读即可。在实践过程中,采用书中介绍的TDD方式学习新知识,在接到相应的任务时,再去细读相关部分。就国内公司的现状,我相信你很快就会用到第二部分乃至第三部分的知识。
\——InfoQ中文站SOA社区编辑 胡键
\读罢《测试驱动开发的艺术》,忽然想起中国传统文化中的“道器之辩”。《易经》曰:形而上者谓之道,形而下者谓之器。中国的传统文化常常是重道轻器,认为道本器末,即道是根本,其他一切是道的外在表现,器是道的从生与从属。这就导致我们常常喜欢把“道”与“器”割裂开来,一味地重视过度抽象的“道”,进而形成一种形而上学的玄幻,使得“道”高高在上,未能落于实处。重道轻器给传统文化带来的缺失告诉我们,“道”与“器”应该是统一的,道是本质,却又必须依赖于器,受制于器。
\从软件开发的角度来看,TDD的本质思想即为“道”,这其中包括按照意图编程的思想,提高可测试性的设计原则,以及测试的模式与面向对象的基本思想。而“器”则包含对TDD的合理运用,针对不同的用例场景做出的测试手法,以及对测试工具的使用。
\本书第一部分《TDD入门》阐述的正是TDD之道。虽然是入门知识,却高屋建瓴地阐明了TDD的真谛。例如本书写道:
\在TDD周期中的第一步中,我们会写测试,实际上这并不只是写测试而已,而是在做设计。我们是在设计API,即用来访问新功能的接口。编码之前写测试,我们会自然地考虑新代码的调用方式。……测试先行的编码方式会促使我们站在代码用户(开发人员)的角度考虑,设计出更易用的 API。\
很多开发人员并不愿意接受TDD的开发方式,认为这种先写测试后编码的方式既别扭而又浪费时间,原因就在于他们没有真正体会这种测试驱动设计的好处。TDD最重要的一个字眼儿就是drive(驱动),事实上,这种驱动力正是所谓“按照意图编程”的重要思想。
\意图编程,顾名思义,就是说写代码时先假设其他部分代码都已经存在了(即使事实并非如此)。使用这种编程方法时,我们可以把注意力集中在能有的,而不是已经有的东西上。使用意图编程,我们能让代码读起来更流畅,容易理解和使用,也能使代码清晰地表达出自己的本意,而不会过于强调实现细节。\
个人认为,本书第一部分给出的邮件模板子系统的范例更贴近开发真实,却又不至于晦涩难懂。作者在选择范例上的匠心独运,使得本书既具有很强的实践指导意义,又不至于陷入复杂的业务需求和技术细节中。范例给出的第一个测试、伪实现以及重构的手法,都是自然而然的TDD过程,而不是为了写作本书生拉硬拽,东拼西凑,有着强烈地雕琢痕迹。若能在阅读过程中,比照着这样的过程动手实验,相信能够获得更大的提高。
\从本书的第二部分开始,就迈入了TDD“器”的部分。之所以说是TDD之“器”,在于它介绍了针对特定技术应用TDD的内容,这其中包括对Web组件、数据访问、多线程、Swing代码的测试驱动开发。在讲解的过程中,作者还介绍了大量用于这些特定技术应用TDD的工具或框架,例如JspTest、 EasyMock、MockObjects、HSQLDB、Jemmy、Abbot等。这些都是Java平台下常用的支持TDD的有力工具。本书的第三部分则着重介绍了ATDD(验收测试驱动开发),包括对用户故事的介绍,验收测试的特征与实现,ATDD的过程以及相关工具Fit。这在许多介绍TDD的书籍中都是不多见的内容。
\这两部分内容给出了许多贴近开发真实的例子,提出了许多卓有成效的测试方法。这些内容如此地实用,涵盖的知识如此地全面,基本上可以解决我们在企业开发中进行TDD可能遇到的问题。事实上,这些内容大多数都可以说是TDD实践过程中的拦路虎,尤其是针对表现层和多线程技术的TDD方法,大多数开发人员都缺乏这方面的知识,甚至因为这样而放弃TDD。本书极具实践指导意义的阐述弥补了这一空白。遗憾的是,本书介绍的内容主要针对Java开发人员,因而提及的工具也都基于Java平台,对于其他平台下的开发人员而言,无疑削弱了几分价值。
\本书还有一点不足就是“道”与“器”的不统一。前面提到,本书的第一部分开篇名义,用极简洁的语言道明了TDD的本质。然而本书的第二部分与第三部分,几乎只停留在TDD方法和工具的使用上,而忽略了测试对于设计的驱动力。书中的例子仅仅给出了如何完成测试用例,如果建立Mock对象,却不再介绍为何要这样编写测试用例,驱动我们进行设计的意图何在。换言之,后面的例子省略了驱动对设计进行推导的过程。这种驱动设计的能力恰好是很多程序员所不具备的。 “器”固然重要,但它必须遵循“道”的要义,在其指引下实施。本书内容“道”与“器”兼顾,却将二者割裂开来,未能形成统一的整体,不能不说白璧微暇,略有遗憾。
\——InfoQ中文站架构社区编辑 张逸