138.软件工程_软件工程学概述

1.1  软件危机

  迄今为止,计算机系统已经经历了4个不同的发展阶段,但是,我们仍然没有彻底摆脱“软件危机”的困扰,软件已经成为限制计算机系统发展的瓶颈。
  为了更有效地开发与维护软件,在20世纪60年代后期软件工作者开始认真研究消除软件危机的途径,从而形成了一门新兴的工程学科——计算机软件工程学(通常简称为软件工程)。
  在20世纪60年代中期以前,是计算机系统发展的早期时代,通用硬件相当普遍,软件却是为每个具体应用而专门编写的。
  这时的软件通常是规模较小的程序,编写者和使用者往往是同一个(或同一组)人。这种个体化的软件环境,使得软件设计通常是在人们头脑中进行的一个隐含的过程,除了程序清单之外,没有其他文档资料保存下来。
  从20世纪60年代中期到70年代中期,是计算机系统发展的第二代时期,这个时期的一个重要特征是出现了“软件作坊”,广泛使用产品软件。
   “软件作坊”基本上仍然沿用早期形成的个体化软件开发方法。

  随着计算机应用的日益普及,软件数量急剧膨胀。要求软件:
    在程序运行时发现的错误必须设法改正;
    用户有了新的需求时必须相应地修改程序;
    硬件或操作系统更新时,通常需要修改程序以适应新的环境。
  上述种种软件维护工作,以令人吃惊的比例耗费资源。更严重的是,许多程序的个体化特性使得它们最终成为不可维护的。
   “软件危机”就这样开始出现了!1968年北大西洋公约组织的计算机科学家在联邦德国召开国际会议,讨论软件危机问题,在这次会议上正式提出并使用了“软件工程”这个名词,一门新兴的工程学科就此诞生了。

 

 

1.1.1  软件危机的介绍


软件危机:是指在计算机软件的开发和维护过程中所遇到的一系列严重问题。
    这些问题绝不仅仅是不能正常运行的软件才具有的,实际上,几乎所有软件都不同程度地存在这些问题。


概括地说,软件危机包含下述两方面的问题:
    如何开发软件,以满足对软件日益增长的需求;
    如何维护数量不断膨胀的已有软件。
   
具体地说,软件危机主要有以下一些典型表现。
(1)对软件开发成本和进度的估计常常很不准确。
          实际成本比估计成本有可能高出一个数量级,实际进度比预期进度拖延几个月甚至几年的现象并不罕见。这种现象降低了软件开发组织的信誉。而为了赶进度和节约成本所采取的一些权宜之计又往往损害了软件产品的质量,从而不可避免地会引起用户的不满。
(2) 用户对“已完成的”软件系统不满意的现象经常发生。
           软件开发人员常常在对用户要求只有模糊的了解,甚至对所要解决的问题还没有确切认识的情况下,就匆忙着手编写程序。由于和用户之间的信息交流不充分,必然导致最终的产品不符合用户的实际需要。
(3) 软件产品的质量往往靠不住。
    软件质量保证技术(审查、复审和测试)没有坚持不懈地应用到软件开发的全过程中,导致软件产品发生质量问题。
(4) 软件常常是不可维护的。
    很多程序中的错误是非常难改正的,无法使这些程序适应新的硬件环境,也不能根据用户的需要在原有程序中增加一些新的功能。
    “可重用的软件”还是一个没有完全做到的、正在努力追求的目标,人们仍然在重复开发类似的或基本类似的软件。
(5) 软件通常没有适当的文档资料。
    计算机软件不仅仅是程序,还应该有一整套文档资料。这些文档资料应该是在软件开发过程中产生出来的,而且应该是“最新式的”(即和程序代码完全一致的)。
    软件开发组织的管理人员可以使用这些文档资料作为“里程碑”,来管理和评价软件开发工程的进展状况;
    软件开发人员可以利用它们作为通信工具,在软件开发过程中准确地交流信息;
    对于软件维护人员而言,这些文档资料更是必不可少的。缺乏必要的文档资料或者文档资料不合格,必然给软件开发和维护带来许多严重的困难和问题。
(6) 软件成本在计算机系统总成本中所占的比例逐年上升。
    由于微电子学技术的进步和生产自动化程度不断提高,硬件成本逐年下降,然而软件开发需要大量人力,软件成本随着通货膨胀以及软件规模和数量的不断扩大而持续上升。美国在1985年软件成本大约已占计算机系统总成本的90%。
(7) 软件开发生产率提高的速度,远远跟不上计算机应用迅速普及深入的趋势,软件产品“供不应求” 。

 

1.1.2  产生软件危机的原因

在软件开发和维护的过程中存在这么多严重问题,
一方面与软件本身的特点有关,
一方面和软件开发与维护的方法不正确有关。

管理和控制软件开发过程相当困难。
    软件不同于硬件,缺乏“可见性”,在写出程序代码并在计算机上试运行之前,软件开发过程的进展情况较难衡量,软件的质量也较难评价。


软件较难维护
    软件在运行过程中不会因为使用时间过长而被“用坏”,运行中发现的错误 ,很可能是在开发时期引入的在测试阶段没能检测出来的错误,需要改正或修改原来的设计,使得软件较难维护。


