在软件产品被开发出来并交付用户使用之后,就进入了软件的运行维护阶段。这个阶段是软件生命周期的最后一个阶段,其基本任务是保证软件在一个相当长的时期能够正常运行。软件维护需要的工作量很大,平均说来,大型软件的维护成本高达开发成本的4倍左右。软件工程的主要目的就是要提高软件的可维护性,减少软件维护所需要的工作量,降低软件系统的总成本。

8.1 软件维护的定义

  • 改正性维护

因为软件测试不可能暴露出一个大型软件系统中所有潜藏的错误,所以必然会有第一项维护活动:在任何大型程序的使用期间,用户必然会发现程序错误,并且把他们遇到的问题报告给维护人员。把诊断和改正错误的过程称为改正性维护。

  • 改正性维护
    对在测试阶段未能发现的、在软件投入使用后才逐渐暴露出来的错误的测试、诊断、定位、纠错,以及验证、修改的回归测试过程,称为改正性维护。
  • 完善性维护
    为了满足用户在使用过程中对软件提出的新的功能与性能要求,需要对原来的软件的功能进行修改或扩充。
  • 适应性维护
    使软件适应外部新的软硬件环境或者数据环境发生的变化,而进行修改软件的过程。
  • 预防性维护
    为了提高软件未来的可维护性、可靠性等,或为了给未来的改进奠定更好的基础而修改软件的过程。

image.png

8.2软件维护的特点

8.2.1.结构化维护与非结构化维护差别巨大

结构化维护:

结构化维护是指软件开发过程是按照软件工程方法进行的、各开发阶段文档齐全的软件的维护过程。 非结构化维护:

非结构化维护是指在只有源程序,缺乏必要的文档说明,难于确定数据结构、系统接口等特性的情况下, 进行的软件维护过程。

明显代价:高昂的维护费用,已上升达80%左右;
无形代价:改错或修改的要求不能及时满足引起的用户不满;
维护时的改动,引入潜伏错误,导致软件质量降低;
软件工程师从事维护工作造成的开发过程混乱。
生产率的大幅下降:维护工作量:生产性劳动+非生产性劳动。
image.png

8.2.3.维护的问题很多

下面列出和软件维护有关的部分问题: 随着软件配置成分的减少而迅速增加。如果仅有程序代 码没有说明文档,则会出现严重的问题。 资料显著不足。认识到软件必须有文档仅仅是第一步, 容易理解的并且和程序代码完全一致的文档才真正有价 值。
(1)理解别人写的程序通常非常困难,而且困难程度 (2)需要维护的软件往往没有合格的文档,或者文档

8.3软件维护的过程

维护过程的本质 维护过程本质上是修改和压缩了的软件定义和开发过程,而且事实上远在提出一项维护要求之前,与软件维护有关的工作已经开始了。

  1. 首先必须建立一个维护组织
  2. 随后必须确定报告和评价的过程
  3. 而且必须为每个维护要求规定一个标准化的事件序列

此外,还应该建立一个适用于维护活动的记录保管过程,并且规定复审标准。

1.维护组织
image.png
2.维护报告
软件维护人员通常给用户提供空白的维护要求表—有时称为软件问题报告表,这个表格由要求一项维护活动的用户填写。如果遇到了一个错误,那么必须完整描述导致出现错误的环境(包括输入数据、全部输出数据以及其他有关信息)。
维护要求表是一个外部产生的文件,它是计划维护活动的基础。软件组织内部应该制定出一个软件修改报告,它给出下述信息。
(1)满足维护要求表中提出的要求所需要的工作量。
(2)维护要求的性质。
(3)这项要求的优先次序。
(4)与修改有关的事后数据。
在拟定进一步的维护计划之前,把软件修改报告提交给变化授权人审査批准。
image.png
image.png

8.4 软件的可维护性

可以把软件的可维护性定性地定义为:维护人员理解、改正、改动或改进这个软件的难易程度。
提高可维护性是支配软件工程方法学所有步骤的关键目标!


8.4.1.决定软件可维护性的因素

