第八章维护与再生工程 编程大师曾说:“哪怕程序只有三行长,总有一天你也不得不对它维护。” 很多软件产品不是一次性的买卖。比如在电信、金融等领域,有些软件系统婴用 几年,对软件进行维护是必不可少的。8.1节将介绍“软件维护的常识”,对维护活动进 行分类,并解释为什么维护比较困难。 软件公司的经理们没有哪一个喜欢被维护的费用吓一跳,但软件维护的代价通常是 高昂的。7,2节将说明影响维护代价的一些主要技术因素与非技术因素。 如果希望提高己有软件的质量并且提高商业竞争力,却又无法靠维护来实现,只好 对已有软件进行全部或者部分的改造,这种活动叫再生工程(Reengineering)。7.3节将 解释什么是再生工程,并论述再生工程的三种类型:重构(Restructure)、逆向工程(Reverse Engineering)和前向工程(Forward Engineering)。 8.1软件维护的常识 对软件而言,“维护”是个不太直观的术语,因为软件产品在重复使用时不会被磨损, 并不需要进行像对车辆或电器那样的维护。软件维护是人们对既丰富多彩又会令人心酸 的活动的统称。其中丰富多彩的活动是指那些反映客观世界变化、能使软件系统更加完 善的修改和扩充工作。令人心酸的活动是指那些永无修止、并且改了旧错却引起新错让 人欲哭无泪的工作。 一些学者将软件维护划分为主要的三类:纠错性维护(Corrective maintenance入、适 应性维护(Adaptive maintenance)和完善性维护(Perfective maintenance): (1)纠错性维护。由于前期的测试不可能揭露软件系统中所有替在的错误,用户在使用 软件时仍将会遇到错误,诊断和改正这些错误的过程称为纠错性维护。 (2)适应性维护。由于新的硬件设备不断推出,操作系统和编译系统也不断地升级,为 了使软件能适应新的环境而引起的程序修改和扩充活动称为适应性维护。 (3)完善性维护。在软件的正常使用过程中,用户还会不断提出新的需求。为了满足用 户新的需求而增加软件功能的活动称为完善性维护。 Lientz和Swanson调查发现(1980年),完善性维护约占65%,适应性维护约占18%, 纠错性维护约占17%1 Sommerville1921。上述调查己是20年前的事了,我们不必太关心 具体的比例,心里有数即可。 以下一些因素将导致维护工作变得闲难 (1)软件人员经常流动,当需要对某些程序进行维护时,可能已找不到原来的开发人员。 只好让新手去“攻读”那些程序。 (2)人们一般难以读懂他人的程序。在勉强接受这类任务时,心里不免嘀咕:“我又不 是他肚子里的虫子,怎么知道他如何编程。” (3)当没有文档或者文档很差时,你简直不知道如何下手
1 第八章 维护与再生工程 编程大师曾说:“哪怕程序只有三行长,总有一天你也不得不对它维护。” 很多软件产品不是一次性的买卖。比如在电信、金融等领域,有些软件系统要用十 几年,对软件进行维护是必不可少的。8.1 节将介绍“软件维护的常识”,对维护活动进 行分类,并解释为什么维护比较困难。 软件公司的经理们没有哪一个喜欢被维护的费用吓一跳,但软件维护的代价通常是 高昂的。7.2 节将说明影响维护代价的一些主要技术因素与非技术因素。 如果希望提高已有软件的质量并且提高商业竞争力,却又无法靠维护来实现,只好 对已有软件进行全部或者部分的改造,这种活动叫再生工程(Reengineering)。7.3 节将 解释什么是再生工程,并论述再生工程的三种类型:重构(Restructure)、逆向工程(Reverse Engineering)和前向工程(Forward Engineering)。 8.1 软件维护的常识 对软件而言,“维护”是个不太直观的术语,因为软件产品在重复使用时不会被磨损, 并不需要进行像对车辆或电器那样的维护。软件维护是人们对既丰富多彩又会令人心酸 的活动的统称。其中丰富多彩的活动是指那些反映客观世界变化、能使软件系统更加完 善的修改和扩充工作。令人心酸的活动是指那些永无修止、并且改了旧错却引起新错让 人欲哭无泪的工作。 一些学者将软件维护划分为主要的三类:纠错性维护(Corrective maintenance)、适 应性维护(Adaptive maintenance)和完善性维护(Perfective maintenance): (1)纠错性维护。由于前期的测试不可能揭露软件系统中所有替在的错误,用户在使用 软件时仍将会遇到错误,诊断和改正这些错误的过程称为纠错性维护。 (2)适应性维护。由于新的硬件设备不断推出,操作系统和编译系统也不断地升级,为 了使软件能适应新的环境而引起的程序修改和扩充活动称为适应性维护。 (3)完善性维护。在软件的正常使用过程中,用户还会不断提出新的需求。为了满足用 户新的需求而增加软件功能的活动称为完善性维护。 Lientz 和 Swanson 调查发现(1980 年),完善性维护约占 65%,适应性维护约占 18%, 纠错性维护约占 17%[Sommerville 1992]。上述调查已是 20 年前的事了,我们不必太关心 具体的比例,心里有数即可。 以下一些因素将导致维护工作变得困难: (1)软件人员经常流动,当需要对某些程序进行维护时,可能已找不到原来的开发人员。 只好让新手去“攻读”那些程序。 (2)人们一般难以读懂他人的程序。在勉强接受这类任务时,心里不免嘀咕:“我又不 是他肚子里的虫子,怎么知道他如何编程。” (3)当没有文档或者文档很差时,你简直不知道如何下手
(4)很多程序在设计时没有考虑到将来要改动,程序之间相互交织,触一而牵百。即使 有很好的文档,你也不敢轻举妄动,否则你有可能陷进错误堆里。 (5)如果软件发行了多个版本,要追踪软件的演化非常闲难。 (6)维护将会产生不良的副作用,不论是修政代码、数据或文档,都有可能产生新的错 误。 (7)维护工作毫无吸引力。高水平的程序员自然不愿主动去做,而公司也舍不得让高水 平的程序员去做。带着低沉情绪的低水平的程序员只会把维护工作搞得一塌糊涂。 8.2维护的代价及其主要因素 软件维护是既破财又费神的工作。看得见的代价是那些为了维护而投入的人力与财 力。而看不见的维护代价则更加高品,我们称之为“机会成本”,即为了得到某种东西所 必须放弃的东西Mkw1999。把很多程序员和其它资源用于维护工作,必然会耽误新产 品的开发甚至会丧失机遇,这种代价是无法估量的 影响维护代价的非技术因素主要有: (1)应用域的复杂性。如果应用域问题已被很好地理解,需求分析工作比较完善,那么 维护代价就较低。反之维护代价就较高。 (2)开发人员的稳定性。如果某些程序的开发者还在,让他们对自己的程序进行维护, 那么代价就较低。如果原来的开发者已经不在,只好让新手来维护陌生的程序,那么代 价就拉高 (3)软件的生命期。越是早期的程序越难维护,你很难想像十年前的程序是多么的落后 (设计思想与开发工具都落后)。一般地,软件的生命期越长,维护代价就越高。生命期 越短,维护代价就越低。 (4)商业操作模式变化对软件的影响。比如财务软件,对财务制度的变化很敏感。财务 制度一变动,财务软件就必须修改。一般地,商业操作模式变化越频繁,相应软件的维 护代价就越高。 影响维护代价的技术因素主要有: (1)软件对运行环境的依赖性。由于硬件以及操作系统更新很快,使得对运行环境依赖 性很强的应用软件也要不停地更新,维护代价就高。 (2)编程语言。虽然低级语言比高级语言具有更好的运行速度,但是低级语言比高级语 言难以理解。用高级语言编写的程序比用低级语言编写的程序的维护代价要低得多(并 且生产率高得多)。一般地,商业应用软件大多采用高级语言。比如,开发一套Windows 环境下的信息管理系统,用户大多采用Visual Basic、Delphi或Power Builder来编程, 用Visual C++的就少些,没有人会采用汇编语言」 (3)编程风格。良好的编程风格意味着良好的可理解性,可以降低维护的代价。 (4)测试与改错工作。如果测试与改错工作做得好,后期的维护代价就能降低。反之维 护代价就升高 (5)文档的质量。清晰、正确和完备的文档能降低维护的代价。低质量的文档将增加维 护的代价(错误百出的文档还不如没有文档)。 2
2 (4)很多程序在设计时没有考虑到将来要改动,程序之间相互交织,触一而牵百。即使 有很好的文档,你也不敢轻举妄动,否则你有可能陷进错误堆里。 (5)如果软件发行了多个版本,要追踪软件的演化非常困难。 (6)维护将会产生不良的副作用,不论是修改代码、数据或文档,都有可能产生新的错 误。 (7)维护工作毫无吸引力。高水平的程序员自然不愿主动去做,而公司也舍不得让高水 平的程序员去做。带着低沉情绪的低水平的程序员只会把维护工作搞得一塌糊涂。 8.2 维护的代价及其主要因素 软件维护是既破财又费神的工作。看得见的代价是那些为了维护而投入的人力与财 力。而看不见的维护代价则更加高昂,我们称之为“机会成本”,即为了得到某种东西所 必须放弃的东西[Mankiw 1999]。把很多程序员和其它资源用于维护工作,必然会耽误新产 品的开发甚至会丧失机遇,这种代价是无法估量的。 影响维护代价的非技术因素主要有: (1)应用域的复杂性。如果应用域问题已被很好地理解,需求分析工作比较完善,那么 维护代价就较低。反之维护代价就较高。 (2)开发人员的稳定性。如果某些程序的开发者还在,让他们对自己的程序进行维护, 那么代价就较低。如果原来的开发者已经不在,只好让新手来维护陌生的程序,那么代 价就较高。 (3)软件的生命期。越是早期的程序越难维护,你很难想像十年前的程序是多么的落后 (设计思想与开发工具都落后)。一般地,软件的生命期越长,维护代价就越高。生命期 越短,维护代价就越低。 (4)商业操作模式变化对软件的影响。比如财务软件,对财务制度的变化很敏感。财务 制度一变动,财务软件就必须修改。一般地,商业操作模式变化越频繁,相应软件的维 护代价就越高。 影响维护代价的技术因素主要有: (1)软件对运行环境的依赖性。由于硬件以及操作系统更新很快,使得对运行环境依赖 性很强的应用软件也要不停地更新,维护代价就高。 (2)编程语言。虽然低级语言比高级语言具有更好的运行速度,但是低级语言比高级语 言难以理解。用高级语言编写的程序比用低级语言编写的程序的维护代价要低得多(并 且生产率高得多)。一般地,商业应用软件大多采用高级语言。比如,开发一套 Windows 环境下的信息管理系统,用户大多采用 Visual Basic、Delphi 或 Power Builder 来编程, 用 Visual C++的就少些,没有人会采用汇编语言。 (3)编程风格。良好的编程风格意味着良好的可理解性,可以降低维护的代价。 (4)测试与改错工作。如果测试与改错工作做得好,后期的维护代价就能降低。反之维 护代价就升高。 (5)文档的质量。清晰、正确和完备的文档能降低维护的代价。低质量的文档将增加维 护的代价(错误百出的文档还不如没有文档)
8.3再生工程 再生工程主要出于如下愿望:(1)在商业上要提高产品的竞争力:(2)在技术上要 提高产品的质量。但这种愿望无法靠软件的维护来实现,因为:(1)软件的可维护性可 能极差,实在不值得去做:(2)即使软件的可维护性比较好,但也只是治表不治本。再 生工程干脆对已有软件进行全部或部分的改造,赋予软件新的活力。 在对待一个不良之徒时,可以进行思想教有并给子他关心和帮助,这种方式类似于 “软件维护”也可以把他关进监狱,送去劳改,这种方式相当于软件的“再生工程”: 如果此人坏透顶了,就毙掉算了。 再生工程与维护的共同之处是没有抛弃原有的软件。如果把维护比作“修修补补” 那么再生工程就算是“痛改前非”。再生工程并不见得一定比维护的代价要高,但再生工 程在将来获取的利益却要比通过维护得到的多。 再生工程主要有三种类型:重构、逆向工程和前向工程 8.3.1重构 重构一般是指通过修改代码或数据以使软件符合新的要求。重构通常并不推翻原有 软件的体系结构,主要是改造一些模块和数据结构。重构的一些好处如下: (1)使软件的质量更高,或使软件顺应新的潮流(标准)。 (2)使软件的后续(升级)版本的生产率更高。 (3)降低后期的维护代价。 要注意的是,在代码重构和数据重构之后,一定要重构相应的文档。 8.3.2逆向工程 逆向工程来源于硬件世界。硬件厂商总想弄到竞争对手产品的设计和制造“奥秘”。 但是又得不到现成的档案,只好拆卸对手的产品并进行分析,企图从中获取有价值的东 西。我的很多同学从事集成电路设计工作,他们经常解剖国外的集成电路,甚至不作分 析就原封不动地复制该电路的版图,然后投入生产,并美其名日“反向设计”(Rev©rsc Design). 软件的逆向工程在道理上与硬件的相似。但在很多时候,软件的逆向工程并不是针 对竞争对手的,而是针对自己公司多年前的产品。期望从老产品中提取系统设计、需求 说明等有价值的信息。 8.3.3前向工程 前向工程也称预防性维护,由Mlr倡导。他把这个术语解释成“为了明天的需要 把今天的方法应用到昨天的系统上”。[Pressman1999 乍看起来,主动去改造一个目前运行得正常的软件系统简直就是“惹事生非”。但是 软件技术发展如此迅速,与其等待一个有价值的产品逐渐老死,还不如主动去更新,以 获取更大的收益。其道理就同打预防性针一样。所以,预防性维护是“吃小亏占大便宜
3 8.3 再生工程 再生工程主要出于如下愿望:(1)在商业上要提高产品的竞争力;(2)在技术上要 提高产品的质量。但这种愿望无法靠软件的维护来实现,因为:(1)软件的可维护性可 能极差,实在不值得去做;(2)即使软件的可维护性比较好,但也只是治表不治本。再 生工程干脆对已有软件进行全部或部分的改造,赋予软件新的活力。 在对待一个不良之徒时,可以进行思想教育并给予他关心和帮助,这种方式类似于 “软件维护”;也可以把他关进监狱,送去劳改,这种方式相当于软件的“再生工程”; 如果此人坏透顶了,就毙掉算了。 再生工程与维护的共同之处是没有抛弃原有的软件。如果把维护比作“修修补补”, 那么再生工程就算是“痛改前非”。再生工程并不见得一定比维护的代价要高,但再生工 程在将来获取的利益却要比通过维护得到的多。 再生工程主要有三种类型:重构、逆向工程和前向工程。 8.3.1 重构 重构一般是指通过修改代码或数据以使软件符合新的要求。重构通常并不推翻原有 软件的体系结构,主要是改造一些模块和数据结构。重构的一些好处如下: (1)使软件的质量更高,或使软件顺应新的潮流(标准)。 (2)使软件的后续(升级)版本的生产率更高。 (3)降低后期的维护代价。 要注意的是,在代码重构和数据重构之后,一定要重构相应的文档。 8.3.2 逆向工程 逆向工程来源于硬件世界。硬件厂商总想弄到竞争对手产品的设计和制造“奥秘”。 但是又得不到现成的档案,只好拆卸对手的产品并进行分析,企图从中获取有价值的东 西。我的很多同学从事集成电路设计工作,他们经常解剖国外的集成电路,甚至不作分 析就原封不动地复制该电路的版图,然后投入生产,并美其名曰“反向设计”(Reverse Design)。 软件的逆向工程在道理上与硬件的相似。但在很多时候,软件的逆向工程并不是针 对竞争对手的,而是针对自己公司多年前的产品。期望从老产品中提取系统设计、需求 说明等有价值的信息。 8.3.3 前向工程 前向工程也称预防性维护,由 Miller 倡导。他把这个术语解释成“为了明天的需要, 把今天的方法应用到昨天的系统上”。[Pressman 1999] 乍看起来,主动去改造一个目前运行得正常的软件系统简直就是“惹事生非”。但是 软件技术发展如此迅速,与其等待一个有价值的产品逐渐老死,还不如主动去更新,以 获取更大的收益。其道理就同打预防性针一样。所以,预防性维护是“吃小亏占大便宜
的事。 8.4小结 大学科研机构里的软件维护工作恐怕是做得最差的了。几乎每一批新的研究生都会 把毕业生留下的软件臭骂一通,然后全部推到重做。到他毕业该走时,就轮到别人骂他 的工作了。如此轮回,最终没有什么成果留下。 如果希望软件系统能活下,必须要对它进行维护。如果希望软件系统有效益,则必 须设法降低维护的代价
4 的事。 8.4 小 结 大学科研机构里的软件维护工作恐怕是做得最差的了。几乎每一批新的研究生都会 把毕业生留下的软件臭骂一通,然后全部推到重做。到他毕业该走时,就轮到别人骂他 的工作了。如此轮回,最终没有什么成果留下。 如果希望软件系统能活下,必须要对它进行维护。如果希望软件系统有效益,则必 须设法降低维护的代价