软件不同于一般程序,其显著特点是规模庞大,而且,程序的复杂性随着程序规模的增加呈指数上升。
    为了在预定时间内开发出规模庞大的软件,必须由许多人分工合作,然而,如何保证每个人完成的工作合在一起确实能构成一个高质量的大型软件系统,是一个极端复杂困难的问题,不仅涉及许多技术问题,更重要的是必须有严格而科学的管理。

软件专业人员对软件开发和维护的错误的认识和作法。
    软件本身独有的特点确实给开发和维护带来一些客观困难,但是人们在开发和使用计算机系统的长期实践中,也确实积累和总结出了许多成功的经验。
    如果坚持不懈地使用正确的方法,许多困难是完全可以克服的。
    但是,目前相当多的软件专业人员对软件开发和维护还有不少糊涂观念,在实践过程中或多或少地采用了错误的方法和技术,这是出现软件危机的主要原因。


这些错误认识和作法的形成,可以归因于在计算机系统发展的早期阶段软件开发的个体化特点。
错误的认识和作法主要表现为忽视软件需求分析的重要性,认为软件开发就是写程序并设法使之运行,轻视软件维护等。


 对用户要求没有完整准确的认识就匆忙着手编写程序是许多软件开发工程失败的主要原因之一。
    只有用户才真正了解他们自己的需要,但是许多用户在开始时并不能准确具体地叙述他们的需要,软件开发人员需要做大量深入细致的调查研究工作,反复多次地和用户交流信息,才能真正全面、准确、具体地了解用户的要求。急于求成,仓促上阵,对用户要求没有正确认识就匆忙着手编写程序,最终必然失败。
    事实上,越早开始写程序,完成它所需要用的时间往往越长。

 

 


    一个软件从定义、开发、使用和维护,直到最终被废弃,要经历一个漫长的时期。通常把软件经历的这个漫长的时期称为生命周期


    软件开发最初的工作应是问题定义,也就是确定要求解决的问题是什么;


    然后要进行可行性研究,决定该问题是否存在一个可行的解决办法;


    接下来应该进行需求分析,也就是深入具体地了解用户的要求,在所要开发的系统(目标系统)必须做什么这个问题上和用户取得完全一致的看法。

    经过上述软件定义时期的准备工作才能进入开发时期
    在开发时期首先需要对软件进行设计(分为概要设计详细设计两个阶段),然后才能进入编写程序的阶段,程序编写完之后还必须经过大量的测试工作(需要的工作量通常占软件开发全部工作量的40%~50%)才能最终交付使用。
    所以,编写程序只是软件开发过程中的一个阶段,而且在典型的软件开发工程中,编写程序所需的工作量只占软件开发全部工作量的10%~20%。
    程序只是完整的软件产品的一个组成部分,在软件生命周期的每个阶段都要得出最终产品的一个或几个组成部分(这些组成部分通常以文档资料的形式存在)。
    因此,一个软件产品必须由一个完整的配置组成,软件配置主要包括程序、文档和数据等成分。必须清除只重视程序而忽视软件配置其余成分的糊涂观念。
   

 


  作好软件定义时期的工作,是降低软件成本提高软件质量的关键。在软件开发的不同阶段进行修改需要付出的代价是很不相同的。
早期引入变动,涉及的面较少,因而代价也比较低;
  在开发的中期,软件配置的许多成分已经完成,引入一个变动要对所有已完成的配置成分都做相应的修改,不仅工作量大,而且逻辑上也更复杂,因此付出的代价剧增;
  在软件“已经完成”时再引入变动,当然需要付出更高的代价。根据美国一些软件公司的统计资料,在后期引入一个变动比在早期引入相同变动所需付出的代价高2~3个数量级。图1.1定性地描绘了在不同时期引入一个变动需要付出的代价的变化趋势。

通过上面的论述不难认识到,轻视维护是一个最大的错误。
许多软件产品的使用寿命长达10年甚至20年,在这样漫长的时期中
  必须改正使用过程中发现的每一个潜伏的错误;
  当环境变化时(例如硬件或系统软件更新换代)还必须相应地修改软件以适应新的环境;
  经常改进或扩充原来的软件以满足用户不断变化的需要。
所有这些改动都属于维护工作,而且是在软件已经完成之后进行的。因此维护是极端艰巨复杂的工作,需要花费很大代价。
统计数据表明,实际上用于软件维护的费用占软件总费用的55%~70%。软件工程学的一个重要目标就是提高软件的可维护性,减少软件维护的代价。

1.1.3  消除软件危机的途径

  为了消除软件危机,首先应该对计算机软件有一个正确的认识。
    应该彻底消除在计算机系统早期发展阶段形成的“软件就是程序”的错误观念。
    一个软件必须由一个完整的配置组成,事实上,软件是程序、数据及相关文档的完整集合。其中,
程序:是能够完成预定功能和性能的可执行的指令序列;
数据:是使程序能够适当地处理信息的数据结构;
文档:是开发、使用和维护程序所需要的图文资料。


1983年IEEE为软件下的定义是:
    计算机程序、方法、规则、相关的文档资料以及在计算机上运行程序时所必需的数据。
    虽然表面上看来在这个定义中列出了软件的5个配置成分,但是,方法和规则通常是在文档中说明并在程序中实现的。
    更重要的是,必须充分认识到软件开发不是某种个体劳动的神秘技巧,而应该是一种组织良好、管理严密、各类人员协同配合、共同完成的工程项目。

  应该推广使用在实践中总结出来的开发软件的成功的技术和方法,并且研究探索更好更有效的技术和方法,尽快消除在计算机系统早期发展阶段形成的一些错误概念和做法。
  应该开发和使用更好的软件工具。