维护就是在软件交付使用后进行的修改,修改之前必须理 解待修改的对象,修改之后应该进行必要的测试,以保证所做的修改是正确的。如果是改正性维护,还必须预先进行调试以确定错误的具体位置。因此,决定软件可维护性的因素主要有下述5个。
1.可理解性
2.可测试性
3.可修改性
4.可移植性
5.可重用性
1.可理解性
软件可理解性表现为外来读者理解软件的结构、功模块化(模块结构良好,高内聚,松耦合)、详细的设计文档、结构化设计、程序内部的文档和良好的高级程序设计语言等,都对提高软件的可理解性有重要贡献。能、接口和内部处理过程的难易程度。
3.可修改性
软件容易修改的程度和本书第5章讲过的设计原理和启发规则直接有关。耦合、内聚、信息隐藏、局部化、控制域与作用域的关系等,都影响软件的可修改性。
4.可移植性
软件可移植性指的是,把程序从一种计算环境(硬件配置和操作系统)转移到另一种计算环境的难易程度。把与硬件、操作系统以及其他外部设备有关的程序代码集中放到特定的程序模块中,可以把因环境变化而必须修改的程序局限在少数程序模块中,从而降低修改的难度。
5.可重用性
所谓重用( reuse)是指同一事物不做修改或稍加改动就在不同环境中多次重复使用。大量使用可重用的软件构件来开发软件,可以从下述两个方面提高软件的可维护性。
(1)通常,可重用的软件构件在开发时都经过很严格的测试,可靠性比较高,且在每次重用过程中都会发现并清除一些错误,随着时间推移,这样的构件将变成实质上无错误的。因此,软件中使用的可重用构件越多,软件的可靠性越高,改正性维护需求就越少。
(2)很容易修改可重用的软件构件使之再次应用在新环境中, 因此,软件中使用的可重用构件越多适应性和完善性维护也就越容易。

8.4.2.文档

文档是影响软件可维护性的决定因素。由于长期使用的大型软件系统在使用过程中必然会经受多次修改,所以文档比程序代码更重要。 软件文档应该满足下述要求:
(1)必须描述如何使用这个系统,没有这种描述时即使是最简单的系统也无法使用。
(2)必须描述怎样安装和管理这个系统。
(3)必须描述系统需求和设计。
(4)必须描述系统的实现和测试,以便使系统成为可维护的。
文档可以分为用户文档和系统文档两类。
1.用户文档
用户文档是用户了解系统的第一步,它应该能使用户获得对 系统的准确的初步印象。
(1)功能描述 (2)安装文档 (3)使用手册 (4)参考手册(要完整) (5)操作员指南(如果需要有系统操作员的话)
2.系统文档
所谓系统文档指从问题定义、需求说明到验收测试计划这样一系列和系统实现有关的文档。描述系统设计、实现和测试的文档对于理解程序和维护程序来说是极端重要的。
和用户文档类似,系统文档的结构也应该能把读者从对系统概貌的了解,引导到对系统每个方面每个特点的更形式化更具体的认识。本书前面各章已经较详细地介绍了各个阶段应该产生的文档,此处不再重复。

8.4.3可维护性复审

  1. ●可维护性是所有软件都应该具备的基本特点,必须在开发 在完成了每项维护工作之后,都应该对软件维护本身进行 不能准确反映软件当前状态的设计文档可能比完全没有文 如果对软件的可执行部分的修改没有及时反映在用户文档<br /> 为什么要进行可维护性复审?
  2. 阶段保证软件具有8.4.1节中提到的那些可维护因素。 仔细认真的复审。 档更坏。 中,则必然会使用户因为受挫折而产生不满。
  • 在软件再次交付使用之前,对软件配置进行严格的复审,则可大大减少文档的问题。
  • 在需求分析阶段的复审过程中,应该对将来要改进的部分和可能会修改的部分加以注意并指明; 应该讨论 软件的可移植性问题,并且考虑可能影响软件维护的 系统界面。
  • 在正式的和非正式的设计复审期间,应该从容易修改、模块化和功能独立的目标出发,评价软件的结构和过 程;设计中应该对将来可能修改的部分预作准备

