Caper Jones是Software Productivity Research(软件生产率研究)的首席科学家,他回顾20年的软件研究,指出他和同事见过不止700种不同的编程语言,以及40种收集需求的方法、50种进行软件设计的方法、30种针对项目的测试方法(Jones 2003)。
不同种类的软件项目,需要在“准备工作”和“构建活动”之间做出不同的平衡。每一个项目都是独特的,但是项目可以归入若干种开发风格。表3-2列出了三种最常见的软件项目种类,并且列出了各种项目最适合的典型实践。
表3-2 三种常见的软件项目种类,及其典型的良好实践
|
软件种类 | |||
|
|
商业系统 |
使命攸关的系统 |
性命攸关的嵌入式系统 |
|
典型应用 |
Internet站点 Intranet站点 库存管理 游戏 管理信息系统(MIS) 工资系统 |
嵌入式软件 游戏 Internet站点 盒装软件 软件工具 Web services |
航空软件 嵌入式软件 医疗设备 操作系统 盒装软件 |
|
敏捷开发(极限编程、 Scrum、time-box 开发等等) 渐进原型(prototyping) |
分阶段交付 渐进交付 螺旋型开发 |
分阶段交付 螺旋型开发 渐进交付 | |
续表
|
软件种类 | |||
|
|
商业系统 |
使命攸关的系统 |
性命攸关的嵌入式系统 |
|
增量式项目计划 随需测试与QA计划 非正式的变更控制 |
基本的预先计划 基本的测试计划 随需QA计划 正式的变更控制 |
充分的预先计划 充分的测试计划 充分的QA计划 严格的变更控制 | |
|
需求 |
非形式化的需求规格 |
半形式化的需求规格 随需的需求评审 |
形式化的需求规格 形式化的需求检查 |
|
设计 |
设计与编码是结合的 |
架构设计 非形式化的详细设计 随需的设计评审 |
架构设计 形式化的架构检查 形式化的详细设计 形式化的详细设计检查 |
|
构建 |
结对编程或独立编码 非正式的check-in手续 |
结对编程或独立编码 非正式的check-in手续 随需代码评审 |
结对编程或独立编码 正式的check-in手续 正式的代码检查 |
|
测试与QA |
开发者测试自己的代码 测试先行开发 很少或没有测试(由单独的测试小组来做) |
开发者测试自己的代码 测试先行开发 单独的测试小组 |
开发者测试自己的代码 测试先行开发 单独的测试小组 单独的QA小组 |
|
非正式的部署过程 |
正式的部署过程 |
正式的部署过程 | |
在真实项目中,你会找到表中所列这三种主调的无数种变奏;无论如何,表中已经列举了它们的共性。开发商业系统的项目往往受益于高度迭代的开发法,这种方法的“计划、需求、架构”活动与“构建、系统测试、质量保证”活动交
织在一起。性命攸关的系统往往要求采用更加序列式的方法——“需求稳定”是确保“超高等级的可靠性”的必备条件之一。
Iterative Approaches’ Effect on Prerequisites
迭代开发法对前期准备的影响
有些作者断言,使用迭代技术的项目基本无须关注前期准备,但这种观点是错的。迭代方法往往能够减少“前期准备不足”造成的负面影响,但是它不能完全消除此影响。让我们看一下表3-3所示的例子,这两个项目都没有关注前期准备工作。第一个项目按序列式开发法运作,并且仅仅依赖于测试来发现缺陷。第二个项目则按迭代方式运作,并且随着项目的进展不断找出错误。第一个方法将绝大部分缺陷修正工作推迟到项目快结束的时候进行,使得成本较高(正如表3-1所述)。而迭代式开发法在项目进行过程中一点点地吸收消化返工,这样使得总体成本较低。这个表中的数据和下一个表中的数据仅仅是为了举例说明,但是这两种通常的开发方法的成本的这种相对关系,是受到本章前面部分提到的那些研究支持的。
表3-3 跳过前期准备对于采用序列式开发法的项目和迭代式开发法的项目的(不同)影响
|
方法1:序列式开发法 方法2:迭代式开发法 (无前期准备) (无前期准备) |
|
项目完成度 工作成本 返工成本 工作成本 返工成本 |
|
20% $100 000 $0 $100 000 $75 000 40% $100 000 $0 $100 000 $75 000 60% $100 000 $0 $100 000 $75 000 80% $100 000 $0 $100 000 $75 000 100% $100 000 $0 $100 000 $75 000 |
|
项目末期返工 $0 $500 000 $0 $0 |
|
总计 $500 000 $500 000 $500 000 $375 000 |
|
总数之和 $1 000 000 $875 000 |
那些简化或取消了前期准备工作的迭代型项目与采用同样做法的序列型项目相比,有两点不同。首先,平均的缺陷修正成本低一些,因为发现缺陷的时间往往更接近引入该缺陷的时间。然而,每一轮迭代仍然要到最后才能检测到缺陷,为了修正这些缺陷,需要对软件的某些部分进行重新设计、重新编码并重新测试——这使得修正缺陷的成本高于实际需要。
其次,使用迭代式开发法,成本将会在整个项目过程当中分次支付,而不会聚集到项目末尾一次性支付。整个项目尘埃落定之后,实际的总成本是相似的,但是看起来却没有那么高,因为开发费用是在整个项目进行过程中分期支付的,而不是在项目最后一次性结账。
如表3-4所示,无论你使用的是迭代式开发法还是序列式开发法,只要进行前期准备,就可以减少成本。“迭代式开发法通常是更好的选择”这一观点有很多的理由支持。但是忽略前期准备的迭代式开发法,最终明显会比“密切关注前期准备工作的序列式开发法”付出更高的代价。
表3-4 关注前期准备工作对于采用序列式开发法的项目和迭代式开发法的项目的影响
|
方法3:序列式开发法 方法4:迭代式开发法 (有前期准备) (有前期准备) |
|
项目完成度 工作成本 返工成本 工作成本 返工成本 |
|
20% $100 000 $20 000 $100 000 $10 000 40% $100 000 $20 000 $100 000 $10 000 60% $100 000 $20 000 $100 000 $10 000 80% $100 000 $20 000 $100 000 $10 000 100% $100 000 $20 000 $100 000 $10 000 |
|
项目末期返工 $0 $0 $0 $0 |
|
总计 $500 000 $100 000 $500 000 $50 000 |
|
总数之和 $600 000 $550 000 |
正如表3-4所暗示的,绝大多数的项目都不会完全使用序列式开发法或者完全使用迭代式开发法。预先详细说明100%的需求和设计是不切实际的,不过对绝大多数项目来说,“尽早把哪些是最关键的需求要素和架构要素确定下来”是很有价值的。
一条很有用的经验规则是,计划好预先对大约80%的需求做出详细说明,并给“稍后再进行详细说明的额外需求”分配一定的时间。然后在项目进行过程中,实施系统化的变更控制措施——只接受那些最有价值的新需求。另一种替代方案是,预先只对最重要的20%的需求做出详细说明,并且计划以小幅增量开发软件的剩余部分,随着项目的进行,对额外的需求和设计做出详细说明。图3-2和图3-3展示了这两种不同的方法。