在软件开发的每个阶段都有许多繁琐重复的工作需要做,在适当的软件工具辅助下,开发人员可以把这类工作做得既快又好。
如果把各个阶段使用的软件工具有机地集合成一个整体,支持软件开发的全过程,则称为软件工程支撑环境。
总之,为了解决软件危机,既要有技术措施(方法和工具),又要有必要的组织管理措施。
软件工程正是从管理和技术两方面研究如何更好地开发和维护计算机软件的一门新兴学科。

 

 

1.2  软件工程

1.2.1  软件工程的介绍

概括地说,
软件工程:是指导计算机软件开发和维护的一门工程学科。
    采用工程的概念、原理、技术和方法来开发与维护软件,把经过时间考验而证明正确的管理技术和当前能够得到的最好的技术方法结合起来,以经济地开发出高质量的软件并有效地维护它,这就是软件工程。


人们曾经给软件工程下过许多定义,下面给出两个典型的定义。
  1968年在第一届NATO会议上曾经给出了软件工程的一个早期定义:“软件工程就是为了经济地获得可靠的且能在实际机器上有效地运行的软件,而建立和使用完善的工程原理。”
     这个定义不仅指出了软件工程的目标是经济地开发出高质量的软件,而且强调了软件工程是一门工程学科,它应该建立并使用完善的工程原理。
  1993年IEEE进一步给出了一个更全面更具体的定义:“软件工程是: ①把系统的、规范的、可度量的途径应用于软件开发、运行和维护过程,也就是把工程应用于软件; ②研究①中提到的途径。”



虽然软件工程的不同定义使用了不同词句,强调的重点也有差异,但是,人们普遍认为软件工程具有下述的本质特性。
1. 软件工程关注于大型程序的构造
     “大”与“小”的分界线并不十分清晰。通常把一个人在较短时间内写出的程序称为小型程序,而把多人合作用时半年以上才写出的程序称为大型程序。传统的程序设计技术和工具是支持小型程序设计的,不能简单地把这些技术和工具用于开发大型程序。
    事实上,在此处使用术语“程序”并不十分恰当,现在的软件开发项目通常构造出包含若干个相关程序的“系统”。

2. 软件工程的中心课题是控制复杂性
    通常,软件所解决的问题十分复杂,以致不能把问题作为一个整体通盘考虑。
    人们不得不把问题分解,使得分解出的每个部分是可理解的,而且各部分之间保持简单的通信关系。  
    用这种方法并不能降低问题的整体复杂性,但是却可使它变成可以管理的。
    注意,许多软件的复杂性主要不是由问题的内在复杂性造成的,而是由必须处理的大量细节造成的。

3. 软件经常变化
    绝大多数软件都模拟了现实世界的某一部分。现实世界在不断变化,软件为了不被很快淘汰,必须随着所模拟的现实世界一起变化。因此,在软件系统交付使用后仍然需要耗费成本,而且在开发过程中必须考虑软件将来可能的变化。


4. 开发软件的效率非常重要
    目前,社会对新应用系统的需求超过了人力资源所能提供的限度,软件供不应求的现象日益严重。因此,软件工程的一个重要课题就是,寻求开发与维护软件的更好更有效的方法和工具。

5. 和谐地合作是开发软件的关键
    软件处理的问题十分庞大,必须多人协同工作才能解决这类问题。
    为了有效地合作,必须明确地规定每个人的责任和相互通信的方法。为了迫使大家遵守规定,应该运用标准和规程。通常,可以用工具来支持这些标准和规程。
   总之,纪律是成功地完成软件开发项目的一个关键。

6. 软件必须有效地支持它的用户
    软件提供的功能应该能有效地协助用户完成他们的工作。因此,仅仅用正确的方法构造系统还不够,还必须构造出正确的系统。
    有效地支持用户意味着必须仔细地研究用户,以确定适当的功能需求、可用性要求及其他质量要求(例如:可靠性、响应时间等)。
   有效地支持用户还意味着,软件开发不仅应该提交软件产品,而且应该写出用户手册和培训材料,此外,还必须注意建立使用新系统的环境。


7. 在软件工程领域中是由具有一种文化背景的人替具有另一种文化背景的人创造产品。
    软件工程师是诸如Java程序设计、软件体系结构、测试或统一建模语言(UML)等方面的专家,他们通常并不是图书馆管理、航空控制或银行事务等领域的专家,但是他们却不得不为这些领域开发应用系统。
    缺乏应用领域的相关知识,是软件开发项目出现问题的常见原因。

 

 


    软件工程的基本原理共7条,
    这7条原理互相独立,其中任意6条原理的组合都不能代替另一条原理,因此,它们是缺一不可的最小集合;
    这7条原理又是相当完备的,人们虽然不能用数学方法严格证明它们是一个完备的集合,但是,可以证明在此之前已经提出的100多条软件工程原理都可以由这7条原理的任意组合蕴含或派生。

