敏捷软件开发基础:进行有效的客户协作

敏捷软件开发基础:进行有效的客户协作

developerWorks
文档选项

最新推荐

Java 应用开发源动力 - 下载免费软件,快速启动开发


孙鸣 , 软件工程师

2006 年 1 月 24 日

在上篇文章(《敏捷软件开发基础:持续集成环境的搭建》)中,我们讲述了如何在团队开发中搭建起一个持续集成的环境,从而为有效地实施敏捷开发实践打下基础。其中所提到的工具和方法都是针对开发团队内部开发环境的搭建的。但是,仅仅有了一个持续集成环境还不足以开发出优秀的软件。毕竟,软件开发出来是要为客户提供价值的,要想开发出真正满足客户要求、使客户满意的软件,开发团队和客户之间的有效协作和沟通是必须的。本文就试图关注于这一方面的内容,就如何高效地进行客户协作以及这种有效协作对软件开发的重要影响展开论述。

首先,我们将简单介绍达成和客户高效协作所需要的一个核心工具FIT(Framework for Integrated Test)。FIT是集成测试框架的简称,从字面意义上来看,它应该是一个测试工具。是的,使用FIT我们可以编写出可以自动运行的集成测试用例,可以用来确认我们所开发出来的软件是否满足了用户所需的功能,可以作为持续构建过程的一部分来确保所构建出来的版本是正确的。但是,FIT还有另外一个更为重要的功能,那就是在软件开发中增强协作,尤其是开发团队和客户、领域专家之间的协作。这种协作可以有效地降低软件开发中的不必要的复杂性,加速反馈,并确保最大程度地为客户提供最高的价值。

在下面的章节中,我们首先简单介绍一下FIT这个工具,然后就如何基于FIT进行有效的客户协同开发,以及这种协同工作对软件开发的重要影响进行详细的论述。

FIT简介

简单来讲,FIT就是一个软件(可从参考文献1中给出地址下载),它能够读取HTML文件中的表格(这些表格可以通过MicroSoft Word或者Excel产生)。针对每个表格,都会由一个程序员编写的"fixture"来解释。该fixture会驱动实际的产品软件来对表格中给出的测试用例进行检验。下面是一个这样的表格示例,如表1所示:


表1:一个简单的FIT table 示例
表1:一个简单的FIT table 示例

表1是针对一个商场的购物打折规则的测试用例描述。该规则可以简单描述为:当一个顾客的消费金额超过1000.00 时(不含1000.00),将享受5%的折扣。FIT会自动地使用该表格中的数据和所开发的软件进行交互,并检查软件返回的结果是否和表格中所给出的期望值一致。如果一致,则在相应的单元格中涂上绿色,否则涂上红色(这一点和常用的Junit一致)。FIT运行结束所报告的结果如下:


表2:FIT针对表1报告的结果
表2:FIT针对表1报告的结果

不错,全部通过了:)那么这一切是如何发生的呢?接下来我们简单的对FIT的工作原理做个介绍。

为了能够更加易于使用,FIT在表格描述和Fixture实现上做了一些约定,比如:表的第一行中的内容对应Fixture实现的类名(本例中为CalculateDiscount),表的第2行中的内容对应于要触发的Fixture类中的实例变量和要调用并验证其结果的方法(本例中为amount以及discount()方法)。FIT会根据表格中的内容,找到相应的Fixture类,实例化出Fixture对象实例,根据表格中提供的内容设置相应的实例变量的值,然后调用表格中给出的方法,并就方法的返回值和表格中提供的值进行对比,然后报告结果。

FIT帮我们完成了大部分的工作,我们要做的就是继承合适的Fixture类,并提供对应于表格的实例变量和方法。对于表格1来说,我们要实现的Fixture的主要代码片断如下:




其中Discount类是我们要开发的应用类,FIT会自动调用CalculateDiscount的discount()方法,该方法又调用了Discount的getDiscount方法(该方法实现了打折的业务规则),然后FIT把返回结果和表格中的对应值进行比较,并通过颜色进行结果报告。如果失败,还会把期望值和实际值列出来。

FitTable、Fixture以及要测试的系统之间的关系可以用下图进行描述:


图1:FitTable、Fixture和要测试系统的关系图
图1:FitTable、Fixture和要测试系统的关系图

其中,Fixture充当Fit表格和要测试系统间的媒介,起协调作用,完成表格中给出的测试。FIT中提供了好几种类型的Fixture,它们分别用于处理不同的情形,这不是本文的重点,就不详细描述了。感兴趣的读者可以从参考文献中获取更多的相关内容。

看了上面的介绍,读者朋友可能会认为除了测试用例的描述方式不同之外,FIT不过是和Junit类似一个测试工具而已。确实,对于FIT这个工具来说的确可以仅仅把它当作一个方便的面向客户的测试工具(就像把JUnit作为一个面向开发人员测试工具一样)。但是正如我们在使用Junit时,要把它看成是一个分析、设计工具才能最有效地发挥其作用一样,我们只有把FIT看成是一个和客户、领域专家间的沟通、协作工具,才能最有效地发挥其作用。

