第1章 软件工程学概述
一、软件危机
1.软件危机的介绍
(1)概念
软件危机是指在计算机软件的开发和维护过程中所遇到的一系列严重问题。这些问题绝不仅仅是不能运行的软件才具有的,实际上,几乎所有的软件都不同程度地存在这些问题。软件危机包含两方面的问题:
①如何开发软件,以满足对软件日益增长的需求;
②如何维护数量不断膨胀的已有软件。
(2)典型表现
①对软件开发成本和进度的估计不准确。实际成本比估计成本有可能高出一个数量级,实际进度比预期进度拖延几个月甚至几年的现象并不罕见。这种现象降低了软件开发组织的信誉。而为了赶进度和节约成本所采取的一些权宜之计又往往损害了软件产品的质量,从而不可避免地会引起用户的不满。
②用户对“已完成的”软件系统不满意的现象经常发生。软件开发人员常常在对用户要求只有模糊的了解,甚至对所要解决的问题还没有确切认识的情况下,就匆忙着手编写程序。软件开发人员和用户之间的信息交流往往很不充分,“闭门造车”必然导致最终的产品不符合用户的实际需要。
③软件产品的质量往往靠不住。软件可靠性和质量保证的确切的定量概念刚刚出现不久,软件质量保证技术(审查、复审、程序正确性证明和测试)还没有坚持不懈地应用到软件开发的全过程中,这些都导致软件产品发生质量问题。
④软件常常是不可维护的。很多程序中的错误是非常难改正的,实际上不可能使这些程序适应新的硬件环境,也不能根据用户的需要在原有程序中增加一些新的功能。“可重用的软件”还是一个没有完全做到的、正在努力追求的目标,人们仍然在重复开发类似的或基本类似的软件。
⑤软件通常没有适当的文档资料。计算机软件不仅仅是程序,还应该有一整套文档资料。
⑥软件成本在计算机系统总成本中所占的比例逐年上升。由于微电子学技术的进步和生产自动化程度的不断提高,硬件成本逐年下降,然而软件开发需要大量人力,软件成本随着通货膨胀以及软件规模和数量的不断扩大而持续上升。
⑦软件开发跟不上计算机应用迅速普及深入的趋势。软件产品“供不应求”的现象使人类不能充分利用现代计算机硬件提供的巨大潜力。
2.产生软件危机的原因
(1)客观原因
①软件是计算机系统中的逻辑部件而不是物理部件。
②软件规模庞大,而且程序复杂性将随着程序规模的增加而呈指数上升。
(2)主观原因
①对软件开发和维护有不少糊涂观念,采用了错误的方法和技术。
②存在与软件开发和维护有关的许多错误认识和做法。
③对用户要求没有完整准确的认识就匆忙着手编写程序。
④一个软件从定义、开发、使用和维护,直到最终被废弃,要经历一个漫长的时期。
⑤一个软件产品必须由一个完整的配置组成,主要包括程序、文档和数据等成分。
⑥在软件开发的不同阶段进行修改需要付出的代价是很不相同的。
⑦轻视维护是一个最大的错误。
3.消除软件危机的途径
(1)应该对计算机软件有一个正确的认识。应该彻底消除在计算机系统早期发展阶段形成的“软件就是程序”的错误观念。软件是程序、数据及相关文档的完整集合。其中,程序是能够完成预定功能和性能的可执行的指令序列;数据是使程序能够适当地处理信息的数据结构;文档是开发、使用和维护程序所需要的图文资料。
(2)应该充分认识到软件开发是一种组织良好、管理严密、各类人员协同配合、共同完成的工程项目。必须充分吸取和借鉴人类长期以来从事各种工程项目所积累的行之有效的原理、概念、技术和方法,特别要吸取几十年来人类从事计算机硬件研究和开发的经验教训。
(3)应该推广使用在实践中总结出来的开发软件的成功的技术和方法,并且研究探索更好更有效的技术和方法,尽快消除在计算机系统早期发展阶段形成的一些错误概念和做法。
(4)应该开发和使用更好的软件工具。在软件开发的每个阶段都有许多繁琐重复的工作需要做,在适当的软件工具辅助下,开发人员可以把这类工作做得既快又好。
二、软件工程
1.软件工程的介绍
(1)概念
软件工程是是从管理和技术两方面研究如何更好地开发和维护计算机软件的一门新兴学科。采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它,这就是软件工程。
(2)产生
为了更有效地开发与维护软件,软件工作者在20世纪60年代后期开始认真研究消除软件危机的途径,从而逐渐形成了一门新兴的工程学科—计算机软件工程学(通常简称为“软件工程”)。
(3)本质特征
①软件工程关注于大型程序的构造
把一个人在较短时间内写出的程序称为小型程序,而把多人合作用时半年以上才写出的程序称为大型程序。传统的程序设计技术和工具是支持小型程序设计的,不能简单地把这些技术和工具用于开发大型程序。
②软件工程的中心课题是控制复杂性
软件所解决的问题通常十分复杂,不得不把问题分解,使得分解出的每个部分是可理解的,而且各部分之间保持简单的通信关系。用这种方法并不能降低问题的整体复杂性,但是却可使它变成可以管理的。
注意:许多软件的复杂性主要不是由问题的内在复杂性造成的,而是由必须处理的大量细节造成的。
③软件经常变化
绝大多数软件都模拟了现实世界的某一部分。现实世界在不断变化,软件为了不被很快淘汰,必须随着所模拟的现实世界一起变化。因此,在软件系统交付使用后仍然需要耗费成本,而且在开发过程中必须考虑软件将来可能发生的变化。
④开发软件的效率非常重要
社会对新应用系统的需求超过了人力资源所能提供的限度,软件供不应求的现象日益严重。软件工程的一个重要课题就是,寻求开发与维护软件的更好更有效的方法和工具。
⑤和谐地合作是开发软件的关键
软件处理的问题十分庞大,必须多人协同工作才能解决这类问题。为了有效地合作,必须明确地规定每个人的责任和相互通信的方法,每个人还必须严格地按规定行事,纪律是成功地完成软件开发项目的一个关键。
⑥软件必须有效地支持它的用户
开发软件的目的是支持用户的工作。软件提供的功能应该能有效地协助用户完成他们的工作。有效地支持用户意味着必须仔细地研究用户,以确定适当的功能需求、可用性要求及其他质量要求。还意味着软件开发不仅应该提交软件产品,而且应该写出用户手册和培训材料。
⑦软件工程领域由具有一种文化背景的人替具有另一种文化背景的人创造产品
软件工程师是软件设计、软件体系结构、测试或统一建模语言等方面的专家,但他们不仅缺乏应用领域和文化领域的实际知识,还缺乏该领域的文化知识,这是软件开发项目出现问题的常见原因。
2.软件工程的基本原理
(1)七条基本原理
①用分阶段的生命周期计划严格管理
在软件开发与维护的漫长的生命周期中,需要完成许多性质各异的工作。应该把软件生命周期划分成若干个阶段,并相应地制定出切实可行的计划,然后严格按照计划对软件的开发与维护工作进行管理。不同层次的管理人员都必须严格按照计划各尽其职地管理软件开发与维护工作,绝不能受客户或上级人员的影响而擅自背离预定计划。
②坚持进行阶段评审
由于大部分错误都是在编码之前造成的,并且错误发现与改正的越晚,所需付出的代价也越高,所以软件的质量保证工作不能等到编码阶段结束之后再进行。因此,在每个阶段都进行严格的评审,以便尽早发现在软件开发过程中所犯的错误,是一条必须遵循的重要原则。
③实行严格的产品控制
当改变需求时,为了保持软件各个配置成分的一致性,必须实行严格的产品控制,其中主要是实行基准配置管理。所谓基准配置又称为基线配置,它们是经过阶段评审后的软件配置成分。
基准配置管理也称为变动控制,主要包括以下两个方面。
a.一切有关修改软件的建议,特别是涉及对基准配置的修改建议,都必须按照严格的规程进行评审,获得批准以后才能实施修改。
b.绝对不能谁想修改软件(包括尚在开发过程中的软件),就随意进行修改。
④采用现代程序设计技术
采用先进的技术不仅可以提高软件开发和维护的效率,而且可以提高软件产品的质量。
⑤结果应能清楚地审查
软件产品不同于一般的物理产品,它是看不见摸不着的逻辑产品。软件开发人员的工作进展情况可见性差,难以准确度量。为了提高软件开发过程的可见性,更好地进行管理,应该根据软件开发项目的总目标及完成期限,规定开发组织的责任和产品标准,从而使得所得到的结果能够清楚地审查。
⑥开发小组的人员应该少而精
软件开发小组的组成人员的素质应该好,而人数则不宜过多。素质高的人员的开发效率比素质低的人员的开发效率可能高几倍至几十倍,而且素质高的人员所开发的软件中的错误明显少于素质低的人员所开发的软件中的错误。
⑦承认不断改进软件工程实践的必要性
为了保证软件开发与维护的过程能赶上时代前进的步伐,能跟上技术的不断进步,不仅要积极主动地采纳新的软件技术,而且要注意不断总结经验。例如,收集进度和资源耗费数据,收集出错类型和问题报告数据等。
(2)意义
这七条原理是确保软件产品质量和开发效率的原理的最小集合。这七条原理是互相独立的,而且是缺一不可的最小集合,然而这七条原理又是相当完备的。
3.软件工程方法学
(1)概念
软件工程包括技术和管理两方面的内容,是技术与管理紧密结合所形成的工程学科。所谓管理就是通过计划、组织和控制等一系列活动,合理地配置和使用各种资源,以达到既定目标的过程。通常把软件生命周期全过程中使用的一整套技术方法的集合称为方法学,也称为范型。目前使用得最广泛的软件工程方法学,分别是传统方法学和面向对象方法学。
(2)三要素
软件工程方法学包括3个要素:方法、工具和过程。
①方法:是完成软件开发的各项任务的技术方法,回答“怎样做”的问题。
②工具:是为运用方法而提供的自动的或半自动的软件工程支撑环境。
③过程:是为了获得高质量的软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤。
(3)传统方法学(生命周期方法学或结构化范型)
①定义
采用结构化技术(结构化分析、结构化设计和结构化实现)来完成软件开发的各项任务,并使用适当的软件工具或软件工程环境来支持结构化技术的运用。
②开发步骤
开发软件时,传统方法学把软件生命周期的全过程依次划分为若干个阶段,然后顺序地完成每个阶段的任务。具体如下。
a.从对问题的抽象逻辑分析开始,一个阶段一个阶段地顺序进行开发。
b.前一个阶段任务的完成是开始进行后一个阶段工作的前提和基础,而后一阶段任务的完成通常是使前一阶段提出的解法更进一步具体化,加了更多的实现细节。
c.每一个阶段的开始和结束都有严格标准,对于任何两个相邻的阶段而言,前一阶段的结束标准就是后一阶段的开始标准。
d.在每一个阶段结束之前都必须进行正式严格的技术审查和管理复审,从技术和管理两个方面对这个阶段的开发成果进行检查,通过之后这个阶段才算结束;如果没通过检查,则必须进行必要的返工,而且返工后还要再经过审查。审查的一条主要标准就是每个阶段都应该交出和所开发的软件完全一致的高质量的文档资料,从而保证在软件开发工程结束时有一个完整准确的软件配置交付使用。
③优点
a.把软件生命周期划分成若干个阶段,每个阶段的任务相对独立,而且比较简单,便于不同人员分工协作,从而降低了整个软件开发工程的困难程度;
b.在软件生命周期的每个阶段都采用科学的管理技术和良好的技术方法,且在每个阶段结束之前都进行严格的审查,使得软件开发工程的全过程以一种有条不紊的方式进行,保证了软件的质量,特别是提高了软件的可维护性;
c.采用生命周期方法学可以大大提高软件开发的成功率,软件开发的生产率也能明显提高。
④缺点
a.当软件规模庞大,或者对软件的需求是模糊的或会随时间变化而变化的时候,传统方法学开发软件往往不成功。
b.结构化范型技术要么面向行为,要么面向数据,没有既面向数据又面向行为的结构化技术,而软件系统本质上是信息处理系统。离开了操作便无法更改数据,而脱离了数据的操作是毫无意义的。数据和对数据的处理原本是密切相关的,把数据和操作人为地分离成两个独立的部分,自然会增加软件开发与维护的难度。
(4)面向对象方法学
①定义
面向对象方法把数据和行为看成是同等重要的,它是一种以数据为主线,把数据和对数据的操作紧密地结合起来的方法。
②基本原则
面向对象方法学的出发点和基本原则,是尽量模拟人类习惯的思维方式,使开发软件的方法与过程尽可能接近人类认识世界、解决问题的方法与过程,从而使描述问题的问题空间与实现解法的解空间在结构上尽可能一致。
③要点
a.把对象作为融合了数据及在数据上的操作行为的统一的软件构件
面向对象程序是由对象组成的,程序中任何元素都是对象,复杂对象由比较简单的对象组合而成,用对象分解取代了传统方法的功能分解。
b.把所有对象都划分成类
每个类都定义了一组数据和一组操作,类是对具有相同数据和相同操作的一组相似对象的定义。数据用于表示对象的静态属性,是对象的状态信息,而施加于数据之上的操作用于实现对象的动态行为。
c.继承性
按照父类与子类的关系,把若干个相关类组成一个层次结构的系统。下层派生类自动拥有上层基类中定义的数据和操作,这种现象称为继承。
d.对象彼此间仅能通过发送消息互相联系
对象是数据处理的主体,必须向它发消息请求它执行它的某个操作以处理它的数据,不能从外界直接对它的数据进行处理,即对象的所有私有信息都被封装在该对象内,不能从外界直接访问,这就是通常所说的封装性。
④与传统方法学的对比
a.传统方法学强调自顶向下顺序地完成软件开发的各阶段任务。
b.用面向对象方法学开发软件的过程,是一个主动地多次反复迭代的演化过程。面向对象方法在概念和表示方法上的一致性,保证了在各项开发活动之间的平滑(即无缝)过渡。
⑤优点
a.降低了软件产品的复杂性;
b.提高了软件的可理解性;
c.简化了软件的开发和维护工作;
d.提高了软件的可重用性。
三、软件生命周期
软件生命周期由软件定义、软件开发和运行维护(也称为软件维护)3个时期组成,每个时期又进一步划分成若干个阶段。
1.组成
(1)软件定义
软件定义时期通常进一步划分成3个阶段,即问题定义、可行性研究和需求分析。这个时期的总任务是:
①确定软件开发工程必须完成的总目标;
②确定工程的可行性;
③导出实现工程目标应该采用的策略及系统必须完成的功能;
④估计完成该项工程需要的资源和成本,并且制定工程进度表。
(2)软件开发
通常由下述4个阶段组成:总体设计,详细设计,编码和单元测试,综合测试。其中前两个阶段又称为系统设计,后两个阶段又称为系统实现。
(3)运行和维护
软件运行和维护的主要任务是使软件持久地满足用户的需要。出现下述三种情况的时候需要进行维护:
①当软件在使用过程中发现错误时应该加以改正;
②当环境改变时应该修改软件以适应新的环境;
③当用户有新要求时应该及时改进软件以满足用户的新需要。
2.软件生命周期各阶段的基本任务。
(1)问题定义
问题定义阶段必须回答的关键问题是:“要解决的问题是什么?”。通过对客户的访问调查,系统分析员扼要地写出关于问题性质、工程目标和工程规模的书面报告,经过讨论和必要的修改之后这份报告应该得到客户的确认。
(2)可行性研究
可行性研究阶段要回答的关键问题是:“对于上一个阶段所确定的问题有行得通的解决办法吗?”为了回答这个问题,系统分析员需要进行一次大大压缩和简化了的系统分析和设计过程。可行性研究阶段的任务是研究问题的范围,探索这个问题是否值得去解,是否有可行的解决办法。可行性研究的结果是客户作出是否继续进行这项工程的决定的重要依据,只有投资可能取得较大效益的那些工程项目才值得继续进行下去。
(3)需求分析
需求分析阶段的任务是准确地确定“为了解决这个问题,目标系统必须做什么”,主要是确定目标系统必须具备哪些功能。系统分析员必须和用户密切配合,充分交流信息,以得出经过用户确认的系统逻辑模型。用数据流图、数据字典和简要的算法表示系统的逻辑模型。这个阶段的一项重要任务,是用正式文档准确地记录对目标系统的需求,这份文档通常称为软件需求规格说明书(SRS)。
(4)总体设计(概要设计)
总体设计阶段必须回答的关键问题是:“应该怎样实现目标系统?”主要是设计出实现目标系统的几种可能的方案。软件工程师应该用适当的表达工具描述每种方案,分析每种方案,推荐一个最佳方案并制定出详细计划。另一项主要任务就是设计程序的体系结构,即确定程序由哪些模块组成以及模块间的关系。
(5)详细设计(模块设计)
详细设计阶段的任务就是把设计方案具体化,也就是回答:“应该怎样具体地实现这个系统呢?”这个阶段的任务是设计出程序的详细规格说明。在这个阶段将详细地设计每个模块,确定实现模块功能所需要的具体算法和数据结构。
(6)编码和单元测试
编码和单元测试阶段的关键任务是写出正确的、容易理解的、容易维护的程序模块。程序员把详细设计的结果翻译成用选定的高级编程语言书写的程序,编写出的每一个模块,并对编写好的各个模块进行测试。
(7)综合测试
综合测试阶段的关键任务是通过各种类型的测试使软件达到预定的要求。最基本的测试是集成测试和验收测试。
a.集成测试是根据设计的软件结构,把经过单元测试检验的模块按某种选定的策略装配起来,在装配过程中对程序进行必要的测试。
b.验收测试则是按照软件需求规格说明书的规定,由用户对目标系统进行验收。
通过对软件测试结果的分析可以预测软件的可靠性;根据对软件可靠性的要求,也可以决定测试和调试过程什么时候可以结束。应该用正式的文档资料把测试计划、详细测试方案以及实际测试结果保存下来,作为软件配置的一个组成部分。
(8)软件维护
维护阶段的关键任务是通过各种必要的维护活动使系统持久地满足用户的需要。实质上维护过程是经历了一次压缩和简化了的软件定义和开发的全过程。每一项维护活动都应该准确地记录下来,作为正式的文档资料加以保存。
通常有四类维护活动:
①改正性维护,即诊断和改正在使用过程中发现的软件错误;
②适应性维护,即修改软件以适应环境的变化;
③完善性维护,即根据用户的要求改进或扩充软件使它更完善;
④预防性维护,即修改软件,为将来的维护活动预先做准备。
四、软件过程
1.概念
(1)定义
软件过程是为了获得高质量软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤。软件过程描述为了开发出客户需要的软件,什么人(who)、在什么时候(when)、做什么事(what)以及怎样(how)做这些事以实现某一个特定的具体目标。在完成开发任务时必须进行一些开发活动,并且使用适当的资源,在过程结束时将把输入转化为输出。
(2)构成
科学、有效的软件过程应该定义一组适合于所承担的项目特点的任务集合。一个任务集合包括一组软件工程任务、里程碑和应该交付的产品。
(3)表示
使用生命周期模型简洁地描述软件过程。生命周期模型(过程模型)规定了把生命周期划分成哪些阶段及各个阶段的执行顺序。
2.典型软件过程模型
(1)瀑布模型
在20世纪80年代之前,瀑布模型一直是唯一被广泛采用的生命周期模型,现在它仍然是软件工程中应用得最广泛的过程模型。传统软件工程方法学的软件过程,基本上可以用瀑布模型来描述。
①传统的瀑布模型
a.定义
传统软件工程方法学的软件过程,基本上可以用瀑布模型来描述,如图1-1所示为传统的瀑布模型。
图1-1 传统的瀑布模型
b.特点
第一,阶段间具有顺序性和依赖性
必须等前一阶段的工作完成之后,才能开始后一阶段的工作;前一阶段的输出文档是后一阶段的输入文档,即只有前一阶段的输出文档正确,后一阶段的工作才能获得正确的结果。
第二,推迟实现的观点
瀑布模型在编码之前设置了系统分析与系统设计的各个阶段,分析与设计阶段的基本任务规定,在这两个阶段主要考虑目标系统的逻辑模型,不涉及软件的物理实现。清楚地区分逻辑设计与物理设计,尽可能推迟程序的物理实现,是按照瀑布模型开发软件的一条重要的指导思想。
第三,质量保证的观点
为了保证所开发的软件的质量,在瀑布模型的每个阶段都必须完成规定的文档,没有交出合格的文档就是没有完成该阶段的任务。完整、准确的合格文档不仅是软件开发时期各类人员之间相互通信的媒介,也是运行时期对软件进行维护的重要依据。越是早期阶段犯下的错误,暴露出来的时间就越晚,排除故障改正错误所需付出的代价也越高。因此,及时审查,是保证软件质量、降低软件成本的重要措施。每个阶段结束前都要对所完成的文档进行评审,以便尽早发现问题,改正错误。
②实际的瀑布模型
a.定义
在设计阶段可能发现规格说明文档中的错误,而设计上的缺陷或错误可能在实现过程中显现出来,在综合测试阶段将发现需求分析、设计或编码阶段的许多错误。因此,实际的瀑布模型是带“反馈环”的,如图1-2所示(图中实线箭头表示开发过程,虚线箭头表示维护过程)。当在后面阶段发现前面阶段的错误时,需要沿图中左侧的反馈线返回前面的阶段,修正前面阶段的产品之后再回来继续完成后面阶段的任务。
图1-2 实际的瀑布模型
b.优点
第一,可强迫开发人员采用规范的方法;
第二,严格地规定了每个阶段必须提交的文档;
第三,要求每个阶段交出的所有产品都必须经过质量保证小组的仔细验证;
第四,对文档的约束,使软件维护变得容易一些,且能降低软件预算。
c.缺点
“瀑布模型是由文档驱动的”是它的一个主要缺点。在可运行的软件产品交付给用户之前,用户只能通过文档来了解产品是什么样的。但是,仅仅通过写在纸上的静态的规格说明,很难全面正确地认识动态的软件产品。由于瀑布模型几乎完全依赖于书面的规格说明,很可能导致最终开发出的软件产品不能真正满足用户的需要。
(2)快速原型模型
①定义
快速原型是快速建立起来的可以在计算机上运行的程序,它所能完成的功能往往是最终产品能完成的功能的一个子集。如图1-3所示(图中实线箭头表示开发过程,虚线箭头表示维护过程)。快速原型的本质是“快速”。UNIX Shell、超文本、第四代语言(4GL)都是广泛使用的快速原型语言。
图1-3 快速原型模型
②原理
快速原型模型的第一步是快速建立一个能反映用户主要需求的原型系统,让用户通过实践来了解目标系统的概貌。通常,用户试用原型系统之后会提出许多修改意见,开发人员按照用户的意见快速地修改原型系统,然后再次请用户试用,一旦用户认为这个原型系统确实能做他们所需要的工作,开发人员便可据此书写规格说明文档,根据这份文档开发出的软件便可以满足用户的真实需求。
③优点
快速原型模型是不带反馈环的,这正是这种过程模型的主要优点,即软件产品的开发基本上是线性顺序进行的。能基本上做到线性顺序开发的主要原因如下:
a.原型系统已经通过与用户交互而得到验证,产生的规格说明文档正确地描述了用户需求。因此,在开发过程的后续阶段不会因为发现了规格说明文档的错误而进行较大的返工。
b.开发人员通过建立原型系统已经学到了许多东西。因此,在设计和编码阶段发生错误的可能性也比较小,减少了在后续阶段需要改正前面阶段所犯错误的可能性。
(3)增量模型
①原理
增量模型也称为渐增模型,如图1-4所示。使用增量模型开发软件时,把软件产品作为一系列的增量构件来设计、编码、集成和测试。每个构件由多个相互作用的模块构成,并且能够完成特定的功能。使用增量模型时,第一个增量构件往往实现软件的基本需求,提供最核心的功能。把软件产品分解成增量构件时,应该使构件的规模适中。分解时唯一必须遵守的约束条件是:当把新构件集成到现有软件中时,所形成的产品必须是可测试的。
图1-4 增量模型
②原理
增量模型分批地逐步向用户提交产品,整个软件产品被分解成许多个增量构件,开发人员一个构件接一个构件地向用户提交产品。从第一个构件交付之日起,用户就能做一些有用的工作。
③优点
a.能在较短时间内向用户提交可完成部分工作的产品。
b.逐步增加产品功能可以使用户有较充裕的时间学习和适应新产品,减少了一个全新的软件可能给客户组织带来的冲击。
④技术难点
a.在把每个新的增量构件集成到现有软件体系结构中时,必须不破坏原来已经开发出的产品。必须把软件的体系结构设计得便于按这种方式进行扩充,向现有产品中加入新构件的过程必须简单、方便,即软件体系结构必须是开放的。
b.增量模型本身是自相矛盾的。它一方面要求开发人员把软件看作一个整体,另一方面又要求开发人员把软件看作构件序列,每个构件本质上都独立于另一个构件。
⑤风险更大的增量模型
图1-5是一种风险更大的增量模型。用这种方式开发软件,不同的构件将并行地构建,因此有可能加快工程进度。但是,这种方法将有构件无法集成到一起的风险,除非密切地监控整个开发过程,否则整个工程可能毁于一旦。
图1-5 风险更大的增量模型
(4)螺旋模型
①基本思想
螺旋模型的基本思想是,使用原型及其他方法来尽量降低风险。可以把它看作在每个阶段之前都增加了风险分析过程的快速原型模型,如图1-6所示。
图1-6 简化的螺旋模型
②原理
完整的螺旋模型如图1-7所示。图中带箭头的点划线的长度代表当前累计的开发费用,螺旋线的角度值代表开发进度。螺旋线每个周期对应于一个开发阶段。每个阶段开始时的任务是,确定该阶段的目标、为完成这些目标选择方案及设定这些方案的约束条件。接下来的任务是,从风险角度分析上一步的工作结果,用建造原型的方法排除各种潜在的风险。如果风险不能排除,则停止开发工作或大幅度地削减项目规模。如果成功地排除了所有风险,则启动下一个开发步骤。最后是评价该阶段的工作成果并计划下一个阶段的工作。
图1-7 完整的螺旋模型
③应用
螺旋模型主要适用于内部开发的大规模软件项目。如果进行风险分析的费用接近整个项目的经费预算,则风险分析是不可行的。事实上,项目越大,风险也越大,因此,进行风险分析的必要性也越大。此外,只有内部开发的项目,才能在风险过大时方便地中止项目。
④优点
a.对可选方案和约束条件的强调有利于已有软件的重用,有助于把软件质量作为软件开发的一个重要目标;
b.减少了过多测试(浪费资金)或测试不足(产品故障多)所带来的风险;
c.在螺旋模型中维护只是模型的另一个周期,在维护和开发之间并没有本质区别。
⑤缺点
螺旋模型是风险驱动的。因此,除非软件开发人员具有丰富的风险评估经验和这方面的专门知识,否则将出现真正的风险,即当项目实际上正在走向灾难时,开发人员可能还认为一切正常。
(5)喷泉模型
①面向对象方法学
这种方法在开发的早期阶段定义了一系列面向问题的对象,并且在整个开发过程中不断充实和扩充这些对象。分析阶段得到的对象模型也适用于设计阶段和实现阶段。整个开发过程都是“无缝”连接的,这就很容易实现各个开发步骤的多次反复迭代,达到认识的逐步深化。每次反复都会增加或明确一些目标系统的性质,但不是对先前工作结果的本质性改动,减少了不一致性,降低了出错的可能性。
②原理
图1-8所示的喷泉模型,是典型的面向对象的软件过程模型之一。“喷泉”这个词体现了面向对象软件开发过程迭代和无缝的特性。图中代表不同阶段的圆圈相互重叠,表示两个活动之间存在交迭;而面向对象方法在概念和表示方法上的一致性,保证了在各项开发活动之间的无缝过渡。图中在一个阶段内的向下箭头代表该阶段内的迭代(或求精)。图中较小的圆圈代表维护,圆圈较小象征着采用了面向对象范型之后维护时间缩短了。
图1-8 喷泉模型
③要求
为避免使用喷泉模型开发软件时开发过程过分无序,应该把一个线性过程作为总目标。同时也应该记住,面向对象范型本身要求经常对开发活动进行迭代或求精。
(6)Rational统一过程
Rational统一过程(Rational Unified Process,RUP)是由Rational软件公司推出的一种完整而且完美的软件过程。
①最佳实践
RUP总结了经过多年商业化验证的6条最有效的软件开发经验,这些经验被称为“最佳实践”,具体如下。
a.迭代式开发
第一,产生原因
在大型复杂软件的开发过程中客户的需求会经常改变,因此需要有一种能够通过一系列细化、若干个渐近的反复过程而得出有效解决方案的迭代方法。
第二,优点
i.迭代式开发允许在每次迭代过程中需求都可以有变化,这种开发方法通过一系列细化来加深对问题的理解,因此能更容易地容纳需求的变更。
ii.采用迭代式开发方法,每个迭代过程以完成可执行版本结束,这不仅使最终用户可以不断地介入和提出反馈意见,而且开发人员也因随时有一个可交付的版本而提高了士气。
b.管理需求
在开发软件的过程中,客户需求将不断发生变化,因此,确定系统的需求是一个连续的过程。RUP描述了如何提取、组织系统的功能性需求和约束条件并把它们文档化。使用用例和脚本是捕获功能性需求的有效方法,RUP采用用例分析来捕获需求,并由它们驱动设计和实现。
c.使用基于构件的体系结构
所谓构件就是功能清晰的模块或子系统。系统可以由已经存在的、由第三方开发商提供的构件组成,因此构件使软件重用成为可能。RUP提供了使用现有的或新开发的构件定义体系结构的系统化方法,从而有助于降低软件开发的复杂性,提高软件重用率。
d.可视化建模
模型是为了理解事物而对事物作出的一种抽象,是对事物的一种无歧义的书面描述。RUP在开发过程中建立起软件系统的可视化模型,可以帮助人们提高管理软件复杂性的能力。
e.验证软件质量
某些软件不受用户欢迎的一个重要原因,是其质量低下,在软件投入运行后再去查找和修改出现的问题,比在开发的早期阶段就进行这项工作需要花费更多的人力和时间。在Rational统一过程中,软件质量评估不再是事后型的或由单独小组进行的孤立活动,而是内建在贯穿于整个开发过程的、由全体成员参与的所有活动中。
f.控制软件变更
在变更是不可避免的环境中,必须具有管理变更的能力,才能确保每个修改都是可接受的而且能被跟踪的。RUP描述了如何控制、跟踪和监控修改,以确保迭代开发的成功。
②RUP软件开发生命周期
RUP软件开发生命周期是一个二维的生命周期模型,如图1-9所示。图中纵轴代表核心工作流,横轴代表时间。
图1-9 RUP软件开发生命周期
③核心工作流
RUP中有九个核心工作流,前三个为核心过程工作流程,后三个为核心支持工作流程。
a.业务建模:了解使用目标系统的机构及其商业运作,评估系统对使用它的机构的影响。
b.需求:捕获客户的需求,并且使开发人员和用户达成对需求描述的共识。
c.分析与设计:把需求分析的结果转化成分析模型与设计模型。
d.实现:把设计模型转换成实现结果,形式化地定义代码结构,用构件实现类和对象,对开发出的构件进行单元测试;把不同实现人员开发出的模块集成为可执行的系统。。
e.测试:检查各个子系统的交互与集成,验证所有需求是否都被正确地实现了,识别、确认缺陷并确保在软件部署之前消除缺陷。
f.部署:成功地生成目标系统的可运行的版本,并把软件移交给最终用户。
g.配置与变更管理:跟踪并维护在软件开发过程中产生的所有制品的完整性和一致性。
h.项目管理:提供项目管理框架,为软件开发项目制定计划、人员配备、执行和监控等方面的实用准则,并为风险管理提供框架。
i.环境:向软件开发机构提供软件开发环境,包括过程管理和工具支持。
④工作阶段
RUP把软件生命周期划分成4个连续的阶段。每个阶段都有明确的目标,并且定义了用来评估是否达到这些目标的里程碑。每个阶段的目标通过一次或多次迭代来完成。在每个阶段结束之前都有一个里程碑评估该阶段的工作成果。如果未能通过评估,则决策者应该作出决定,要么中止该项目,要么重做该阶段的工作。这4个阶段的工作目标如下。
a.初始阶段:建立业务模型,定义最终产品视图,并且确定项目的范围。
b.精化阶段:设计并确定系统的体系结构,制定项目计划,确定资源需求。
c.构建阶段:开发出所有构件和应用程序,把它们集成为客户需要的产品,并且详尽地测试所有功能。
d.移交阶段:把开发出的产品提交给用户使用。
⑤RUP迭代式开发
a.定义
RUP强调采用迭代和渐增的方式来开发软件,整个项目开发过程由多个迭代过程组成。在每次迭代中只考虑系统的一部分需求,针对这部分需求进行分析、设计、实现、测试和部署等工作,每次迭代都是在系统已完成部分的基础上进行的,每次给系统增加些N的功能,如此循环往复地进行下去,直至完成最终项目。
b.特点
第一,每个阶段又进一步细分为一次或多次迭代过程。项目经理根据当前迭代所处的阶段以及上一次迭代的结果,对核心工作流程中的活动进行适当的裁剪,以完成一次具体的迭代过程。在每个生命周期中都一次次地轮流访问这些核心工作流程。
第二,在不同的迭代过程中是以不同的工作重点和强度对这些核心工作流程进行访问的。
⑥RUP适用性
目前,全球已经有上千家软件公司在使用Rational统一过程。这些公司分布在不同的应用领域,开发着或大或小的项目,这表明了RUP的多功能性和广泛适用性。
(7)敏捷过程
敏捷过程能够较好地适应商业竞争环境下对小型项目提出的有限资源和有限开发时间的约束。敏捷软件开发宣言如下:
①个体和交互胜过过程和工具
优秀的团队成员是软件开发项目获得成功的最重要因素;当然,不好的过程和工具也会使最优秀的团队成员无法发挥作用。团队成员的合作、沟通以及交互能力要比单纯的软件编程能力更重要。
②可以工作的软件胜过面面俱到的文档
软件开发的主要目标是向用户提供可以工作的软件而不是文档;但是,完全没有文档的软件也是一种灾难。开发人员应该把主要精力放在创建可工作的软件上面,仅当迫切需要并且具有重大意义时,才进行文档编制工作,而且所编制的内部文档应该尽量简明扼要、主题突出。
③客户合作胜过合同谈判
客户通常不可能做到一次性地把他们的需求完整准确地表述在合同中。能够满足客户不断变化的需求的切实可行的途径是,开发团队与客户密切协作,因此,能指导开发团队与客户协同工作的合同才是最好的合同。
④响应变化胜过遵循计划
软件开发过程中总会有变化,这是客观存在的现实。一个软件过程必须反映现实,因此,软件过程应该有足够的能力及时响应变化。
根据敏捷开发宣言提出的软件过程统称为敏捷过程,其中最重要的是极限编程。
(8)极限编程
①概念
极限编程(XP)是敏捷过程中最富盛名的一个,其名称中“极限”,二字的含义是指把好的开发实践运用到极致。目前,极限编程已经成为一种典型的开发方法,广泛应用于需求模糊且经常改变的场合。
②极限编程的有效实践
a.客户作为开发团队的成员
必须至少有一名客户代表在项目的整个开发周期中与开发人员在一起紧密地配合工作,客户代表负责确定需求、回答开发人员的问题并且设计功能验收测试方案。
b.使用用户素材
所谓用户素材就是正在进行的关于需求的谈话内容的助记符。根据用户素材可以合理地安排实现该项需求的时间。
c.短交付周期
每两周完成一次的迭代过程实现了用户的一些需求,交付出目标系统的一个可工作的版本。通过向有关的用户演示迭代生成的系统,获得他们的反馈意见。
d.验收测试
通过执行由客户指定的验收测试来捕获用户素材的细节。
e.结对编程
结对编程就是由两名开发人员在同一台计算机上共同编写解决同一个问题的程序代码,通常一个人编码,另一个人对代码进行审查与测试,以保证代码的正确性与可读性。结对编程是加强开发人员相互沟通与评审的一种方式。
f.测试驱动开发
极限编程强调“测试先行”。在编码之前应该首先设计好测试方案,然后再编程,直至所有测试都获得通过之后才可以结束工作。
g.集体所有
极限编程强调程序代码属于整个开发小组集体所有,小组每个成员都有更改代码的权利,每个成员都对全部代码的质量负责。
h.持续集成
极限编程主张在一天之内多次集成系统,而且随着需求的变更,应该不断地进行回归测试。
i.可持续的开发速度
开发人员以能够长期维持的速度努力工作。XP规定开发人员每周工作时间不超过40小时,连续加班不可以超过两周,以免降低生产率。
j.开放的工作空间
XP项目的全体参与者(开发人员、客户等)一起在一个开放的场所中工作,项目组成员在这个场所中自由地交流和讨论。
k.及时调整计划
计划应该是灵活的、循序渐进的。制定出项目计划之后,必须根据项目进展情况及时进行调整,没有一成不变的计划。
l.简单的设计
开发人员应该使设计与计划要在本次迭代过程中完成的用户素材完全匹配,设计时不需要考虑未来的用户素材。在一次次的迭代过程中,项目组成员不断变更系统设计,使之相对于正在实现的用户素材而言始终处于最优状态。
m.重构
所谓代码重构就是在不改变系统行为的前提下,重新调整和优化系统的内部结构,以降低复杂性、消除冗余、增加灵活性和提高性能。
注意:在开发过程中不要过分依赖重构,特别是不能轻视设计,对于大中型系统而言,如果推迟设计或者干脆不做设计,将造成一场灾难。
n.使用隐喻
可以将隐喻看作把整个系统联系在一起的全局视图,它描述系统如何运作,以及用何种方式把新功能加入到系统中。
③极限编程的整体开发过程
图1-10描述了极限编程的整体开发过程。具体开发过程如下:
a.项目组针对客户代表提出的“用户故事”进行讨论,提出隐喻,在此项活动中可能需要对体系结构提出相关技术难点的试探性解决方案;
b.项目组在隐喻和用户故事的基础上,根据客户设定的优先级制订交付计划;
c.开始多个迭代过程,在迭代期内产生的新用户故事不在本次迭代内解决,以保证本次开发过程不受干扰。开发出的新版本软件通过验收测试之后交付用户使用。
图1-10 XP项目的整体开发过程
④极限编程的迭代过程
a.项目组根据交付计划和项目速率,选择需要优先完成的用户故事或待消除的差错,将其分解成可在1~2天内完成的任务,制订出本次迭代计划;
b.通过每天举行一次的“站立会议”,解决遇到的问题,调整迭代计划;
c.进行代码共享式的开发工作。所开发出的新功能必须100%通过单元测试,并且立即进行集成,得到的新的可运行版本由客户代表进行验收测试。
d.开发人员与客户代表交流此次代码共享式编程的情况,讨论所发现的问题,提出新的用户故事,算出新的项目速率,并把相关的信息提交给站立会议。
图1-11描述了极限编程的迭代开发过程。
图1-11 XP迭代开发过程
⑤特点
a.极限编程为代表的敏捷过程,具有对变化和不确定性的更快速、更敏捷的反应特性;
b.在快速的同时仍然能够保持可持续的开发速度。
(9)微软过程
①微软过程遵循的基本准则
a.项目计划应该兼顾未来的不确定因素。
b.用有效的风险管理来减少不确定因素的影响。
c.经常生成并快速地测试软件的过渡版本,从而提高产品的稳定性和可预测性。
d.采用快速循环、递进的开发过程。
e.用创造性的工作来平衡产品特性和产品成本。
f.项目进度表应该具有较高稳定性和权威性。
g.使用小型项目组并发地完成开发工作。
h.在项目早期把软件配置项基线化,项目后期则冻结产品。
i.使用原型验证概念,对项目进行早期论证。
j.把零缺陷作为追求的目标。
k.里程碑评审会的目的是改进工作,切忌相互指责。
②微软软件生命周期
微软过程把软件生命周期划分成五个阶段,图1-12描绘了生命周期的阶段及每个阶段的主要里程碑。
图1-12 微软软件生命周期阶段划分和主要里程碑
a.规划阶段
这个阶段的主要任务是,根据从市场上获得的用户情况和客户需求等信息,在调查、统计和分析的基础上,完成下述工作:
第一,确定产品目标。
第二,获取竞争对手的信息。
第三,完成对客户和市场的调研分析。
第四,确定新版本产品应该具备的主要特性。
第六,确定相对于前一版本而言,新版本应该解决的问题和需要增加的功能。
b.设计阶段
当项目团队已经确定了70%以上的产品需求时,开发工作就可以进入设计阶段了,主要工作内容如下:
第一,根据产品目标编写系统的特性规格说明书。
第二,从系统高层开始着手进行系统设计。
第三,划分出系统中的子系统,给出各个子系统和各个构件的规格说明。
第四,根据产品特性规格说明书制订产品开发计划。
c.开发阶段
开发阶段的主要任务是,完成产品中所有构件的开发工作。一些开发工作可能会持续到稳定阶段,以便在那时对测试中发现的问题作出修改。
d.稳定阶段
稳定阶段的主要任务是对产品进行测试和调试,以确保已经正确地实现了整个解决方案,产品可以发布了。这个阶段测试的重点是,产品在真实环境下的使用和操作。
e.发布阶段
发布阶段的主要任务是发布产品或解决方案,稳定发布过程,并把项目移交到运营和支持人员手中,以获得最终用户对项目的认可。
③微软过程模型
a.定义
图1-13描绘了微软过程的生命周期模型。微软过程的每一个生命周期发布一个递进的软件版本,各个生命周期持续、快速地迭代循环。
图1-13 微软过程的生命周期模型
b.特点
第一,微软过程综合了Rational统一过程和敏捷过程的许多优点,是对众多成功项目的开发经验的正确总结;
第二,微软过程也有某些不足之处,例如,对方法、工具和产品等方面的论述不如RUP和敏捷过程全面,人们对它的某些准则本身也有不同意见。在开发软件的实践中,应该把微软过程与RUP和敏捷过程结合起来,取长补短.针对不同项目的具体情况进行定制。