1、软件工程论文 计研 53 郭强 0248641极限编程( XP)的研究及在软件工程中的应用计研 53 郭强 024864【摘要】极限编程是以开发符合变化的客户需求的软件为目标而产生的一种方法,它的成功得益于它对客户满意度的特别强调,XP 使开发者能 够更有效的响应客户的需求变化,哪怕在软件生命周期的后期。极限编程是一种经历过很多实践考验的软件开发方法. 已经被成功的应用在许多大型的公司。本文还将结合实际项目中问题以及实际开发的经验,阐述极限编程的运用。极限 编程带 来了不少新的思想,值得学习和借鉴,在阐述的过程中,本文 还要讨论如何能 够结合我国软件工程实践的现状,更好的利用 这些思想,并指出
2、某些做法的利弊,以供参考。【关键词】极限编程 结对编程 迭代 协作 简单化 一、极限编程的简介a、什么是极限编程极限编程(XP) 是一个周密而严谨的软件开发流程。引入了迭代的概念,减少了开发中的瓶颈,风险也随着降低,但核心问题是项目计划。还有一个潜在的因素就是每个项目成员尝试不同的角色,减少项目由于人员流失而带来的周期失控。可是这样做也很有可能使某一个周期迭代的结果发散而不是收敛,无论如何,总比整个项目失控好.XP 对客户满意度的重视是它成功的一个因素。开发满足客户需要且确实是客户需要的软件,这是 XP 的初衷。XP 使得你的开发人员能够自信地面对客户需求的变化,即使是在开发周期的后期。 XP
3、 强调团队合作。经理、客户和开发人员都是团队中的一员,他们都应该为了开发出高质的软件而努力。对于这种团体形式的开发,XP 采用了一种简单但有效的方式 。XP 中许多部分其实都来自于业已存在的那些优秀的开发实践。“XP 中没有一个想法是全新的。大多数想法产生的时间实际上和编程一样古老“ , 尽管 XP 所用的实践方式不是全新的,但是概念的建立以及它们如何融合在一起极大地增强了这些“老“ 的实践。可以从XP 中提炼出四个关键的思想:交流,简易,反馈和勇气。XP 程序员同客户交流,同他们的同事交流;他们的设计简单而干净;他们通过测试来得到反馈;他们根据变化修改代码,并争取尽可能早地将软件交付给客户。
4、在此基础上,XP 程序员能够勇于面对需求和技术上的变化。XP 对生产力也有要求。从已有的报告中,在相同条件下,所有采取 XP 的项目组都无一例外地比其它项目组的生产力高。但这从来不是 XP 的目的。XP 的真正目的在于按时交付客户需要的软件。如果这对于你的项目而言很重要,你就可以尝试一下 XP。要有充分的培训、要有每个人的提升空间、制定报酬要根据对企业的贡献大小,而不是职位的高低,允许下属比上级薪酬更高,薪酬的高低取决于绩效评定,同时绩效评定要尽可能量化。并且推行淘汰制。同时有有效的招聘制度。有强有力的后勤保障制度和轻松的企业文化。b、极限编程的应用范围极限编程(XP)适用于需求经常发生变化的
5、项目。你的客户对系统应该做什么可能没有一个固定的想法;一个系统每隔几个月其功能就要求进行一定的改变。大多数软件项目的需求都处于这样的动态变化之中。与其它的方法相比,XP 能够更好地适应这种情况。在我国,电脑化还处于初级阶段,很多客户对于自己的需求在开始的时候很模糊,这样随着软件工程论文 计研 53 郭强 0248642项目的推进,这种情况往往是不可避免的。XP 适用于高风险的项目。 如果客户需要一个新的系统,而且要求在某天前完成,这里的风险就比较高;如果你的开发组没有做过类似的系统,风险就更高了;如果该系统对整个软件业来说都是一个新的挑战,那这风险就可想而知。使用 XP 可以降低风险和增加成功
6、的可能性。XP 适用于小规模的项目组,一般在 2 到 10 人之间。使用 XP 不需要拥有博士头衔的开发人员,一般的开发人员就可以。但不能在一个大型的项目组中采用 XP。我们注意到,对于一个需求动态变化和高风险的项目而言,一小组 XP 开发人员要比大的开发组更加有效。 XP 对项目组的组成人员有要求。组内不仅包括开发人员,还包括经理和客户,所有人员肩并肩地战斗在一起。软件开发中问题的讨论,项目范围和进度的协商,以及功能测试的创建仅靠开发人员是不够的。XP 对可测试性有要求。你必须建立自动的单元测试和功能测试。虽然在某些情况下这个要求不能满足,但事实上你会惊讶地看到通过某种方式仍然可以达到这个要
7、求。比如可以通过修改系统的设计以使之已于测试。记住,只要你愿意就可以找到一种测试的方式。对于针对小型项目以及编程而言,在 XP(至少是 Beck 的书中)里对管理的欠缺是可以理解的, 。就如 Beck 写的,“对于教练(coach)来说,或许最重要的工作就是获得玩具同食物“(指导是 Beck 的管理战略中的一个组成部分)同许多的程序员一样,他们推荐的管理策略像是:躲避。下面的假定呢?躲避会建立一个协作的环境,在传统的基于任务的管理里,这个假定是有效的。然而,根据我的经验,创造并维持一个协作的环境会挑战管理远离编制任务列表以及检查。Beck 从他的早期的著作开始,就不断向那些软件工程中的一些“
8、古训“发出挑战。从 19世纪 70 年代中期的结构化方法,以至后来的那些更复杂的方法,他们都基于如图 1 所示的那个“事实“,在整个 80 年代,我必须了解、使用、讨论、实施这些方法。figure 1 history lifecycle change costBeck 却给我们提了一个问题,那些在 70 年代和 80 年代也许还能起到效果的方法,他们的经费开销状况(如图 1)现在已经发生了变化(如图 2) ,也就是说,维护的成本(也可以等价为不断发生的变化)降低了,而不是越来越高。实际上,图 2 所示的开销情况在当今是否是事实其实并不重要,重要的是我们必须认识到,如果图 1 的现象还在继续重演
9、的话,我们只有死路一条,因为当今时代变化实在太快了(也就是说维护的成本将是一个软件工程论文 计研 53 郭强 0248643天价) 。Figure 2 - Contemporary lifecycle change costs.图 1 中的 y 轴通常用来表示在开发周期的后期发现错误后需要花费的改错成本。可是,这正验证了一个假设,即后期所有需要做的开动均来自前期的一个错误,比方说一个设计缺陷。从这一点来看,传统方法太依赖于在软件生命周期的早期“不出错“ 。但是在当今瞬息万变的环境中,我们不能完全预防住那些我们预测不到的东西-即由应用需求不断增长而带来的变化,并且这种变化在早期不可能遇见并加以预
10、防。因此,虽然我们要尽可能在早期做出某些应付变化的预防措施,但是更重要的是我们要减少后期改变所带来的开销。正如 Alistai Cockburn 所指出的,需要高成本的图 1 所示的那种改正缺陷方法,正好从节省开支的角度给了一些实用的方法(如配对编程)一个好的理由。二、极限编程在软件工程中的实际应用a、 国内的现状目前在国内,大部分的软件开发都是以模块为单位的,一个项目确定后,项目负责任依据功能将项目划分几大模块,根据工作量的大小,进行任务划分,每个项目开发人员负责一个模块的编写。项目中很大一部分是应用项目,局限性很大,这个应用结束之后,可能相应的软件就没有多大的应用价值了。即使是一些比较大的
11、公司,其系统调研也更依靠系统分析员的经验,因为客户很少又在项目初期就对自己的需求了解的很清楚,而且即使客户有了解,我们的程序员不一定可以很深入的了解道,并实施道项目当中去!如果项目负责人是一个有着丰富经验的高级系统分析员,以前从事过这样的项目,根据以前的经验,可以很好的总结,并指导项目组按照一定的方向实施,可能会达到比较满意的结果。可是一方面项目有各种各样的不同,另一方面,一个人的经验往往可能无法跟上变化,这个时候有可能导致很周密的先期分析、调研可能导致的是完全不合需求的产物。而且,对于任何一个项目,在项目的开始就有很完善的设计,几乎是不可能的事情,随着项目的进行,总会发现没有考虑到的东西越来
12、越多的出现,有可能是在开始的完全错误的设计。已经完成的模块,完全不是符合用户需求的产品。造成极不好的影响!一方面拖延了项目的工期,加大了项目的成本,另一方面,降低了用户的信任度,不利于项目的进一步实施!对于这种情况,有几种解决办法,第一就是在项目的初期,保证对项目的理解正确地情况下,和用户签订协议,把项目的目标集中在核心的模块上,当需求发生变化时,可以尽可能的忽略,根据计划继续进行下去,如软件工程论文 计研 53 郭强 0248644果这种缺陷可能是无法回避的,可以同客户签订备忘录,对项目进行调整,尽量减少项目的风险和成本。第二种就是限编程方法。在国内,很多项目要求可以看到明显的进度,这样有阶
13、段性的成果,对下一步项目的实施以及客户的满意都有很重要的影响,客户会采取更主动的态度,有利于软件的开发,而这个时候,采取极限编程往往可以得到比较好的结果,极限编程就是强调小型的发布,迭代的开发。b、 极限编程的应用应记住的一件事情就是我们应倾向于在小型的, 局部的团队中运用 XP。除了代码与测试用例外, 尽量减少有限的影响。XP 的实践既有正面的表现,也有负面的。在某些方面看来,他们听起来就像一堆规则,要做这个,不要做那个。对此 Beck 解释道, 与规则相比, XP 更像是指导方针,一个灵活的依赖于具体环境的开发方针。但是诸如“每周工作 40 小时“ 等看起来可能会感觉罗嗦。Jeffries
14、 使得实践也会互相作用的,平衡,互相加强。以至于挑选使用的同丢弃的都是棘手的事情。交流,应该保持开发队伍的交流。这样才能保持队伍的活性。在一个开发队伍当中,程序员的素质是不一样的,有经验非常丰富的高级程序员,也有代码量很少的程序员。这样就造成了开发上的难度,不能保证每个人对制订的标准和开发的规范是完全理解的,而理解伤得偏差反应在程序里就会造成借口的不统一,模块独立性的下降。这样只有通过加强程序员之间的交流小型发布以及迭代式的开发,就如同备考一样。参加高考,需要参加许多的模拟考试,这样才能保持状态,不断的检验自己的盲区和不足,适时的弥补缺陷。项目开发也是一样的道理,只有保持明确的短期目的,才会保
15、持团队的目标,避免在项目开发过程中迷失方向。需要不断的修正前进的方向,以保证不会偏离轨道或太远。站立会议,要求项目组全体参加,而不是某几个人。这种形势有利于团队之间进行沟通,每个成员随时了解整个项目的动态,以对自己的工作做出调整,避免出现,软件开发了大部分,却不合要求的情况。站立开会要求更高的效率,任何人的迟到都可能引起大家的不满,而且要求会议的内容尽可能的精简和重要。简单化:不要增加没有列入到进度中的功能。有些功能听起来确实恨诱人,但实施的时候却可能成倍的增加项目的难度,而且可能并不适用。据调查,仅有 10的预留功能在将来发挥了作用,其他全是无用功,为什么不等到明确提出这种需求的时候再去实现
16、呢?尽可能的针对当前这个项目,有利于项目的实施,和集中精力完成核心功能。注意力太过分散,只会得不偿失。例如,有两个做医院 MIS 的公司,一个公司在开始的时候实力稍强(以下简称 A) ,签了一家比较大的市级医院作为试点,如果这个项目成功,则意味着该市的医院都将成为潜在的市场,甚至可能全国的医院。而另外一家公司开始的规模并不大(以后简称 B) ,开始的规模仅为一间办公室, 10 个左右的开发人员,其中只有一名资深程序员。在开始的时候,仅利用低廉的价格争取了一家郊区的医院作为试点。而可能正是起点的不同导致了结果的不同。A 在开始就把目光放在了医院整体软件上面,其方案非常庞大,希望开发出旗舰级的软件
17、,认为医院的核心就是医疗器械,认为这是医院的特色,甚至想涉足医院的医疗成像等专用设备,希望通过电脑联网,实现网上诊断。预留了非常多得接口,软件非常庞大。如果可以实现的话,将是非常成功的软件。但是由于医疗方面的好多软件涉及到图形学、医疗知识等许多领域,并没有相应的成形软件,即使有的话,由于知识产权的缘故,并没有提供相应的借口。结果可想而知,软件迟迟不能发布,客户信心逐渐丧失。而 B 在开始的时候,就把精力集中在几个核心的领域,他们认为医院作为一个企业,关心的是他的经济利益,所以重点放在了住院,药方,门诊,库房等领域。还有目前在医院已经用电脑化的部分,参考已有的软件进行设计,由于有现有的软件参考,
18、软件工程论文 计研 53 郭强 0248645实现起来比较容易。最后的结果是项目按期交付,大大降低了医院员工的劳动强度,实现了医院管理的透明化,因为医院最关心得还在于账目的管理,而不在一些以前并未涉足的图形图像领域,赢得了客户的好评,客户配合非常积极。而且在这期工程实现后,医院意识到了自己的需求,主动要求增加二期工程,这样不仅占领了市场,而且赢得了时间。现在去这个市,市里的医院大部分都在使用该公司的软件,而这个市是一个直辖市,市场可谓很大。所以,要在开始的时候集中精力,作一些客户最关心的东西,让客户可以感觉到实现自动化所带来的好处,这样才可能更大的挖掘客户的潜能,有利于吸引客户。不管是从开发的
19、角度,还是从市场的角度来说都是非常好的。一定要脚踏实地,不要头脑发热。程序员都有希望得到他人认可的冲动,往往希望通过一鸣惊人来达到这种目的,希望可以推出尽善尽美得软件。但是往往是得不偿失,到后期往往是一方面不能得到客户的认可,另一方面由于精力放在了多余的方面,继续投入精力觉得浪费,不投入精力有无法完成功能模块,结果越走越远。所以随时随地对自己做过的东西毫不留情地简化,将设计、编码简单化,简单得足够容易理解、修改和扩展,这才是编程应遵守得法则。测试,也是非常重要的。单元测试是 XP 方法中的小界石,但与传统的单元测试略有不同1、要创建或下载一些单元测试工具以便能够自动生成测试数据2、测试系统中所
20、有的类3、单元测试应与其所测试的代码一起发布4、没有单元测试的代码不能发布5、若发现没有进行单元测试,则立即开始进行一家软件公司客户引用一个内部研究结果,表明在测试阶段发现一个缺陷需 15 小时,在 Inspection 阶段发现一个缺陷则需 23 小时,而在 Inspection 之前发现缺陷只需 15 分钟。后面的数据来自于产生于常规审查的持续的团队学习。“ 对于编程而言,乐观主义是一种冒险。而反馈则是相应的解决良药。无论是用反复的构建或者频繁的用户功能测试,XP 都能不断地接收到反馈。虽然每次对软件开发策略进行研讨时,我们都会说及反馈-即使是非常有害的瀑布模型-不同的是 XP 的实践者认
21、为反馈比起前馈 (feedforward)来更为重要。无论是对测试失败的代码进行修改或者是对用户拒收的软件从新返工,开发环境的快速变化要求开发人员对反馈有更好的认识。在我们 ddb 的工程中,我负责的模块先期测试做得很少,想当然的认为没有什么问题,认为即使有问题,也不是什么大问题,结果代码累计越来越多,当上千行之后,测试就成了一个麻烦。最终在联调的时候,出现了许多预想不到的错误,需要一个一个函数,一个一个模块检查过去,甚至整晚都在排除一个错误,导致了时间上的严重浪费。有一些问题,甚至就是初期设计上的严重不足,属于先天的不足,属于架构上的错误,但是由于编程只停留在编码的阶段,只是编译通过,并没有
22、实际进行运行和黑箱测试。最后导致了灾难性的后果,一大块代码必须废除,根本没有办法融入到整体当中,留下了惨痛的教训。在极限编程当中强调配对编程,“配对编程是两个人试图同时编程和理解如何更好编程的一种对话“,让两个人同时坐在一台终端前面(一个人敲代码或测试用例,一个人审查和思考)产生一种持续的、动态的交流。Williams 在犹他大学进行的博士论文研究证明了配对编程不仅仅是一种美好的想法而且确有实效。可是在我国的环境下,配对编程不一定是一个好的想法,由于我国的人才培养制度和工作环境,我国的软件开发人员大都习惯于独立开发,而且这被证明是非常高效的制度,三个和尚的故事我觉得还是有一定的道理。但是可以采
23、纳配对编程的想法,编程的过程中进行交叉测试,交叉排错。这样既可以提高开发的效率,又可以增加程序的鲁棒性,增加程序员之间的交流,更有效的开展整个项目。软件工程论文 计研 53 郭强 0248646客户是非常重要的资源。一方面,没有客户的好的配合,工作的开展将是非常的困难,几乎就是不可能完成的任务,先期的调研到后期的实现,必须有客户的配合;另一方面,客户的反馈是非常重要的,如果最后得不到客户的认可,这个项目就是失败的。在给一个企业做 MIS 的时候,在开发的前期,根据已有的调研进行项目的开发,经常会遇到不知道应该怎么办的情况,因为好多情况,不是仅凭调研就可以想象到的,一些具体细节和流程是我们所不熟
24、悉的。结果在现场调试的时候,客户提出了很多疑问,很多地方是完全不符合要求的,鉴于这种情况,我们当时采取现场开发的办法,这样可以随时向客户咨询,每当我们完成了一个功能模块,我们就让客户进行检验,随时获得反馈,这样取得了意想不到的好的效果,工程进度大大提高,主要原因是少走了很多弯路,可以直接的把客户的应用转化成为我们的需求,从而满足用户的要求。另一方面,我觉得在极限编程的许多介绍回避了很重要的一点,那就是把客户当成你的开发伙伴,贯穿于整个周期中,但客户的主要功能是在实际的使用中给开发者提供有效的反馈信息,开发人员可以做到及时分析客户的反馈以调整程序,但是大量的运行数据已经发生(客户的业务数据) ,
25、调整程序必然会引起数据的规范,这个工作量伴随着整个开发周期,而且不容忽视。举个例子,在你的初期模型运行了两个月后,你突然发现设计中存在很大的漏洞,导致系统查询的速度非常的慢,因为在主要使用的表中存在着大量的低概率使用数据,这个时候你要重新考虑设计,也许会将经常使用的数据和不常使用的数据进行分离,那么在第二个周期,又一个很重要的工作就是数据分离,如果在第三个周期,突然发现又一种现象你的程序无法处理,这个时候也许你需要一个标志位什么的进行区别,那么以前的数据是不是要根据具体情况划分到不同的情况中去(设置标志位) ,这些工作必须是建立在数据完整和规范的基础上,否则你的下一个周期就无法得到正确的结果。
26、另外,让我们进一步做个简化,即假定软件的用户需求已经确定。我们的目标是既能快速不断的发布新功能,同时又要让软件的设计易于更改。即使是在快速发布这个目标下,仍然需要在“快速发布但 Bug 丛生“和“面面俱到但旷日持久“ 之间进行取舍。因此,让我再简化一下我们要讨论的问题,我们假定我们已经在设计、编码和测试这三者之间取得了合理的平衡。在上面这些简化的基础上,还留有一个尾巴:我们在设计时对于未知的未来要看多远?现在的设计已经实现了我们现在想到的一些功能。具有预见性的设计可以使未来的需求更快的获得实现,也就是说预见性设计方法在以现在的时间换取未来的时间,如果一点点现在的时间可以换来未来节约大量时间,当
27、然是划算的。但是这种建设怎么才能成为现实呢?也许未来出了问题就整个重新设计一遍也不慢,那又何必现在瞎猜呢?这就是我们为什么要提出重构的原因。重构,Martin Fowler 说过,是不改变软件对外表现但是重整内务的一种改进。XP 方法的支持者在变化的环境中实践了连续的、增量式的重构方法。如果变化是不断演化的,那就不可能存在什么一步到位的设计方法。说白了,如果变化不可预测-正如当今社会的情况-过多的在设计时考虑以后可能的变化,完全是一种浪费。我认为图 3 给出的是互联网时代到来之前的情况。由于变化的速度慢(图中由天平的支点比较靠左来表示) ,早期的预测多一些是合理的。但是在图 4 中,由于变化速
28、度变快了,设计时预测太多是得不偿失的,这种情况正是现在许多系统所面临的。软件工程论文 计研 53 郭强 0248647Figure 3 - Balancing design and refactoring, pre-internetFigure 4 - Balancing design and refactoring today.在一个长期项目中,检验一个设计是否具有很好的灵活性是通过变化需求,同时看看原设计能否很容易的实现新变化的需求。这种传统的“先设计,再维护“ 策略的最大问题在于软件系统存在非常大的熵(极易变化,没有规律) 。一个系统随着时间的推移,维护、改错、打补丁、增强功能等工作会使
29、系统的熵越来越大。现在由于外部环境变化加快,情况正越来越糟。不过,现在的重构技术也不是第一个试图解决这个问题的方法。早在所谓的“黑暗时期“(circa 1986) ,Dave Higgins 指出了由于随着时间的推移变化的累计影响不断增大,维护所需要的开销也将越来说庞大,Higgins 提出了一种新的设计方法(the Warnier/Orr Approach)用于阻止系统的熵增大所带来的负面影响,该方法的思想是在维护过程中有系统的对程序进行重新设计。Higgins 的方法首先为程序改如何设计设定一种模式(虽然那时还没有模式这个提法) ,然后在细致的代码设计与“好 “的模式之间建立一种映射,程序
30、员即根据这种映射关系来理解系统并修改程序,使修改的结果更接近于那个模式。使用 Higgins 这个方法可以通过维护抵消系统谁时间而熵增大的趋势。Higgins 说:“该方法的目标并不是重写整个系统,而只是重写那些根据需要必须增强的部分。“软件工程论文 计研 53 郭强 0248648虽然这种原始的“重构“ 技术并没有被广泛的实践检验,其思想与现在的重构还是相通的,只不过现在的需求变化更快、更大。不过有两个东西驱动、提高了现代的重构技术:一是更好的程序设计语言和开发工具;二是更快的变化需求。在早期的 RAD(快速原型开发)方法中还有另一种应付变化的办法:代码抛弃思想。这个思想认为环境和需求变化太
31、快,因此我们唯一的办法只能是快速编写新代码,并且也快速的抛弃老代码。我们认为这不是长久之计。重构,设计模式,对单元测试的充分理解,配对编程-这些都不是黑客们的工具。它们是开发者 们为了解决产品快速发布,同时又能保持较少的缺陷和灵活性时探索出的新方法。关于质量,Beck 说,“只有两种情况下是有价值的: 优秀或者极其优秀,这取决于其对软件产品生存的影响程度“ ,以及 “执行测试直到它们通过(100正确)“ 。你也许可以指责 XP 的实践者是受到了蒙蔽,但是他们决不是那种不重视质量的黑客。三、总结对于传统方法的支持者来说,缩短发布时间是质量的敌人。然而,我看过一些开发速度 很慢而且质量非常差的软件
32、,就象我看过的另一些开发速度很快但质量低下的软件一样。虽然在时间和质量间存在一些明显的联系,但我认为这个联系比我们一般所想象的要的复杂的多。.传统方法可用于开发那些变化程度不大并可预期最终结果的软件。然而,商业世界却是变化莫测的,并且传统开发方法已无法满现在的快速变化软件需求的要求。轻量级软件开发实践的创始人 Bob Charette 认为“由于软件工程研究所 (SEI)这样组织的官僚化、顽固性,以及诸如 CMM 的实践,使得他们日益脱离当今的软件开发。.XP 中的各个独立实践,都是从著名的,经过很好的测试的传统实践中抽取出来的。这些原则驱动着实践的使用,与一个特别的实践最小集自然的一体化在一
33、起,使得 XP 成为一个解决现代软件开发问题的新方案。但是所有的这些新实践都没有很长的历史,它们没有被加以研究和度量。然而我坚信,我们混乱复杂的电子商务经济需要我们重新审视 如何开发和管理软件发布。这些方法虽然很新,但它们提供了有价值的另一条思路。【参考文献】1、 Extreme Programming Examined , Person Education, (加)Giancarlo Succi, (美)Michele Marchesi 著2、 Planning Extreme Programming , Pearson Education,Kent Beck,Martin Fowler 著3、 解析极限编程拥抱变化 ,人民邮电出版社,Kent Beck 著