在下面的章节中,我们将探讨一下和客户、领域专家间进行有效沟通需要哪些条件,以及FIT是如何满足这些条件的。记住,FIT是一个协作、沟通工具,所产生的测试用例只是沟通、协作的一个附属产品(当然,这个附属产品提供了巨大的好处)。





回页首


和客户进行有效协作所需的条件

我们所开发出来的软件是要为客户所用的,因此就必须要满足客户的需求,并被客户所理解。要想开发出这样的软件,我们就必须也要充分了解问题领域,并理解隐藏在需求背后的客户的真正意图。遗憾的是,软件开发领域和实际要解决的问题领域之间存在着一条巨大的断层:我们所使用的开发语言客户并不熟悉和了解,而客户所描绘的领域概念和规则也无法清晰、直接映射到我们的设计中。这样,就存在许多的翻译和转换过程,为协作的有效性带来了诸多障碍。因此,解决这个问题的根本之道就是要填平这个断层,平滑问题领域和解决方案领域间的间隙。要达成成这个目的,需要一些条件。

面向客户的需求描述

第一个条件就是:要提供一种方法,可以让客户非常容易地参与到需求的探讨和描述之中。客户对于软件的观点对于开发软件的团队来说是非常有价值的。要想充分理解客户所表达的内容,无障碍的沟通和协作是必须的。因此,我们必须得提供一种方法使得客户可以容易地把自己的观点清晰、准确、方便地表述出来。FIT正好解决了这个问题。

客户在参与到需求的探讨中,进行需求描述时,不需要使用对他们来说不熟悉的编程语言(包括一些高级脚本),而是使用一些常用的文档(比如:Word或者Excel)。在其中根据FIT的一些规则(非常简单、直观,甚至可以先不按照FIT的规则来写,而由开发人员完成这项工作)创建一些面向问题领域的表格,存为HTML格式即可。每当一个新的特新需要添加时,客户就可以把整个团队招集起来,对该特性进行描述,然后通过FIT表格的形式把一些example写出来。这里所写出的example就是我们通常所说的规格说明。以这种方式描述的规格说明即面向客户,又能够得到执行和验证。

统一的交流语言

面向客户的描述是和客户进行有效沟通的基础,但是要想在此基础上取得进一步的成效,就必须要具有一个统一的交流语言。这样,开发团队在和领域专家探讨业务规则和特性时就不会有语言隔阂,领域专家就可以深入到软件开发的活动中,及时发现理解和设计中的错误。而开发团队也可以清晰、直接的理解领域专家对特性或者业务规则的理解,从而设计出简单的系统来。

FIT作为一种工具本身没有提供适合所有领域的统一交流语言,但是FIT却能非常有效地促成这样一种语言的产生。FIT非常鼓励客户在描述特性的example时,把重点放在领域上面,着重描述领域规则,着重于领域概念。这样,开发团队就可以在这些领域概念和规则的驱动下去进行设计和开发,使用领域中的词汇来构造程序元素。从而可以有效地解决由于领域元素和实现元素间的断层所带来的诸多问题。

快速提供反馈

沟通和协作不是简单的瀑布式过程,有效的沟通和协作需要一个快速反馈机制,就达成的一些沟通结果进行验证,然后提供出反馈并作为进一步沟通和协作的基础。缺少了快速反馈的沟通和协作,其有效性会大打折扣,甚至会走入错误的方向。如果有了快速的反馈,就可以进一步了解到客户对于每个特性或者业务规则的理解和认识,从而开发出更好的软件。

FIT可以说就是一个快速提供反馈的工具,领域专家描述完特性或者业务规则并转换为Fit表格后,开发团队就可以迅速实现出该功能,并运行起来把结果呈现给客户。在反映出客户和开发团队之间对于同一个问题的理解是否一致方面,没有什么能比一个可以工作的软件所提供的反馈更有效的了。基于这个真实反馈,客户和开发团队之间可以进行进一步的沟通,在挖掘更深层次的业务规则方面取得进展。从这一层意义上来讲,FIT应该是"example-driven-requirements".

开发状况的可视性

开发软件的目的是为了尽快、尽可能地为客户提供最大的商业价值。要想达到这个目的,客户就必须要能够容易、准确地了解到开发的总体情况,只有这样才能在突发状况发生时做出最有利的决策。同时,只有整个开发过程做到可视化,开发团队和客户在面对变化时才能做到有的放矢的沟通和协作。

从了解开发的总体情况的角度来说,没有什么能比一幅幅具有清晰描述并可以运行验证的特性表格更准确的了。持续集成所提供的集成测试结果HTML页面上的颜色标示清晰、准确地反映出了目前项目的开发状况。





回页首


有效协作对软件开发的重要影响

