软件项目估算方法在敏捷开发中的实践.doc
软件项目估算方法在敏捷开发中的实践 0 引言 不知道您是否听说过关于软件项目管理的一个经典“六拍”笑话。那是这样说的 :在项目开始之前 ,大家先“拍脑袋”承诺项目进度安排 ;在开工大会上领导“拍拍大家的肩膀” ,语重心长 ,充满期待 ;而两杯小酒下肚 ,春风得意的时候 ,不由得“拍胸脯”向领导表决心 ,领任务 ; 而当项目执行中遇到困难时 ,客户和业主已经在“拍桌子”时 ,研发团队却不得不“一拍大腿” ,恍然大悟 ,事情怎么就这样了呢 ?!直到一切覆水难收 ,项目失败的时候 ,也只能“拍拍屁股”另谋高就去了。虽说这只是个笑话 ,但是也确实反映了软件项目中面临的一些问题。从“拍脑袋”到“拍屁股”走人 ,每个环节都可能存在着各式各样的问题。 但是追根溯源 ,要不是当初“拍脑袋”的时候没有考虑清楚、轻易地承诺 ,那么后面的一系列问题也就不会发生了。“拍脑袋”也需要好的方法 ,并不能轻而易举地一“拍”而就。就像带兵打仗 ,先要仔细谋划 ,知己知 彼 ,才能百战不殆。本文正是试图从软件项目的现实角度 ,通过敏捷开发中常用估算方法在项目中的实践 ,以及与其他估算方法的比较 ,从而希望能得到些有价值的参考意见。 这也是为了提高项目的计划质量而未雨绸缪 ,也希望下一次“拍脑袋”能拍得有理有据。 1 什么是估算 在软件项目管理中 ,估算就是对项目将持续多长时间或花费多少成本的预测。所以说 ,估算正是一种对未来的预测。本文将仅就项目时间估算这一方面展开讨论 ,而不涉及项目的费用和成本估算。 估算往往是与项目目标、项目承诺、执行计划等诸如此类的项目管理词汇联系在 一起。业务目标描述的是项目期望达到的成果 ,是进行估算的基本输入。而项目承诺则是项目组许诺在特定的日期之前以特定的质量交付规定的功能。承诺可以与估算相同 ,也可能比估算更激进或保守。 承诺是主观的对项目交付的时间和质量的预计 ,而估算只是基于客观事实的预测结果。此外 ,执行计划通常是罗列出各个工作项和其相联的关系 ,从而将承诺具体化。计划与估算并不相同。 前者是寻求如何实现特定的结果 ,而后者的目的是为了得到准确的预测。计划可以通过主观的方法进行调整 ,以实现特殊的要求 ,比如为了应付突发情况而进行赶工、增加资源等 。计划的基础正是估算 ,但计划不一定要与估算结果相同。如果估算与计划存在显著的差别 ,那么项目可能有较高的风险 ;反之则计划可能具有较低的风险。 在项目管理的九大知识领域中 ,项目时间管理中包含了与估算相对应的管理过程 :活动资源估算和活动持续时间估算。这些过程是在项目组已经建立 ,范围确定后进行的。其输入内容除上述前导过程的输出结果外 ,还建立在事业环境因素和组织过程资产之上。 而且活动持续时间估算的输出是后续制定进度表和进度控制的依据。由此可见 ,估算在项目管理中处于承前启后的位置 ,是项目计划制订的必须条件之一 ,也是项目最终顺利交付的关键因素之一。 项目管理是一门偏向于实践的科学 ,其理论和方法都需要在实践中检验 ,也需要根据实践经验做出适当的调整。这也是各种估算方法在项目管理中运用的关键 :必须根据实际的情况做出合适的变化 ,才能达到最好的结果。 2 估算的目的 软件项目的估算并不完全是纯粹的预测活动 ,而是与项目计划及确定优先级的活动有密切的联系。实际上 ,软件估算很容易受到其他事情的影响。但一旦做出了估算 ,并且在此估算的基础上承诺在某日期前交付具有一定质量的功能 ,那么项目经理就不得不通过管理控制使项目达到目标 。 通常来说 ,只要交付的项目与最初想要的功能水平大致相当 ,花费的资源与计划基本相同 ,而且大致上是在设定的时间框架内完成的 ,那么就可以认为项目“与估算一致” ,而不管这种说法在推理上隐含着怎样的瑕疵。 因此 ,评估估算的预测能力 (与最终结果进行比较 )并不能说明估算的实际价值 ,因为软件项目的外围环境总是不断地在变化。评价“良好”估算的标准应该是基于估算为项目成功提供支持的能力。所以说 ,估算的首要目标不是预测项目的结果 ,而是确定项目目标是否足够现实 ,从而让项目在可控的状态下达成这些目标。 3 敏捷开发的特 点 敏捷开发是在 2001 年前后 ,一些软件业专家为了解决许多公司的研发团队所面临的不断增长的项目问题和“过程”泥潭 ,所概括出的一些可以让开发团队具有快速工作、响应变化能力的价值观和原则。他们自称为敏捷联盟。 而其所倡导的开发方法就称之为敏捷方法。敏捷方法集成了许多新型开发模式的共同特点 ,它重点强调 : ①以人为本 ,注重编程中人的自我特长发挥 ; ②强调软件开发的产品是软件 ,而不是文档。文档是为开发服务 ,而不是开发的目的 ; ③客户与开发者的关系是协作 ,不是合约细则。开发者应与客户合作来澄清需求细 节 ,而不是将自己变成客户业务的“专家” ; ④设计周密是为了最终软件的质量 ,但不表明设计比实现更重要。为了适应客户需求的变化 ,设计要能根据环境的变化而不断更新。 敏捷开发通常用于复杂或非常不确定需求的软件项目。它不同于传统开发方法 ,如瀑布模型 ,原型法等。主要区别在于敏捷方法是开放的、具有弹性的方法。敏捷方法在项目管理中更加关注于人在项目中的作用 ,而不是繁复的计划和沉重的过程方法。 人是项目成功的最重要因素之一。但是敏捷开发团队并不一定非要由顶尖的开发人员组成。顶尖的、但不能很好与别人合作的成员并不 比普通的、但与其他人沟通良好的成员更加适应敏捷开发的特点。因此 ,敏捷开发特别强调与人合作、沟通和交流的能力 ,这比单纯的软件开发能力更为重要。而且敏捷开发团队一般都会较小 ,这也是为了能达到最高的沟通效率。典型的敏捷开发方法有 :SCRUM、Crystal、特征驱动软件开发 (Feature Driven Development,FDD)、以极限编程(eXtreme Programming,XP)等。 本文会根据在软件项目中实施极限编程的实践 ,对敏捷方法的估算技术做进一步的讨论。但所讨论的方法不仅能用于极限编程 ,也适用于其他敏捷方法。 4 敏捷开发中的估算方法 敏捷开发的团队通常是由较有经验的、善于沟通的人员构成。所以在敏捷开发中采用的估算方法往往需要便于理解、能发挥团队成员的集体智慧、并有利于项目的顺利交付。在笔者的团队中 ,采用了一种叫做“扑克估算” (Planning Poker)的方法进行项目初 期的估算。正像许多其他敏捷开发中所采用的技术 ,“扑克估算”也非常简单 ,但却有效率。 首先 ,敏捷方法中的估算应该是由团队成员共同进行 ,而不是由项目经理“闭门造车”式地得出。这样做的原因之一是因为开发团队是由不同经验的同事组成 ,对于同一个问题 ,经验不同的人往往会给出不一样的解决方案。如果可以将所有人的能力集中到一起 ,那么最后对问题的求解也就八九不离十了。 同样的道理也能用在估算上。“扑克估算”大致过程是这样的 :开始之前首先要决定采用的估算度量。一般来说“估算点”比较常用 ,但有时也会采用费伯那其数字 (FibonacciNumber,0,1,1,2,3,5,8,13… )作为估算点的值 ,或者 采用衣服的尺码 (XS,S,M,L,XL,XXL… )或其他抽象的数字或符号。例如 ,用户故事一比较简单 ,那么可以标记 1 为它的估算点 ;用户故事二是一个系统登录过程 ,需要考虑的方面较多 ,那么就可以标记 13 为它的估算点等。 这样做的最大好处是可以估算出每一个“块”相对于其他“块”的大小 ,而不是实现它需要的时间长短。因为敏捷开发具有短交付周期的特点 ,一般经过几个周期的适应 ,团队就能逐渐得出每个“点”该花费多少时间的认识 ,那么下次估计就会更加准确。 这也正是敏捷开发的另一个“自我纠正”的特点。接下来就是准备这样一 套卡片或使用即时贴代替。团队成员对于每一个用户故事进行讨论 ,澄清关于该点的需求 ,尽量使所有成员都理解这个功能该如何设计等。 如果大家对于某一点再也提不出问题 ,那么就一起亮出自己的“估算点”卡片。正如前面所说的 ,每个成员都有不同经验背景 ,所以很难一次都给出同样的估算。这是因为可能某个人看到了潜在的问题和风险而其他人却没有发现 ,又或者有人想到了一个更加简便的办法等。得到不同意见后 ,将其作为下一步讨论的基础。 大家相互交换对问题风险的看法 ,讨论新的点子等。最后 ,小组重新投票得出一个比较一致的估算。一个接着 一个 ,按照同样的流程对所有的用户故事进行估算 ,得出一串不同的“估算点”。这就是“扑克估算”的大致思路。 5 常用的估算方法 能够应用在软件项目中估算方法还有很多种 ,其中功能点分析是一种常用方法。它是将系统分解为较小组件 ,以便能够快速理解和分析。同“估算扑克”法类似 ,功能点是功能点分析的测量单位在功能点分析中 ,系统被分为五个大类组成部分 (组件 )和一些常规系统特性。 前三类件是 :外部输入 (External Inputs EI)、外部输出 (External Outputs EO)和外部查询 (External Inquiry EQ)。这些组件中的每一个组件都处理档案 ,因此他们被称为“事务” (Transac-tion)。另外两类或组件是 :内部逻辑文件(InternalLogical Files ILF)和外部界面文件 (External InterfaceFiles EIF),它们是构成逻辑信息数据的存储之地。 外部输入 :是指用户可以根据需要通过增、删、改来维护内部逻辑文件。外部输入使用户可以维护 ILF。外部输出 :是指用户的输出结果。显示结果就是经过调用维护数据和参考数据获得的。在功能点术语中 ,显示的结果 就称为“外部输出”。外部查询 :是指用户可以通过计算机系统选择特定的数据并显示结果。 为了获得这项结果 ,用户要输入选择信息抓取符合条件的数据。此时没有对数据的处理 ,是直接从所在的文件抓取信息。例如 :驾驶员要显示预先设置的地形图 ,输出的结果就是直接从信息存贮位置提取的信息 ;这里称作“外部查询”。 内部逻辑文件 :这是第一项数据功能 ,使客户可以使用他们负责维护的数据。数据在系统中的逻辑分组是由最终用户维护的 ,所以把它们叫做“内部逻辑文件”(ILF)。 外部界面文件 :这是第二项数据功能 ,也和数据的逻辑分组 有关。在这种情况下 ,用户不负责维护数据 ,数据在另一系统中驻留由其他用户进行维护。该数据只供系统用户参考使用。例如 :飞行中 ,驾驶员可能需要参考某卫星或地面定位系统的定位数据。驾驶员不负责更新这些数据但要参考使用。 这样 ,这些只供参考使用的其他系统的数据分组就称为外部界面文件。功能点估算通过对于系统的分析 ,根据以上五种组件的多少 ,按照高、中、低三个类别对每项的复杂度进行打分 ,最后加上影响估算的调整因子而得出估算结果 ,如下面的公式 AFP(调整后功能点 )=UFP(未调整功能点数目 )×AF(影响因子 ) 6 实际的例子 笔者在实际采用敏捷方法的项目中进行了一些实验。分别采用不同的方法对于同样一个短开发周期的工作进行了估算 ,结果如下表 1 所示。表 1 不同估算方法不同估算结果方法估算值单位工作量 (人 /天 )预计工作量扑克估算 33 1·6 52·8 人 /天功能点估算 69 0·8 55·2 人 /天 其中扑克估算的单位工作量是按照前几次团队估算的结果调整得出的 ,大约要花费 1·6 个人天才能完成一个估算点的工作量 ;功能点估算的单位工作量是从公司已有的统计表格上摘录 ,反映了在公司中采用类似技术团队的平均工作效率。 整个周 期大约花费了两个礼拜的时间 ,共有六个团队成员参与开发。实际工作量可以认为是 60 人 /天。 7 结果的分析 综上所述 ,在采用比较简单的、基于团队经验的估算方法比起精确的、有着复杂数学模型的估算方法并没有明显精确度的差异。但是相对于复杂的方法来说 ,简单的、易于团队达成共识的方法能节约得出结论所需要的时间 ,也能增强团队对于任务的认识。 从另一个侧面来看 ,也能提高团队的士气和效率。正如某些研究预测学的专家所说 ,“研究预测学得到的最牢靠也最有用的结论之一就是 ,简单方法总体上和复杂方法一样准确。” 比较敏 捷估算和功能点估算 ,二者都是将项目量化成一个抽象的值 ,但如何求出项目完成所需要花费的时间却又各不相同。前者通过项目团队自适应的开发模式 ,通过一段时间的实践 ,得出一个单位工作量 ,从而得出项目的全部工作量。后者通过更大范围的历史数据。 比较相类似的项目 ,得出一个单位工作量 ,然后估算项目的预计时间。无法说哪种方式更加优越 ,但显而易见第一种更容易实现 ,而第二种需要大量的项目积累。而且项目团队并不完全一样 ,人也并不是纯粹的资源 ,所以后者的平均工作量对于不同团队可能是不一样的。 比较而言 ,第一种方法可能会更贴近 于实际。此外 ,估算方法毕竟只是某种估计 ,并不能期望采用一些更好的方法就能做出完美的项目计划。在项目控制上多下力气才是最终的王道。由于需求变更是估算产生问题的最大来源。 如果需求确定不下来 ,估算的可变性就会保持在一个高的水平直到项目结束。而且因为有需求变更 ,项目经理往往会更加关注于变更本身以及其对于进度控制等方面的影响 ,从而忽视了对原始估算进行调整的需要。 不幸的是 ,也许原始的估算在当初的功能范围内还算准确 ,但在增加了十几个功能以后 ,由于没有适当的更新 ,所以项目将根本达不到它最初所承诺的估算结果。讽刺 的是 ,虽然所有人都承认增加的那些特性是不错的改动 ,但项目最终还是会被看做延误了。所以 ,再好的估算方法并不能解决由于需求不稳定所造成的问题。 在项目控制上做出相应的调整才能更好地解决这个矛盾。对于敏捷开发来说 ,其本身就是为了适应高可变性的环境而诞生的 ,所以将合理的估算和敏捷开发的项目控制结合起来 ,才能最好地保证项目按照可控的时间、预计质量进行交付 ,也能使得所有的利益相关方最终收获满意的结果。