1. 用分阶段的生命周期计划严格管理
    经统计发现,在不成功的软件项目中有一半左右是由于计划不周造成的,可见把建立完善的计划作为第一条基本原理是吸取了前人的教训而提出来的。
    在软件开发与维护的漫长的生命周期中,需要完成许多性质各异的工作。这条基本原理意味着,应该把软件生命周期划分成若干个阶段,并相应地制定出切实可行的计划,然后严格按照计划对软件的开发与维护工作进行管理。
    不同层次的管理人员都必须严格按照计划各尽其职地管理软件开发与维护工作,绝不能受客户或上级人员的影响而擅自背离预定计划。

2. 坚持进行阶段评审
    软件的质量保证工作不能等到编码阶段结束之后再进行。理由:  
    第一,大部分错误是在编码之前造成的,例如,根据Boehm等人的统计,设计错误占软件错误的63%,编码错误仅占37%;
    第二,错误发现与改正得越晚,所需付出的代价也越高。因此,在每个阶段都进行严格的评审,以便尽早发现在软件开发过程中所犯的错误,是一条必须遵循的重要原则。

3. 实行严格的产品控制
    在软件开发过程中改变需求是难免的,只能依靠科学的产品控制技术来顺应这种要求。当改变需求时,为了保持软件各个配置成分的一致性,必须实行严格的产品控制,其中主要是实行基准配置管理。
    所谓基准配置又称为基线配置,它们是经过阶段评审后的软件配置成分。基准配置管理也称为变动控制:一切有关修改软件的建议,特别是涉及到对基准配置的修改建议,都必须按照严格的规程进行评审,获得批准以后才能实施修改。绝对不能谁想修改软件,就随意进行修改。


4. 采用现代程序设计技术
    研究各种新的程序设计技术,并进一步研究各种先进的软件开发与维护技术。
    实践表明,采用先进的技术不仅可以提高软件开发和维护的效率,而且可以提高软件产品的质量。

5. 结果应能清楚地审查
    软件产品是看不见摸不着的逻辑产品。软件开发人员(或开发小组)的工作进展情况可见性差,难以准确度量,从而使得软件产品的开发过程比一般产品的开发过程更难于评价和管理。
    为了提高软件开发过程的可见性,更好地进行管理,应该根据软件开发项目的总目标及完成期限,规定开发组织的责任和产品标准,从而使得所得到的结果能够清楚地审查。

6. 开发小组的人员应该少而精
     开发小组人员的素质和数量是影响软件产品质量和开发效率的重要因素。
    素质高的人员的开发效率比素质低的人员的开发效率可能高几倍至几十倍,而且素质高的人员所开发的软件中的错误明显少于素质低的人员所开发的软件中的错误。
    此外,随着开发小组人员数目的增加,因为交流情况讨论问题而造成的通信开销也急剧增加。
    因此,组成少而精的开发小组是软件工程的一条基本原理。


7. 承认不断改进软件工程实践的必要性
    遵循上述6条基本原理,就能够按照当代软件工程基本原理实现软件的工程化生产,但是,仅有上述6条原理并不能保证软件开发与维护的过程能赶上时代前进的步伐,能跟上技术的不断进步。
    因此,把承认不断改进软件工程实践的必要性作为软件工程的第7条基本原理。按照这条原理,不仅要积极主动地采纳新的软件技术,而且要注意不断总结经验。

 

1.2.3  软件工程方法学


    软件工程包括技术和管理两方面的内容,是技术与管理紧密结合所形成的工程学科。

 管理:就是通过计划、组织和控制等一系列活动,合理地配置和使用各种资源,以达到既定目标的过程。
 通常把在软件生命周期全过程中使用的一整套技术方法的集合称为方法学(methodology),也称为范型(paradigm)。在软件工程领域中,这两个术语的含义基本相同。




软件工程方法学包含3个要素:
        方法、工具和过程。
方法:是完成软件开发的各项任务的技术方法,回答“怎样做”的问题;
工具:是为运用方法而提供的自动的或半自动的软件工程支撑环境;
过程:是为了获得高质量的软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤。

 

    目前使用得最广泛的软件工程方法学,分别是传统方法学和面向对象方法学。
1. 传统方法学
传统方法学:也称为生命周期方法学或结构化范型。
    它采用结构化技术(结构化分析、结构化设计和结构化实现)来完成软件开发的各项任务。
    这种方法学把软件生命周期的全过程依次划分为若干个阶段,然后顺序地完成每个阶段的任务。

 目前,传统方法学仍然是人们在开发软件时使用得十分广泛的软件工程方法学。
    此外,要全面了解面向对象方法学,先要了解传统方法学。


传统方法学优点(生命周期方法学或结构化范型)
    把软件生命周期划分成若干个阶段,每个阶段的任务相对独立,而且比较简单,便于不同人员分工协作,从而降低了整个软件开发工程的困难程度;
    在每个阶段结束之前都从技术和管理两个角度进行严格的审查,保证了软件的质量,特别是提高了软件的可维护性。
    总之,采用生命周期方法学可以大大提高软件开发的成功率,软件开发的生产率也能明显提高。

    
2. 面向对象方法学
    当软件规模庞大,或者对软件的需求是模糊的,或软件需求会随时间而变化的时候,使用传统方法学开发软件往往不成功。
    此外,使用传统方法学开发出的软件,维护起来仍然很困难。
原因:
    这种技术要么面向行为(即对数据的操作),要么面向数据,把数据和操作人为地分离成两个独立的部分,自然会增加软件开发与维护的难度。