在上一小节中,我们讲述了客户和开发团队间的有效沟通、协作所需要的几个基本条件以及FIT是如何满足这些条件的。本小节,我们将关注一下这种有效的沟通和协作对软件开发带来的几方面重要影响。

促成更具价值的软件

前面也提到过,软件的价值在于为客户提供的价值。因此,我们在软件开发中不能同等地看待所有需求特性,而是要有一个优先级别列表。这个特性优先级别列表基本上是由客户根据其为自己提供价值的大小排定的。尽早交付最有价值的特性给客户,才能真正体现出软件的价值。如果缺少有效地沟通和协作,那么就会造成客户急需的软件特性迟迟无法提供,而把精力和资源都花费在了那些价值很低的特性上(很可能这些特性价值虽低,实现起来却很复杂)。

例如,客户需要10个特性,开发团队开始开发工作。突然,客户提出在下周有一个展览会,需要展示其中的3个重要特性。如果缺乏有效的协作和沟通,很可能这3个最具商业价值的特性更本还没有开始开发,要在短短的几天内开发出来基本上不可能。相反,如果开发团队和客户之间一致保持有效的沟通和协作,那么开发团队在一开始就会首先关注于这3个最具商业价值的特性,并通过快速迭代和反馈使它们真正满足客户的要求,这样的软件才更具有价值。

促成更简单的设计

开发软件是有代价的,正好能够满足客户真正需求的设计才是最经济、简单的设计。请注意,我上一句话中的"真正"这个词。因为,在很多情况下,由于缺乏有效的沟通和协作,所进行的设计都是在没有充分了解需求背后客户的意图的基础上进行的,难免会具有很多不必要的复杂性,增加开发的难度和成本。

James Shore在这方面有一个很好的例子,是这样的:一个客户希望烤面包机能够具有在面包烤熟会自动把面包弹出来的功能。开发者说这个需求实现起来非常的昂贵。客户就问为什么。开发者说,把面包弹出来很简单,只需要一根弹簧,但是要探测面包是否烤熟了却比较麻烦。我们需要一个光传感器以及可以对一些定制的褐色进行探测的软件。此时,客户问,那么市场上销售的那些具有此项功能的烤面包机是如何知道面包烤熟了呢?开发者说,它们使用了定时器,并不能够真正探测出面包是否烤熟了。客户说,这样就行了,我们需要的就是这种常规的烤面包机。

试想,如果缺少有效的沟通,不知道要做出一个多复杂的烤面包机来呢。

促成更加易于演化的设计

在达成有效协作所需要的条件中,我们提到了统一的交流语言,也就是面向领域,以领域规则和概念为核心的语言。如果以这个语言驱动来进行我们的软件设计,所有的设计考虑、命名、要素都以这个领域语言中的名称、要素概念为依据,那么我们所得出来的就是Eric Evans(Domain-Driven Design一书的作者)所说的"Ubiquitous Language" (参见参考文献3)。我们所创建的类型将是具有丰富领域语义的"Whole Value"(参见参考文献2),而不是简单的编程语言中的基本类型。

比如,在表格1中给出的示例中,领域专家更可能会写出900.00RMB这样的内容,而不是简单的900.00。这就会驱动我们创建一个Currency这样的类型,而不是简单的一个double。这样,我们在设计时就是使用这些具有完整领域语义的类型,从而避免一些由于概念不完整而在软件的演化过程中所造成的问题。

此外,面向领域的设计具有更好的适应性和应对变化的能力,因为问题领域中的一个小变化可以很好地映射到解决方案领域中的一个局部更改。并且,新功能的增加往往就是现有功能的自然延伸。

促成更好的规格说明

一般认为的规格说明就是以文本文档的形式呈现的功能需求描述,这样的描述往往会造成理解上的错误,并且很难验证和演化。这样的规格说明在项目开发过程中会逐渐失去其应有的价值,甚至还会为其他参考的人带来误导,因为很可能其中所描述的一些特性在项目的开发过程中已经做了修改而文档却没有同步更改。

而在有效的沟通和协作基础上形成以FIT表格方式呈现的规格说明则完全没有这方面的问题。因为以这种方式描述的规格说明是可以运行和验证的,并且是在具真实的反馈基础上形成的。此外,由于业务规则的描述是通过example的方式给出的,所以非常易于被他人理解。相比之下,这样的规格说明更好一些。





回页首


总结

在本文中,我们讲述了客户协作在敏捷软件开发中的重要性,以及达成有效的用户协作所需要的一些条件。并简述了FIT是如何满足这些条件的。我们的目的是想让读者在使用FIT的过程中,不要仅仅把它作为一个可以编写集成测试用例的工具,而是要把它看作是一个用于增强开发团队和客户、领域专家之间协作和沟通的工具。通过这种基于FIT的沟通和协作,可以为我们的软件开发带来很多正面的重要影响。

 
阅读更多

没有更多推荐了,返回首页