代码复审应该强调编码风格和内部说明文档这两个影 响可维护性的因素。 在设计和编码过程中应该尽量使用可重用的软件构件, 如果需要开发新的构件,也应该注意提高构件的可重 用性。 在测试结束时进行最正式的可维护性复审,这个复审 称为配置复审。配置复审的目的是保证软件配置的所 有成分是完整的、一致的和可理解的,而且为了便于 修改和管理已经编目归档了。

8.5预防性维护

什么是老程序呢? 这些程序的体系结构和数据结构都很差,文档不全甚至完全没有文档,对曾经做过的修改也没有完整的记录。
怎样满足用户对老程序的维护要求?
(1)反复多次地做修改程序的尝试,与不可见的设计及源代码“顽强战斗”,以实现 所要求的修改。
(2)通过仔细分析程序尽可能多地掌握程序的内部工作细节,以便更有效地修改它。
(3)在深入理解原有设计的基础上,用软件工程方法重新设计、重新编码和测试那些需要变更的软件部分。
(4)以软件工程方法学为指导,对程序全部重新设计、重新编码和测试,为此可以使用CASE工具(逆向工程和 再工程工具)来帮助理解原有的设计

  1. 预防性维护方法是由Mier提出来的,他把这种方法定义为:“把今天的方法学应用到昨天的系统上,以支持明天的需求。”<br /> 粗看起来,在一个正在工作的程序版本已经存在的情况下重新开发一个大型程序,似乎是一种浪费。其实不然,下述事实很能说明问题。<br />(1)维护一行源代码的代价可能是最初开发该行源代码代价的14~40倍。<br />(2)重新设计软件体系结构(程序及数据结构)时使用了现代设计概念,它对将来的维护可能有很大的帮助<br />(3)由于现有的程序版本可作为软件原型使用,开发生产率可大大高于平均水平。<br />(4)用户具有较多使用该软件的经验,因此,能够很容易地搞清晰的变更需求和变更的范围。<br />(5)利用逆向工程和再工程的工具,可以使一部分工作自动化。 <br />(6)在完成预防性维护的过程中可以建立起完整的软件配置。 <br />虽然由于条件所限,目前预防性维护在全部维护活动中仅占很小比例,但是,人们不应该忽视这类维护,在条件具备时应该主动地进行预防性维护

8.6 软件再工程过程

  1. 些活动以线性顺序发生,但也并非总是这样。例如,为了理 解某个程序的内部工作原理,可能在文档重构开始之前必须 先进行逆向工程。典型的软件再工程过程模型如下图所示。在某些情况下这 <br />![image.png](https://cdn.nlark.com/yuque/0/2020/png/1118250/1587429146410-0fa99efe-8e9d-4301-8f0c-caf889c7357f.png#align=left&display=inline&height=265&margin=%5Bobject%20Object%5D&name=image.png&originHeight=529&originWidth=568&size=48272&status=done&style=none&width=284)<br />1.库存目录分析
  • 每个软件组织都应该保存其拥有的所有应用系统的库存目录。该目录包含关于每个应用系统的基本信息

(例如应用系统的名字,最初构建它的日期,已做过的实质性修改次数,过去18个月报告的错误,用户数量,安装它的机器数量,它的复杂 程度,文档质量,整体可维护性等级,预期寿命,在未来36个月内的预 期修改次数,业务重要程度等)。
2.文档重构

  • 老程序固有的特点是缺乏文档。具体情况不同,处理这个 问题的方法也不同。
  1. 建立文档非常耗费时间,不可能为数百个程序都重新建立文档。如果一个程序是相对稳定的,正在走向其 有用生命的终点,而且可能不会再经历什么变化,那么,让它保持现状是一个明智的选择。
  2. 为了便于今后的维护,必须更新文档,但是由于资源有限,应采用“使用时建文档”的方法。
  3. 如果某应用系统是完成业务工作的关键,而且必须重构全部文档,则仍然应该设法把文档工作减少到必需的最小量。

4.代码重构

  • 代码重构是最常见的再工程活动。某些老程序具有比较完整、合理的体系结构,但是,个体模块的编码方式却是难于理解、测试和维护的。在这种情况下,可以重构可疑模块的代码。

6.正向工程

  • 正向工程也称为革新或改造,这项活动不仅从现有程序中恢复设计信息,而且使用该信息去改变或重构现有系统,以提高其整体质量。

    8.7 本章小结

    image.png