面向对象方法学具有下述4个要点。
(1) 把对象(object)作为融合了数据及在数据上的操作行为的统一的软件构件。用对象分解取代了传统方法的功能分解。
(2) 把所有对象都划分成类(class)。
(3) 父类与子类的继承关系。
    把若干个相关类组成一个层次结构的系统,下层派生类自动拥有上层基类中定义的数据和操作。
(4) 对象彼此间仅能通过发送消息互相联系。
        对象的所有私有信息都被封装在该对象内,不能从外界直接访问,这就是通常所说的封装性。

 

 

面向对象方法学优点
面向对象方法学的出发点和基本原则,是尽量模拟人类习惯的思维方式,从一般到特殊,从特殊到一般,使开发软件的方法与过程尽可能接近人类认识世界解决问题的方法与过程。传统方法学强调自顶向下顺序地完成软件开发的各阶段任务。事实上,人类认识的过程,是一个渐进的过程,经过多次反复才能逐步深化。
运用面向对象方法学的开发软件,最终的软件产品由许多较小的、基本上独立的对象组成,降低了软件产品的复杂性,提高了软件的可理解性,简化了软件的开发和维护工作。

软件重用。对象是相对独立的实体,容易在以后的软件产品中重复使用。
继承性和多态性,进一步提高了面向对象软件的可重用性。

 

 

1.3  软件生命周期

软件生命周期:由软件定义、软件开发和运行维护,直到最终被废弃所经历的时期。

每个时期又进一步划分成若干个阶段。


软件定义时期的任务是:
  确定软件开发工程必须完成的总目标;
  确定工程的可行性;
  导出实现工程总目标应该采用的策略及系统必须完成的功能;
  估计完成该项工程需要的资源和成本,制定工程进度表。
这个时期的工作又称为系统分析,由系统分析员负责完成。
这个时期进一步划分成3个阶段:
     问题定义、可行性研究和需求分析


开发时期的任务是:
    设计和实现在前一个时期定义的软件,它通常由下述4个阶段组成:
    总体设计,详细设计,编码和单元测试,综合测试。
    其中前两个阶段又称为系统设计,后两个阶段又称为系统实现。


维护时期的主要任务是:
    使软件持久地满足用户的需要。具体地说:
当软件在使用过程中发现错误时应该加以改正;
当环境改变时应该修改软件以适应新的环境;
当用户有新要求时应该及时改进软件以满足用户的新需要。 维护时期不再进一步划分阶段。 

 

 


生命周期每个阶段的基本任务。
1. 问题定义
关键问题是:“要解决的问题是什么?”
弄清楚


2. 可行性研究
关键问题是:“对于上一个阶段所确定的问题有行得通的解决办法吗?”
任务:探索这个问题是否值得去解,是否有可行的解决办法。
不是具体解决问题。

 

3. 需求分析
    主要是确定目标系统必须具备哪些功能
    得出经过用户确认的系统逻辑模型。通常用数据流图、数据字典简要的算法表示。
    任务:是用正式文档准确地记录对目标系统的需求,这份文档通常称为规格说明书(specification)。


4. 总体设计
关键问题是:“以概括的方式,应该怎样实现目标系统?”
总体设计又称为概要设计
主要任务之一:制定出实现最佳方案的详细计划
主要任务之二:设计程序的体系结构,确定程序由哪些模块组成以及模块间的关系

    软件设计的一条基本原理就是,程序应该模块化,一个程序应该由若干个规模适中的模块按合理的层次结构组织而成。


5. 详细设计
    详细设计阶段的任务就是把解法具体化
任务:
    设计出程序的详细规格说明,其作用很类似于工程蓝图,它们应该包含必要的细节。
具体地说:
    详细地设计每个模块,确定实现模块功能所需要的算法和数据结构
    详细设计也称为模块设计,
    还不是编写程序


6. 编码和单元测试
    关键任务:写出正确的容易理解、容易维护的程序模块。
   
7. 综合测试
关键任务:通过各种类型的测试(及相应的调试)使软件达到预定的要求
单元测试,查找各模块在功能和结构上存在的问题并加以纠正
组装测试,将已测试过的模块按一定顺序组装起来
按规定的各项需求,逐项进行有效性测试,决定已开发的软件是否合格,能否交付用户使用

8. 软件维护
关键任务:通过各种必要的维护活动使系统持久地满足用户的需要。
通常有4类维护活动:
改正性维护:诊断和改正在使用过程中发现的软件错误;
适应性维护:修改软件以适应环境的变化;
完善性维护:根据用户的要求改进或扩充软件使它更完善;
预防性维护:修改软件为将来的维护活动预先做准备。

每一项维护活动都要经过:
    提出维护要求(或报告问题),分析维护要求,提出维护方案,审批维护方案,确定维护计划,修改软件设计,修改程序,测试程序,复查验收等一系列步骤,实质上是经历了一次压缩和简化了的软件定义和开发的全过程。
    每一项维护活动都应该准确地记录下来,作为正式的文档资料加以保存。

 


1.4  软件过程

    软件过程是为了获得高质量软件所需要完成的一系列任务的框架,它规定了完成各项任务的工作步骤
    过程定义了运用方法的顺序、应该交付的文档资料、为保证软件质量和协调变化所需要采取的管理措施,以及标志软件开发各个阶段任务完成的里程碑。
    通常使用生命周期模型简洁地描述软件过程。生命周期模型规定了把生命周期划分成哪些阶段及各个阶段的执行顺序,因此,也称为过程模型。