图3-2 对于绝大部分的项目(即便是高度序列化的项目)来说,各种活动会在一定程度上有所重叠

图3-3 对于其他的项目,各种活动在项目开发期间会重叠起来。成功“构建”的关键之一,就是理解前期准备工作的完成程度,并据此调整你的开发方法
Choosing Between Iterative and Sequential Approaches
在序列式开发法和迭代式开发法之间做出选择
前期准备预先要满足哪些条件,会随表3-2所列出的不同项目种类、项目的正式程度、技术环境、员工能力以及项目的商业目标变化而变化。你可能因为下列原因选择一个更加序列化的方法。
■ 需求相当稳定。
■ 设计直截了当,而且理解透彻。
■ 开发团队对于这一应用领域非常熟悉。
■ 项目的风险很小。
■ “长期可预测性”很重要。
■ 后期改变需求、设计和编码的代价很可能较昂贵。
你可能因为下列原因选择一个更加迭代(as-you-go,走着瞧)的方法。
■ 需求并没有被理解透彻,或者出于其他理由你认为它是不稳定的。
■ 设计很复杂,或者有挑战性,或者两者兼具。
■ 开发团队对于这一应用领域不熟悉。
■ 项目包含许多风险。
■ “长期可预测性”不重要。
■ 后期改变需求、设计和编码的代价很可能较低。
事实上,在软件开发中,适用迭代式开发法的情况比适用序列式开发法的情况多得多。你可以使前期准备适应某个特定项目,办法是调整其正式程度和完备程度,到你觉得合适为止。大型项目和小型项目有不同的开发方法(也称为正式项目和非正式项目有不同的开发方法),关于这点具体讨论请阅读第27章。
你应该首先确定哪些前期准备活动适合你的项目。有些项目在前期准备上面花的时间太少了,结果使得在构建活动中遇到大量不必要的反复修改,同时阻碍了项目的稳步前进。有些项目则预先做了太多的事情,固执地坚持原有的需求和计划,后来事实证明这些需求和计划是无效的,这同样阻止了构建活动的顺利进展。
既然你已经研究过表3-2,并且确定了何种前期准备适合你的项目,那么本章接下来将要讨论的是:如何判断每一项特定的前期准备工作是否到位。







