成功的现代项目——以及使用传统过程开发的成功项目——通常都有详细定义的项目阶段性标志,即从创造性研究状态到生产状态的显著过渡。早期阶段着重于实现可演示的功能。后期阶段着重于实现可供用户使用的产品,这种产品关注的是健壮性、性能、适用性以及完整性。
另一个重要方面是从创造性世界到生产世界的过渡对整个团队的影响。结构良好的团队通常不喜欢严格的过程、细节以及不成熟的精确性。生产能力强的团队通常会对松散的、不固定的、粗糙的结果感到不愉快。项目管理者需要管理各种团队的平衡性,这样技术上领导的重力中心可以在整个生存周期发展进化,从初始阶段的管理团队,到细化阶段的架构团队,到建构阶段的开发团队,再到过渡阶段的测试/评估团队。软件项目管理中人的因素被低估了,而且团队动态性的主题值得被给予比大多数项目管理课程所给予的更多的关注。
进展
经典开发过程的很多方面造成了涉众关系退化到相互间的不信任。信任对在用户需要、产品特性以及计划中通过指导和协商取得平衡是基本的。迭代过程加强了涉众间的有效交流(通过一系列可演示的发布实现),允许基于更为客观的所有人理解的协商。这需要客户、用户、以及管理者集中于可用系统的发布,而不是笃信标准和合同条款。它同时还需要开发组织致力于用能获得利润的方式创造价值。
迭代过程需要对一个不断完整的系统进行顺序的建构,这个系统展示了架构,实现了客观的需求协商,证实了技术方法,并指出关键风险。理想的情况下,所有涉众都着眼于这些里程碑,把它们视为有用功能的递增发布,这不同于那些投机的对终观点的论文描述。向可演示驱动的生存周期的过渡造成了非常不同的项目外观。一个健康的项目将诚实地展示出一个进展与背离共存的序列,而不是一个线性发展价值递增的轨迹(通常是不诚实的)。
下面是两个我从未见过的反例的相关观察:
1.一个具有一张价值持续不断增长曲线图的软件项目一定会有一个待解决的很大的回归。
2.在解决不确定性,会师于一个可接受的解决方案的过程中,健康的软件项目表现为一个进展不断增加,弯路不断减少的序列。
雄心勃勃的展示是一个健康的项目的发展道路上绝好的里程碑。在生存周期早期进行展示的目的是暴露设计缺陷,不是粉饰门面。涉众不应对早期错误、背离或不成熟的设计反应过激。如果早期工程阶段受到过分限制,开发组织建立的中间检查点将不会那么有抱负。早期的增量是不成熟的。外界涉众,比如客户和用户,不能指望初始发布的版本拥有终发布版本的规格和性能——也是完整、完全可靠、拥有目标级的质量和性能。
另一方面,开发组织必须对连续增量之上的切实的进展负责,并对之进行展示。客观地量化变化、修改以及更新将会为进展和质量提供诚实的指示。公开和专心的追随对解决问题是必须的。好的和不好的项目性能在生存周期的早期往往更为明显。采用指导式的领导方式,成功会孕育成功。在发布一系列可演示的结果以后,你可以很好地预测结果了。持续没有进展或者停滞的结果序列是项目需要认真重新考虑资源、范围或者项目价值的标志。软件项目的经验已多次表明,早期阶段决定项目的成败。这是使用小型的、能力强的出发团队处理计划和架构设计阶段工作的原因。如果这些早期阶段处理得当,项目将会由能力中等规模的团队向终产品发展,并成功完成。如果计划和架构设计阶段处理不好,即使出动全世界的程序和测试专家可能也无法在后续阶段取得成功。
质量控制
如果你按照迭代开发的精神正在成功管理一个项目,那么多数集成测试应在部件测试之前进行。停下来思考这一陈述。尽管在任何时候都有两种活动在混合进行,你应该认识到初始的部件开发和测试更多的是作为在一个集成的、系统级的线程或行为内执行一个部件的接口和功能的方法。一旦接口和集成行为被成功测试,部件的完整性也可以测试了。先进行集成测试加速了架构上重要的问题更早进入生存周期的相应阶段。它还为持续的系统级和部件级进展和性能的评估提供了演进的测试模板。
这种先进行集成测试的方法的一个关键副产品是测试和测试人员成了项目过程中的头等公民。在传统方法中,测试人员建立计划、过程和文档,它们都是次要于分析和设计工件的。测试人员的工作和生存周期早期的工件对项目的成功没有太多指示作用,在多数组织内都是由“B选手”(意思是,不能成为分析和设计师的人)来完成的。在健康的迭代项目中,生存周期早期的演示需要重要的测试观念和产品。很多测试团队对一些有效的“分析”活动和结果负有责任。太多分析人员在抽象模型内单独工作,他们的分析受到的制约是有限的。但是测试人员面临的是建立“测试用例”——真实世界中用例或者评估标准或者预期行为的表现。他们提出一整套不同的问题并从一个不同的角度看世界,因为他们的工作是把抽象的东西翻译为可测试的东西。
这是一个例子。现在很多项目都面临着对商业上可获得的部件和应用程序是采取买还是自己写的办法的抉择。如果第一个面向结果的项目的里程碑是通过演示来作出自己写/购买的决定的,那么你应该对你的团队进行如下分工:
分析团队:与用户一起工作,捕捉产生差性能的关键用例的情况,比如数据量峰值或者关键的控制画面。
设计团队:设计可以运行候选商业部件的原型。
测试团队:构建测试用例(比如,一个消息集合、一个测试驱动、一个智能桩模块、一个有数据的数据库、一个图形用户界面操作的序列等等)。这些用例能够反映关键用例,驱动原型并记录它的相应。
为了实现这第一个里程碑,你的团队可以只关注其中两个关键用例(约为用户需要的10%)、少数几个关键部件以及少数几个测试用例,但是它们以及用户将会在生存周期非常早的时候解决掉30%的风险。通过把测试观点作为过程早期一个同等伙伴包括进来,你将可以吸引更多作出更好分析的人才,因为这项工作更为有趣,而且对成功的贡献更为有效。
传统软件测试方法遵循相同的、应用于软件开发的文档驱动方法。开发团队在建立任何源文件或可执行文件之前先建立需求文档、顶层设计文档以及详细设计文档。相似地,测试团队在建立任何测试驱动、桩模块或工具之前先建立系统测试计划文档,系统测试过程文档、集成测试计划文档、单元测试计划文档以及单元测试过程文档。这一文档驱动方法对测试活动造成的问题与它对开发活动造成的问题是相同的:对大量废物的刨光,还要留待日后重新组合整理。
为了在生存周期中提早进行集成测试,测试序列应该由迭代过程来组织,而不是根据部件来组织。典型地,它应该被一组用例和其它文本表现的、能有意义地为用户进行演示的实体所捕获。下面是一个抽象的描述:
初始迭代:大约五到十个评估标准,抓住与主要用例(对结构选择和整体商业案例有影响的)相关的驱动问题。
细化迭代:十几个评估标准,当用候选架构进行演示时,为主要用例检验实体框架,并证明关键风险已经被解决了。
构建迭代:大约数百个与有意义的用例集相关的评估标准,这些用例集通过测试以后将组成有用的产品子集,可以转为产品的alpha或beta发布版本。
产品化迭代:完整的用例集和相关的评估标准(可能有上千个),组成了与真正发布产品相关的接受测试结果的标准。
现代过程在产品的测试活动中使用的基本工具、语言、符号以及工件与在产品的开发过程中使用的是相同的。测试是指对某些组件在一个控制情境下的执行以及期望的客观结果的外在评估。一个测试的成功取决于在一般意义上定义的成功标准下期望结果与实际结果的比较情况。测试是可以大规模自动化由机器完成的评估形式。