1.4.1  瀑布模型

    在20世纪80年代之前,瀑布模型一直是惟一被广泛采用的生命周期模型,现在它仍然是软件工程中应用得最广泛的过程模型。
    传统软件工程方法学的软件过程,基本上可以用瀑布模型来描述。
图1.2所示为传统的瀑布模型。
   

 

 按照传统的瀑布模型开发软件,有下述的几个特点。

1. 阶段间具有顺序性和依赖性
这个特点有两重含义:
   ①必须等前一阶段的工作完成之后,才能开始后一阶段的工作;
   ②前一阶段的输出文档就是后一阶段的输入文档。
2. 推迟实现的观点
    对于规模较大的软件项目来说,往往编码开始得越早最终完成开发工作所需要的时间反而越长。

3. 质量保证的观点
    每个阶段都应坚持两个重要做法:
(1) 每个阶段都必须完成规定的文档
(2) 每个阶段结束前都要对所完成的文档进行评审,以便尽早发现问题,改正错误。

    传统的瀑布模型过于理想化了,事实上,人在工作过程中不可能不犯错误。
    因此,实际的瀑布模型是带“反馈环”的,如图1.3所示。

 


    当在后面阶段发现前面阶段的错误时,需要沿反馈线返回前面的阶段,修正前面阶段的产品之后再回来继续完成后面阶段的任务。

 瀑布模型有许多优点
    强迫开发人员采用规范的方法;
    严格地规定了每个阶段必须提交的文档
    要求每个阶段交出的所有产品都必须经过质量保证小组的仔细验证
    遵守瀑布模型的文档约束,将使软件维护变得比较容易一些。
   文档驱动

 瀑布模型的缺点
文档驱动
    用户仅仅通过写在纸上的静态的规格说明,很难全面正确地认识动态的软件产品
 一旦用户开始使用最终系统,并对系统有更多的学习以后,观点会发生很大的变化。用户的这种变化常常是无法预测的。
    最终产品更多的反映用户在项目开始时的需求,而不是最后的需求。导致最终开发出的软件产品不满足用户需求。



1.4.2  快速原型模型

 

 所谓快速原型:是快速建立起来的可以在计算机上运行的程序,它所能完成的功能往往是最终产品能完成的功能的一个子集
    如图1.4所示

 

    快速原型模型的第一步是快速建立一个能反映用户主要需求的原型系统,让用户在计算机上试用它,通过实践来了解目标系统的概貌。

 

   用户试用原型系统之后
  提出许多修改意见,
  开发人员快速地修改原型系统,
  然后再次请用户试用……直到得到用户认可,
  开发人员便可据此书写规格说明文档,反映了用户的真实需求。
   因此快速原型模型是不带反馈环的,这正是这种过程模型的主要优点: 软件产品的开发基本上是线性顺序进行的。
    

 

 

1.4.3  增量模型

     增量模型也称为渐增模型,如图1.5所示。

 


    使用增量模型开发软件时,把软件产品作为一系列的增量构件来设计、编码、集成和测试


增量模型的优点:
 能在较短时间内向用户提交可完成部分工作的产品
 逐步增加产品功能可以使用户有较充裕的时间学习适应新产品

使用增量模型的困难是:
 在把每个新的增量构件集成到现有软件体系结构中时,必须不破坏原来已经开发出的产品
 必须把软件的体系结构设计得便于按这种方式进行扩充,即加入新构件的过程必须简单、方便,也就是说,软件体系结构必须是开放的
 从长远观点看,具有开放结构的软件拥有真正的优势,这样的软件的可维护性明显好于封闭结构的软件。

     如果一个增量模型的设计非常灵活而且足够开放,那么,这样的设计将允许在不破坏产品的情况下进行维护。
意味着:
    使用增量模型时开发软件和扩充软件功能(完善性维护)没有本质区别,都是向现有产品中加入新构件的过程。
    维护时期反馈环很小。

1.4.4  螺旋模型

    软件风险是任何软件开发项目中都普遍存在的实际问题,项目越大,软件越复杂,承担该项目所冒的风险也越大。
    软件风险可能在不同程度上损害软件开发过程和软件产品质量。


    因此,在软件开发过程中必须及时
    识别和分析风险,
    并且采取适当措施,
   以消除或减少风险的危害。

     构建原型是一种能使某些类型的风险降至最低的方法。
    在需求分析阶段:通过快速地构建一个原型,降低交付给用户的产品不能满足用户需要的风险。
    在后续的阶段中也可以通过构造适当的原型来降低某些技术风险。
    螺旋模型的基本思想是,使用原型及其他方法来尽量降低风险,在每个阶段之前都增加了风险分析过程的快速原型,如图1.7所示简化的螺旋模型。

 

 

Boehm于1988年提出,主要针对大型软件项目的开发。
四个象限
制定计划
风险分析
实施工程
客户评价

制定计划:确定软件项目目标;明确对软件开发过程和软件产品的约束;制定详细的项目管理计划;根据当前的需求和风险因素,制定实施方案,并进行可行性分析,选定一个实施方案,并对其进行规划。
风险分析:明确每一个项目风险,估计风险发生的可能性、频率、损害程度,并制定风险管理措施规避这些风险。
实施工程:针对每一个开发阶段的任务要求执行本开发阶段的活动。
客户评估:客户使用原型,反馈修改意见;根据客户的反馈,对产品及其开发过程进行评审,决定是否进入螺旋线的下一个回路。

 

