本节将介绍软件生命周期与软件开发模型。
软件工程是一门年轻的学科。“软件工程”这个概念最早是在1968年召开的一个当时被称为“软件危机”的会议上提出的。自1968年以来,我们在该领域已经取得了长足的进步。软件工程的发展已经极大地完善了我们的软件,使我们对软件开发活动也有了更深的理解。
那么什么是软件危机呢?自从强大的第三代计算机硬件问世以后,许多原来难以实现的计算机应用成为现实,同时对软件系统的需求数量和复杂度要求变得更高。而当时的软件开发技术无法满足这一日益增长的需求,引发了软件危机。它主要表现为。
● 软件开发生产率提高的速度,远远跟不上计算机迅速普及的趋势。软件需求的增长得不到满足,软件产品“供不应求”的现象使人类无法充分利用现代计算机硬件提供的巨大潜力。
● 软件成本在计算机系统总成本中所占的比例逐年上升。
● 不能正确估计软件开发产品的成本和进度,致使实际开发成本高出预算很多,而且超出预期的开发时间要求。
● 软件开发人员和用户之间的信息交流往往很不充分,用户对“已完成的”软件系统不满意的现象经常发生。
● 软件产品的质量不易保证。
● 软件产品常常是不可维护的。
● 软件产品的重用性差,同样的软件多次重复开发。
● 软件通常没有适当的文档资料。
软件危机的产生一方面是由于软件开发本身的复杂性,另一方面是与当时的手工作坊式软件开发模式有密切关系。
开发一个具有一定规模和复杂性的软件系统和编写一个简单的程序大不一样。其间的差别,借用Booch的比喻,如同建造一座大厦和搭一个狗窝的差别。大型的、复杂的软件系统的开发是一项工程,必须按工程学的方法组织软件的生产与管理,必须经过计划、分析、设计、编程、测试、维护等一系列的软件生命周期阶段。这是人们从软件危机中获得的最重要的教益,这一认识促使了软件工程学的诞生。
软件工程学就是研究如何有效地组织和管理软件开发的工程学科。IEEE在1983年将软件工程定义为:软件工程是开发、运行、维护和修复软件的系统方法。
著名的软件工程专家Boehm于1983年提出了软件工程的7条基本原理:
● 用分阶段的生命周期计划严格管理;
● 坚持进行阶段评审;
● 实行严格的产品控制;
● 采用现代程序设计技术;
● 结果应能清楚地审查;
● 开发小组的人员应该少而精;
● 承认不断改进软件工程实践的必要性。
软件工程方法学包含三个要素,方法、工具和过程。方法是指完成软件开发的各项任务的技术方法;工具是指为运用方法而提供的软件工程支撑环境;过程是指为获得高质量的软件所需要完成的一系列任务的框架。
近30年来,影响力最大、使用最广泛的软件工程方法学是结构化方法学和面向对象的方法学。
软件生命周期(Software Life Cycle)是人们在研究软件开发过程时所发现的一种规律性的事实。如同人的一生要经历婴儿期、少年期、青年期、老年期直至死亡这样一个全过程一样,一个软件产品也要经历计划、分析、设计、编程、测试、维护直至被淘汰这样一个全过程。软件的这一全过程被称为软件生命周期。
目前,软件生命周期各阶段的划分尚不统一,有的分得粗些,有的分得细些,所包含的实际内容也不完全相同。
● 1970年,Boehm提出了如表4-1所示的软件生命周期模型。
表4-1 Boehm定义的软件生命周期模型
● 在1988年制订和公布的国家标准《GB8566-1988计算机软件开发规范》中将软件生命周期划分为如表4-2所示的8个阶段。
表4-2 GB8566定义的软件生命周期模型
● 在20世纪90年代初有了软件工程过程的概念之后,于1995年制订和公布的国家标准《GB/T8566-1995信息技术–软件生存期过程》定义了软件生命周期的7个主要过程,如表4-3所示。
表4-3 GB/T8566定义的软件生命周期模型
其中,“获取过程”和“供应过程”分别描述了软件的“获取者”(用户)和“供应者”(开发者)在开发之前的主要活动和任务。而“管理过程”和“支持过程”则贯穿于整个软件生命周期。
● 1995年国际标准化组织对软件生命周期过程做了调整,公布了新的国际标准《ISO/IEC 12207信息技术–软件生存期过程》。该标准全面、系统地阐述了软件生命周期的3组共17个过程活动和任务,如表4-4所示。
表4-4 ISO/IEC定义的软件生命周期模型
● 1999年,Rational软件公司的3位软件工程大师Ivar Jacobson、Grady Booch和James Rumbaugh联合编写了一部划时代的著作《统一软件开发过程》(The Unified Software Development Process),将他们多年研究所得的软件开发方法学融合在了一起。该书清楚地说明了支持整个软件生命周期的统一软件开发过程是一个用例驱动的、以架构为中心的、迭代与增量的开发过程。统一软件开发过程是在重复一系列组成软件生命周期的循环,每次循环都包括如下的四个阶段和五种工作流,分别如表4-5和表4-6所示。
表4-5 RUP定义的软件生命周期模型的四个阶段
表4-6 RUP定义的软件生命周期模型的五种工作流
尽管软件生命周期中各阶段的划分标准不统一,名称也不一致,但主要包括了计划、分析、设计、编程、测试和维护等阶段。本书主要介绍分析、设计、测试和维护阶段的工作。
为了指导软件的开发,可以用不同的方式将软件生命周期中的所有开发活动组织起来,从而形成了不同的软件开发模型。常见的开发模型有瀑布模型(waterfall model)、快速原型模型(rapid prototype model)、演化模型(evolutionary model)、增量模型(incremental model)、螺旋模型(spiral model)和喷泉模型(water fountain model)等。
瀑布模型严格遵循软件生命周期各阶段的固定顺序:计划、分析、设计、编程、测试和维护,上一阶段完成后才能进入到下一阶段,整个模型就像一个飞流直下的瀑布,如图4-1所示。
图4-1 瀑布模型示意图
瀑布模型有许多优点:可强迫开发人员采用规范的方法;严格规定了各阶段必须提交的文档;要求每个阶段结束后,都要进行严格的评审。
但瀑布模型过于理想化,而且缺乏灵活性,无法在开发过程中逐渐明确用户难以确切表达或一时难以想到的需求,直到软件开发完成之后才发现与用户需求有很大距离,此时必须付出高额的代价才能纠正这一偏差。
快速原型是指快速建立起来的可以在计算机上运行的程序,它所完成的功能往往是最终软件产品功能的一个子集。快速原型模型的第一步是快速建立一个能反映用户主要需求的软件原型,让用户在计算机上使用它,通过实际操作了解目标系统的概貌。开发人员按照用户提出的意见快速地修改原型系统,然后再次请用户试用……,一旦用户认为这个原型系统确实能够满足他们的需求,开发人员便可据此书写软件需求说明,并根据这份文档开发出可以满足用户真实需求的软件产品。
原型化方法基于这样一种客观事实:并非所有的需求在系统开发之前都能准确地说明和定义。因此,它不追求也不可能要求对需求的严格定义,而是采用了动态定义需求的方法。
具有广泛技能高水平的原型化人员是原型实施的重要保证。原型化人员应该是具有经验与才干、训练有素的专业人员。衡量原型化人员能力的重要标准是他是否能够从用户的模糊描述中快速获取实际的需求。
演化模型也是一种原型化开发方法,但与快速原型模型略有不同。在快速原型模型中,原型的用途是获知用户的真正需求,一旦需求确定了,原型即被抛弃。而演化模型的开发过程,则是从初始模型逐步演化为最终软件产品的渐进过程。也就是说,快速原型模型是一种“抛弃式”的原型化方法,而演化模型则是一种“渐进式”的原型化方法。
增量模型是第三种原型化开发方法,但它既非“抛弃式”的,也非“渐进式”的,而是“递增式”的。增量模型把软件产品划分为一系列的增量构件,分别进行设计、编程、集成和测试。每个构件由多个相互作用的模块构成,并且能够完成特定的功能。如何将一个完整软件产品分解成增量构件,因软件产品特点和开发人员的习惯而异,但使用增量模型的软件体系结构必须是开放的,加入新构件的过程必须简单方便,新的增量构件不得破坏已经开发出来的产品。其示意图如图4-2所示。
图4-2 增量模型示意图
螺旋模型综合了瀑布模型和演化模型的优点,还增加了风险分析。螺旋模型包含了4个方面的活动:制订计划、风险分析、实施工程、客户评估。这4项活动恰好可以放在一个直角坐标系的4个象限,而开发过程恰好像一条螺旋线。采用螺旋模型时,软件开发沿着螺旋线自内向外旋转,每转一圈都要对风险进行识别和分析,并采取相应的对策。螺旋线第一圈的开始点可能是一个概念项目。从第二圈开始,一个新产品开发项目开始了,新产品的演化沿着螺旋线进行若干次迭代,一直运转到软件生命期结束。其示意图如图4-3所示。
图4-3 螺旋模型示意图
喷泉模型主要用于描述面向对象的开发过程。喷泉一词体现了面向对象开发过程的迭代和无间隙特征。迭代意味着模型中的开发活动常常需要多次重复,每次重复都会增加或明确一些目标系统的性质,但却不是对先前工作结果的本质性改动。无间隙是指在开发活动(如分析、设计、编程)之间不存在明显的边界,而是允许各开发活动交叉、迭代地进行。
构件(Component,也称为组件)是一个具有可重用价值的、功能相对独立的软件单元。基于构件的软件开发(Component Based Software Development,CBSD)模型是利用模块化方法,将整个系统模块化,并在一定构件模型的支持下,复用构件库中的一个或多个软件构件,通过组合手段高效率、高质量地构造应用软件系统的过程。基于构件的开发模型融合了螺旋模型的许多特征,本质上是演化型的,开发过程是迭代的。基于构件的开发模型由软件的需求分析和定义、体系结构设计、构件库建立、应用软件构建、测试和发布5个阶段组成。采用基于构件的开发模型的软件过程如图4-4所示。
图4-4 采用基于构件的开发模型的软件过程
构件作为重要的软件技术和工具得到了极大的发展,这些新技术和工具有Microsoft的DCOM,Sun的EJB,OMG的CORBA等。基于构件的开发活动从标识候选构件开始,通过搜索已有构件库,确认所需要的构件是否已经存在,如果已经存在,就从构件库中提取出来复用;如果不存在,就采用面向对象方法开发它。在提取出来的构件通过语法和语义检查后,将这些构件通过胶合代码组装到一起实现系统,这个过程是迭代的。
基于构件的开发方法使得软件开发不再一切从头开始,开发的过程就是构件组装的过程,维护的过程就是构件升级、替换和扩充的过程,其优点是构件组装模型导致了软件的复用,提高了软件开发的效率;构件可由一方定义其规格说明,被另一方实现,然后供给第三方使用;构件组装模型允许多个项目同时开发,降低了费用,提高了可维护性,可实现分步提交软件产品。
缺点是由于采用自定义的组装结构标准,缺乏通用的组装结构标准,引入具有较大的风险;可重用性和软件高效性不易协调,需要精干的、有经验的分析人员和开发人员,一般的开发人员插不上手,客户的满意度低;过分依赖于构件,构件库的质量影响着产品质量。
快速应用开发(Rapid Application Development,RAD)模型是一个增量型的软件开发过程模型,强调极短的开发周期。RAD模型是瀑布模型的一个“高速”变种,通过大量使用可复用构件,采用基于构件的建造方法赢得快速开发。如果需求理解得好且约束了项目的范围,利用这种模型可以很快地创建出功能完善的“信息系统”。其流程从业务建模开始,随后是数据建模、过程建模、应用生成、测试及反复。采用RAD模型的软件过程如图4-5所示。
图4-5 采用RAD模型的开发过程
RAD模型各个活动期所要完成的任务如下。
● 业务建模:以什么信息驱动业务过程运作?要生成什么信息?谁生成它?信息流的去向是哪里?由谁处理?可以辅之以数据流图。
● 数据建模:为支持业务过程的数据流,找数据对象集合,定义数据对象属性,与其他数据对象的关系构成数据模型,可辅之以E-R图。
● 过程建模:使数据对象在信息流中完成各业务功能。创建过程以描述数据对象的增加、修改、删除、查找,即细化数据流图中的处理框。
● 应用程序生成:利用第四代语言(4GL)写出处理程序,重用已有构件或创建新的可重用构件,利用环境提供的工具自动生成并构造出整个应用系统。
● 测试与交付,由于大量重用,一般只做总体测试,但新创建的构件还是要测试的。
与瀑布模型相比,RAD模型不采用传统的第三代程序设计语言来创建软件,而是采用基于构件的开发方法,复用已有的程序结构(如果可能的话)或使用可复用构件,或创建可复用的构件(如果需要的话)。在所有情况下,均使用自动化工具辅助软件创造。很显然,加在一个RAD模型项目上的时间约束需要“一个可伸缩的范围”。如果一个业务能够被模块化使得其中每一个主要功能均可以在不到三个月的时间内完成,那么它就是RAD的一个候选者。每一个主要功能可由一个单独的RAD组来实现,最后再集成起来形成一个整体。
RAD模型通过大量使用可复用构件加快了开发速度,对信息系统的开发特别有效。但是像所有其他软件过程模型一样,RAD方法也有其缺陷:
● 并非所有应用都适合RAD。RAD模型对模块化要求比较高,如果有哪一项功能不能被模块化,那么建造RAD所需要的构件就会有问题;如果高性能是一个指标,且该指标必须通过调整接口使其适应系统构件才能赢得,RAD方法也有可能不能奏效。
● 开发者和客户必须在很短的时间完成一系列的需求分析,任何一方配合不当都会导致RAD项目失败。
● RAD只能用于信息系统开发,不适合技术风险很高的情况。当一个新应用要采用很多新技术或当新软件要求与已有的计算机程序有较高的互操作性时,这种情况就会发生。
RUP(Rational Unified Process)是一个统一的软件开发过程,是一个通用过程框架,可以应付种类广泛的软件系统、不同的应用领域、不同的组织类型、不同的性能水平和不同的项目规模。RUP是基于构件的,这意味着利用它开发的软件系统是由构件构成的,构件之间通过定义良好的接口相互联系。在准备软件系统所有蓝图的时候,RUP使用的是统一建模语言UML。
与其他软件过程相比,RUP具有3个显著的特点:用例驱动、以基本架构为中心、迭代和增量。
RUP中的软件过程在时间上被分解为4个顺序的阶段,分别是初始阶段、细化阶段、构建阶段和交付阶段。每个阶段结束时都要安排一次技术评审,以确定这个阶段的目标是否已经满足。如果评审结果令人满意,就可以允许项目进入下一个阶段。基于RUP的软件过程模型如图4-6所示。
图4-6 基于RUP的软件过程
从图4-6中可以看出:基于RUP的软件过程是一个迭代过程。通过初始、细化、构建和提交四个阶段就是一个开发周期,每次经过这4个阶段就会产生一代软件。除非产品退役,否则通过重复同样的四个阶段,产品将演化为下一代产品,但每一次的侧重点都将放在不同的阶段上。这些随后的过程称为演化过程。
在进度和工作量方面,所有阶段都各不相同。尽管不同的项目有很大的不同,但一个中等规模项目的典型初始开发周期应该预先考虑到工作量和进度间的分配,如表4-7所示。
表4-7 RUP各阶段的工作量和进度分配
对于演进周期,初始和细化阶段就小得多了。能够自动完成某些构建工作的工具将会缓解此现象,并使得构建阶段比初始阶段和细化阶段的总和还要小很多。
RUP的工作流程分为两部分:核心工作流程与核心支持工作流程。核心工作流程(在项目中的流程)包括业务需求建模、分析设计、实施、测试、部署;核心支持工作流程(在组织中的流程)包括环境、项目管理、配置与变更管理。
统一过程4个阶段的核心任务,以及需要提交的文档和模型分别如下。
(1)核心任务
● 明确地说明项目规模。这涉及了解环境及最重要的需求和约束,以便于可以得出最终产品的验收标准。
● 计划和准备商业理由。评估风险管理、人员配备、项目计划和成本/进度/收益率折中的备选方案。
● 综合考虑备选构架,评估设计和自制/外购/复用方面的折中,从而估算出成本、进度和资源。此处的目标在于通过对一些概念的证实来证明可行性。该证明可采用可模拟需求的模型形式或用于探索被认为高风险区域的初始原型。先期阶段的原型设计工作应该限制在确信解决方案可行就可以了。该解决方案在精化和构建阶段实现。
● 准备项目的环境,评估项目和组织,选择工具,决定流程中要改进的部分。
(2)需要提交的文档和模型(见表4-8)
表4-8 初始阶段需要提交的文档和模型
(1)核心任务
● 快速确定构架,确认构架并为构架建立基线。
● 根据此阶段获得的新信息改进前景,对推动构架和计划决策的最关键用例建立可靠的了解。
● 为构建阶段创建详细的迭代计划并为其建立基线。
● 改进开发案例,定位开发环境,包括流程和支持构建团队所需的工具和自动化支持。
● 改进构架并选择构件。评估潜在构件,充分了解自制/外购/复用决策,以便有把握地确定构建阶段的成本和进度。集成了所选构架构件,并按主要场景进行了评估。通过这些活动得到的经验有可能导致重新设计构架、考虑替代设计或重新考虑需求。
(2)需要提交的文档和模型(见表4-9)
表4-9 细化阶段需要提交的文档和模型
(1)核心任务
● 资源管理、控制和流程优化。
● 完成构件开发并根据已定义的评估标准进行测试。
● 根据前景的验收标准对产品发布版进行评估。
(2)需要提交的文档和模型(见表4-10)
表4-10 构建阶段需要提交的文档和模型
(续表)
(1)核心任务
● 执行部署计划。
● 对最终用户支持材料定稿。
● 在开发现场测试可交付产品。
● 制作产品发布版。
● 获得用户反馈。
● 基于反馈调整产品。
● 使最终用户可以使用产品。
(2)需要提交的文档和模型(见表4-11)
表4-11 提交阶段需要提交的文档和模型
请参看第12章《软件新技术简介》的极限编程部分。