3.1 软件生存周期模型
瀑布模型(waterfall model)是最早被广泛使用的软件生存周期模型。本节首先回顾瀑布模型,然后概述其他可选择的软件生存周期模型,这些模型用来克服瀑布模型的部分局限性,它们是:抛弃型原型生存周期模型(throwaway prototyping life cycle model),增量开发生存周期模型(incremental development life cycle model,也称为演化式原型evolutionary prototyping),螺旋模型(spiral model),以及统一软件开发过程(Unified Software Development Process)。
3.1.1 瀑布生存周期模型
从20世纪60年代以来,开发软件的成本逐步增长,同时制造和购买硬件的成本则急剧下降。进一步说,当前软件成本一般占据整个项目预算的百分之八十,然而在软件开发的早期,硬件则是最大的项目成本(Boehm 2006)。
在20世纪60年代,相关人员还没有明确理解与开发软件相关的一些问题。在60年代后期,人们才理解到存在软件危机这一问题。软件工程这个术语是指为了有效开发一个大型软件系统所需要的管理与技术方法、过程和工具。随着软件工程概念的不断推广与使用,人们已经使用软件生存周期模型开发了许多大规模的软件。图3-1展示了第一个被广泛使用的软件生存周期模型,通常指的是瀑布模型,它一般被看做是传统的或者“古典”的软件生存周期。瀑布模型是一个理想化的过程模型,它规定每一阶段完成后才能启动下一阶段,另外,一个项目在没有迭代和重复的情况下从一个阶段移动到下一个阶段。
3.1.2 瀑布模型的局限性
瀑布模型是对早期软件项目所使用的较为散乱的开发方法的一种重要改进,它已经被成功应用在许多项目中。然而,事实上,当在开发中检测到一些软件错误时,在生存周期的连续阶段中时常需要一些重复与迭代(见图3-2)。此外,对于一些软件开发项目而言,瀑布模型会呈现出以下显著问题:
软件需求作为软件开发项目中的一个关键因素,无法进行合适的测试,直至一个工作系统被开发出来并能演示给最终用户。事实上,好几个研究工作已经指出软件需求规约的错误通常在最后才被检测到(直至执行系统测试或验收测试才能被检测到),并且需要花费最大的代价对其进行纠正。
只有在生存周期的后期才能得到一个工作的系统。因此,直到系统几乎可以运行时,一个重要的设计或性能问题才有可能被发现,到那时通常已经太晚了,以至于无法采取有效的措施。
对于带有很大风险因素的软件开发项目来说——例如,由于那些无法清晰理解或预期会改变的需求所导致的风险——瀑布模型的变体或者其他替代模型已经被提出。
可以使用两种不同的软件原型方法来克服瀑布模型的一些局限:抛弃型原型和演化式原型。抛弃型原型有助于解决瀑布模型的第一个问题,这个问题在前面的列表中已被描述,演化式原型则有助于解决第二个问题。
3.1.3 抛弃型原型
抛弃型原型有助于阐明用户需求。该方法对从用户界面上获得反馈非常有用,并且能够应用于具有复杂用户界面的系统。
一个抛弃型原型能够在一个初步的需求规约被制定之后就被开发出来(图3-3)。通过让用户使用原型,可以得到许多通常难以得到的有价值的反馈。以这些反馈为基础,就可以准备制定一个修订的需求规约。后续的开发过程则延续了传统的软件生存周期。
针对详述交互式信息系统需求的问题,抛弃型原型(尤其是用户界面的原型)已经成为解决该问题的一种有效方案。Gomaa(1990)描述了如何使用抛弃型原型来阐明一个具有高度交互性的制造型应用软件的需求。该原型有助于克服存在于用户和开发者之间的沟通障碍这一最大的问题。
抛弃型原型也能被用于构造设计的实验性原型(图3-4)。这个原型能用于确定特定的算法是否逻辑正确,或者用于确定它们是否满足性能目标。
3.1.4 通过增量开发的演化式原型
演化式原型方法是增量开发的一种形式,在增量开发中,原型从几个中间步骤的可运行系统(图3-5)逐步演化为可交付系统。该方法可用于确定系统是否满足性能目标,并用于测试设计中所涵盖的关键构件。另外,通过将实现分布在一个较长的时间段内也降低了开发的风险。用例和基于场景的通信图能辅助选择每一次增量中的系统子集。
演化式原型方法的一个目标是得到早期运行的系统子集,随后在该子集上逐步构造。如果系统的第一个增量版本对一条从外部输入到外部输出的路径进行了完整的测试,那么使用增量式原型方式是有优势的。
Gomaa(1990)描述了通过增量开发的演化式原型的一个实例。开发者在一个实时的机器人控制系统(Gomaa 1986)中使用了这种方法,结果得到了一个系统的早期可运行版本,这极大鼓舞了开发团队和管理者的士气。同时,这种方法也带来了一系列的好处,包括验证系统的设计、确定特定的关键算法是否满足性能目标以及持续进行系统集成。
3.1.5 抛弃型原型和增量开发的结合
与传统的瀑布生存周期相比,使用增量开发的生存周期模型方法能够更早地得到一个以演化式原型为形式的工作系统。然而,开发这种类型的原型比开发一个抛弃型原型需要投入更多的关注,这是由于演化式原型形成了最终产品的基础;因此,从一开始就必须将软件质量考虑进来,而不能将其作为一种事后产物添加进来。特别是,需要仔细地设计软件体系结构并且指明所有的接口。
传统的瀑布生存周期模型因引入抛弃型原型或增量开发而受到严重的冲击。将抛弃型原型与增量开发这两种方法结合起来也是有可能的,如图3-6所示。其中,抛弃型原型被用来阐明需求。当理解需求并完成规约之后,就可开始进行一个增量开发生存周期。在后续的增量开发中,由于用户环境的变化,需求的进一步变更也可能是必要的。
3.1.6 螺旋模型
螺旋模型是一个风险驱动的过程模型,最初由Boehm(1988)开发用来解决软件生存周期早期过程模型中存在的已知问题,尤其是瀑布模型中的问题。螺旋模型旨在涵盖其他生存周期模型,例如瀑布模型、增量开发模型以及抛弃型原型模型。
在螺旋模型中,径向坐标代表成本,角坐标代表完成一次模型周期(循环)的成果。螺旋模型包含以下4个象限,如图3-7所示。
图3-7 螺旋过程模型
1)定义目标、候选方法和约束。此次循环的详细计划:确定目标以及用来实现目标的各种候选方法。
2)分析风险。对当前项目风险进行详细评估;为了减轻风险,计划待执行的活动。
3)开发产品。进行产品开发,例如需求分析、设计或者编码。
4)计划下一次循环。对此次循环的成果进行评估,并开始计划下一次循环。
螺旋模型的每一次循环都会迭代地经过这4个象限,尽管循环的次数是由特定项目决定的。每一个象限中的活动描述都要足够通用,使得它们能够被包含在任何一个循环中。
螺旋模型的目标是风险驱动,因此一个特定循环中的风险由“分析风险”这一象限决定。为了管理这些风险,需要额外地计划特定项目的活动来解决这些风险。例如,当风险分析指出软件需求并未被清晰理解时,就需要采用需求原型。这些特定项目的风险被称为过程驱动力(process driver)。对于任何过程驱动力而言,需要执行一个或多个特定项目的活动来管理这个风险(Boehm and Belz 1990)。
识别一个特定项目风险的例子是确定初始的软件需求没有被很好地理解。用来管理该风险所需执行的一个特定项目的活动是开发一个抛弃型原型,其目的是从用户处得到反馈从而有助于阐明系统的需求。
3.1.7 统一软件开发过程
按照Jacobson et al.(1999)中的描述,统一软件开发过程(USDP)是使用UML表示法的一种用例驱动的软件过程。USDP也被称为Rational统一过程(RUP)(Kroll and Kruchten 2003;Kruchten 2003)。USDP/RUP是一种流行的基于UML的软件开发过程。本节介绍PLUS方法如何用于USDP/RUP过程。
如图3-8所示,USDP包含5个核心工作流和4个阶段,同时USDP是可迭代的。制品(artifact)被定义为由一个过程生产、修改或使用的信息(Kruchten 2003)。工作流(workflow)被定义为生产可观测结果的一系列活动(Kruchtem 2003)。阶段(phase)被定义为两个里程碑之间的一段时间,在此过程中一组事先定义的开发目标得到了满足,完成了一些制品,同时做出了是否进入下一阶段的决定(Kruchten 2003)。通常,在一个阶段中存在超过一次的迭代;因此,USDP中一个阶段迭代与螺旋模型中的一次循环是相对应的。
图3-8 统一软件开发过程(Jacobson et al,THE UNIFIED SOFTWARE DEVELOPMENT PROCESS,Figure 1.5“Unified Software Development Process”p.11,?1999 Pearson Education,Inc.Reproduced by permission of Pearson Education,Inc.)
每一次循环历经所有的四个阶段,并且指明了每一个核心工作流中的开发工作。每一个工作流及其产物如下所述:
1)需求。需求工作流的产物是用例模型。
2)分析。分析工作流的产物是分析模型。
3)设计。设计工作流的产物是设计模型和部署模型。
4)实现。实现工作流的产物是实现模型。
5)测试。测试工作流的产物是测试模型。
与螺旋模型类似,USDP是一个风险驱动的过程。USDP生存周期阶段如下所述(Jacobson,Booch,and Rumbaugh 1990;Kruchten 2003):
1)初始。在初始阶段,制定出达到足够水平的初步想法,用以证明有能力进入细化阶段。
2)细化。在细化阶段,定义软件体系结构。
3)构造。在构造阶段,开发出能够发布给用户的软件产品。
4)交付。在交付阶段,软件被交付给用户。