1.4.5 喷泉模型

 喷泉模型也称迭代模型,认为软件开发过程的各个阶段是相互重叠和多次反复的,就象喷泉一样,水喷上去又可以落下来,既可以落在中间,又可以落到底部。
各个开发阶段没有特定的次序要求,完全可以并行进行,可以在某个开发阶段中随时补充其他任何开发阶段中遗漏的需求。


优点:
提高开发效率
缩短开发周期


缺点:难于管理

 

 

 

 

1.4.6面向对象过程

RUP

RUP(Rational Unified Process)是由Rational公司(现被IBM公司收购)开发的一种软件工程过程框架,是一个面向对象的基于web的程序开发方法论 。
RUP既是一种软件生命周期模型,又是一种支持面向对象软件开发的工具,它将软件开发过程要素和软件工件要素整合在统一的框架中 。

RUP的基本结构

RUP中的软件生命周期在时间上被分解为四个顺序的阶段:初始阶段(Inception)、细化阶段(Elaboration)、构造阶段(Construction)和交付阶段(Transition)。
每个阶段结束于一个主要的里程碑(Major Milestones),并在阶段结尾执行一次评估以确定这个阶段的目标是否已经满足。如果评估结果令人满意的话,可以允许项目进入下一个阶段。

 

 初始阶段
目标是为系统建立商业案例(business case)并确定项目的边界。
商业案例包括项目的验收规范、风险评估、所需资源估计、阶段计划等。
要确定项目边界,需识别所有与系统交互的外部实体,并在较高层次上定义外部实体与系统交互的特性,主要包括识别外部角色(actor)、识别所有用例并详细描述一些重要的用例。
阶段结束里程碑:生命周期目标(Lifecycle Objective)里程碑。生命周期目标里程碑包括一些重要的文档,如:项目构想(vision)、原始用例模型、原始业务风险评估、一个或者多个原型、原始商业案例等。需要对这些文档进行评审,以确定正确理解用例需求、项目风险评估合理、阶段计划可行等。

细化阶段
目标是分析问题领域,建立健全的体系结构基础,编制项目计划,完成项目中高风险需求部分的开发。
里程碑:生命周期体系结构(Lifecycle Architecture)里程碑。生命周期体系结构里程碑包括风险分析文档、软件体系结构基线、项目计划、可执行的进化原型、初始版本的用户手册等。通过评审确定软件体系结构已经稳定、高风险的业务需求和技术机制已经解决、修订的项目计划可行等。

构造阶段
将所有剩余的技术构件和稳定业务需求功能开发出来,并集成为产品,所有功能被详细测试。从某种意义上说,构造阶段只是一个制造过程,其重点放在管理资源及控制开发过程以优化成本、进度和质量。
里程碑:初始运行能力(Initial Operational Capability)里程碑。包括可以运行的软件产品、用户手册等,它决定了产品是否可以在测试环境中进行部署。此刻,要确定软件、环境、用户是否可以开始系统的运行。

移交阶段
移交阶段的重点是确保软件对最终用户是可用的。交付阶段可以跨越几次迭代,包括为发布做准备的产品测试,基于用户反馈的少量调整。
里程碑:产品发布(Product Release)里程碑。此时,要确定最终目标是否实现,是否应该开始产品下一个版本的另一个开发周期。在一些情况下这个里程碑可能与下一个周期的初始阶段的相重合。

RUP的迭代增量开发思想
RUP是融合了喷泉模型和增量模型的一种综合生命周期模型。

 

 

RUP的9个核心工作流
6个核心过程工作流
  商业建模(Business Modeling)
  需求(Requirements)
  分析和设计(Analysis & Design)
  实现(Implementation)
  测试(Test)
  部署(Deployment)
3个核心支持工作流:
  配置和变更管理(Configuration & Change Management)
  项目管理(Project Management)
  环境(Environment)

RUP的最佳实践:
  短时间分区式的迭代:2~6周,不鼓励时间推迟;
  适应性开发:小步骤、快速反馈和调整;
  在早期迭代中解决高技术风险和高业务价值的问题;
  不断地让用户参与迭代结果的评估,并及时获取反馈信息,以逐步阐明问题并引导项目进展;
  在早期迭代中建立内聚的核心架构。该实践是和早期处理高技术风险和高业务价值问题有关的,因为核心架构一般和高风险因素紧密相关。
  不断地验证质量;尽早、经常和实际地测试;
  使用用例驱动软件建模:用例是获取需求、制定计划、进行设计、测试、编写终端用户文档的驱动力量。
  可视化软件建模:使用UML(Unified Modeling Language,统一建模语言)进行软件建模。
  仔细地管理需求:不要草率地对待需求,而要有机地进行需求的提出、记录、等级划分、追踪。拙劣的需求管理是项目陷入麻烦的一个常见原因。
  实行变更请求和配置管理。



敏捷模型

  敏捷建模(Agile Modeling,AM)是由Scott W. Ambler从许多的软件开发过程实践中归纳总结出来的一些敏捷建模价值观、原则和实践等组成的,它只是一种态度,不是一个说明性过程 。
  AM是对已有生命周期模型的补充,它本身不是一个完整的方法论,在应用传统的生命周期模型时可以借鉴AM的过程指导思想 。
  极限编程(eXtreme Programming, XP)是敏捷过程中最富盛名的一个,其名称中“极限”二字的含义是指把好的开发实践运用到极致。目前,极限编程已经成为一个典型的开发方法,广泛应用于需求模糊且经常改变的场合。

敏捷建模的价值观
  沟通:建模不但能够促进团队内部开发人员之间沟通,还能够促进团队和项目干系人(project stakeholder)之间的沟通。
  简单:画一两张图表来代替几十甚至几百行的代码,通过这种方法,建模成为简化软件和软件开发过程的关键。
  反馈:通过图表来交流建模想法,可以快速获得彼此的反馈。
  勇气:如果一项决策证明是不合适的时候,就需要勇气做出重大的决策:放弃或重构(refactor)先前的工作,修正建模方向。
  谦逊:最优秀的开发人员都拥有谦逊的美德,他们总能认识到自己并不是无所不知的。

 

敏捷建模核心原则:
  主张简单;
  拥抱变化;
  软件开发的第二个目标应是可持续性
  递增的变化
  令项目干系人投资最大化
  有目的地建模

  多种模型
  高质量的工作
  快速反馈
  以有效的方式,制造出满足项目干系人所需要的软件,而不是制造无关的文档、无关的用于管理的工件,甚至无关的模型
  轻装前进

敏捷模型补充原则:
  内容比表示更重要
  三人行必有我师
  了解软件建模方法
  了解软件开发工具
  局部调整
  开放诚实的沟通
  利用好直觉

 

敏捷建模核心实践(极限编程)
项目干系人的积极参与
正确使用工件
集体所有制
测试性思维
并行创建模型
创建简单的内容
简单地建模
公开展示模型
切换到另外的工件
小增量建模
和他人一起建模
用代码验证
使用最简单的工具

 

敏捷模型补充实践:
使用建模标准
逐渐应用模式(pattern)
丢弃临时模型
合同模型要正式
为外部交流建模
为帮助理解建模
重用现有的资源
不到万不得已不更新模型

 

 

极限编程的有效实践(特色)

客户作为开发团队的成员(不一定是真客户)
使用用户素材(用户故事,记录在卡片上)
短交付周期(两周-一个月)
验收测试
结对编程
测试驱动开发
集体所有
持续集成
可持续的开发速度(每周40个小时)
开放的工作空间
及时调整计划
简单的设计
重构
使用隐喻(隐喻相当于体系结构,从客户角度来描述一个项目的全局,用户故事则从局部来描述)


极限编程的开发过程

 

 

 极限编程的迭代过程

 

 

 

 极限编程的特点

综上所述,以极限编程为代表的敏捷过程,具有对变化和不确定性的更快速,更敏捷的反映特性,而且在快速的同时仍然能保持可持续的开发速度。上述这些特点使得敏捷过程能够较好的适应商业竞争环境下对小型项目提出的有限资源和有限开发时间的约束。

 

 

 

微软过程

 作为世界上最大的同时也是最成功的软件公司之一,Microsoft(微软)公司拥有自己独特的软件开发过程,几十年的实践证明微软过程是非常成功和行之有效的。


主要内容
微软过程准则
微软软件生命周期
微软过程模型

 微软过程准则

项目计划应该兼顾未来的不确定因素
用有效的风险管理来减少不确定因素的影响
经常生成并快速地测试软件的过渡版本,从而提高产品地稳定性和可预测性
采用快速循环,递进地开发过程
用创造性地工作来平衡产品特性和产品成本
项目进度表应该具有较高稳定性和权威性
使用小型项目组并发地完成开发工作
在项目早期把软件配置项基线化,项目后期则冻结产品
使用原型验证概念,对项目进行早期论证
把零缺陷作为追求的目标
里程碑评审会的目的是改进工作,切忌相互指责


微软软件生命周期

 

 

 

 五个阶段及里程碑

 (1)规划阶段
确定产品目标。
获取竞争对手的信息。
完成对客户和市场的调研分析。
确定新版本产品应具备的主要特征。
确定相对于前一版本而言,新版本应该解决的问题和需要增加的功能。
(2)设计阶段
根据产品目标编写系统的特性规格说明书。主要描述软件特性、系统结构、各构件间的相关性以及接口标准。
从系统高层着手开始进行系统设计,主要完成:系统设计方案,描绘系统结构图,确定系统中存在的风险因素,分析系统的可重用性。
划分出系统的子系统,给出各自系统和各个构件的规格说明。
根据产品特性规格说明书制定产品开发计划。
(3)开发阶段
完成产品中所有构件的开发工作,包括编写程序代码和书写文档。
(4)稳定阶段
对产品进行测试和调式,以确保已经正确地实现了整个解决方案,产品可以发布了。
(5)发布阶段
发布产品获解决方案,并把项目移交到运营和支持人员手中,以获得最终用户对项目的认可。



 微软过程的生命周期模型

 

 

 微软过程小结

综合了Rational同一过程和敏捷过程的许多优点,是对众多成功项目的开发经验的正确总结;
有某些不足之处,例如,对方法,工具和产品等方面的论述不如RUP和敏捷过程全面。
在开发软件的实践中,应该把微软过程与RUP和敏捷过程结合起来,取长补短,针对不同项目的具体情况进行制定。

 

 

 

 

posted @ 2019-05-27 20:00  Zander_Zhao  阅读(1731)  评论(0编辑  收藏  举报