通常认为,一个易于维护的系统,就是复用率较高的系统;而一个复用性较好的系统,就是一个易于维护的系统。但是实际上,可维护性和可复用性是两个独立的目标,就像两只奔跑的兔子一样,并不总是方向一致的。
对于面向对象的软件系统设计来说,在支持可维护性的同时,提高系统的可复用性是一个核心的问题。
一、软件系统的可维护性
软件开发是一个比较快速的过程,一般只需要半年时间。但是系统的维护却是一个长期的过程,需要很多年。并且在一个软件项目的周期内,花费在维护上面的钱,是花费在原始开发上面的钱的两倍。
作为一个开发人员必须要认识到,软件的维护就是软件的再生。一个好的软件设计,必须能够允许新的设计要求以较为容易和平稳的方式加入到已有的系统中去,从而使这个系统能够不断的焕发青春。 一个可维护性较好的系统,应当允许维护工作能够以容易、准确、安全和经济的形式进行。
1、一个典型的软件生命周期
一个软件项目开始了,系统设计师拿到了系统的设计要求,设计师就会开始系统设计;这个系统毫无疑问将是一个优美的系统。系统的美,首先存在于设计师的头脑中,然后存在于设计图纸上,然后变成一个原型系统,最后变成一个真实的、有血有肉、可以交付客户使用的产品。
设计师喜欢看着他运行,程序员喜欢它的每一个功能键和图形视窗,而客户终于看到花出去的钱变成了实现。这个时候,这个系统就像一个美少女一样,毫无疑问是纯净的、优美的、动人心弦的。
但是不久事情就开始发生变化。客户看了运行的系统,又提出了一些“小小的”修改要求,这些要求都是客户在提出系统设计要求的时候遗忘的一些“小”问题。设计师讨论之后,给出了一些设计上面的修改。由于这些修改于现有系统的设计并不一定相容,所以设计师不得不采取一些权宜之计,是的这些修改看上去就像一个美丽少女脸上的青春痘。但是好像所有的软件都不能避免这些“青春痘”似的东西的出现,所以一切还不是很糟。
可是事情并没有就此结束,这些小的痘痘越来越多,而且其中有一些变成了系统的肿瘤。随着时间的流逝,这些肿瘤变成了系统中最主要的组成部分,当初的美少女变成了一个丑陋不堪,日渐“腐烂”的代码,以至于没有人愿意去维护他。人们把它叫做遗留系统,而不得不去维护这个遗留系统的人们,会天天诅咒设计这个系统的设计师:是谁设计出这么丑陋的一个东西??!!
经过一段漫长的时间后,“苦难”终于要结束了!在抱怨了软件系统的维护之昂贵之后,客户决定投入一笔资金,一个新的系统将被设计出来,而这个新系统将具有这个正在死去的系统的所有功能(当然还包括一些新的功能),并且取代这个已经“腐烂”的系统。
但是仔细想想,这个新系统会面临怎样的命运呢?也许这仅仅是下一个轮回的开始。
2、导致这种情况的真正原因
导致一个软件设计的可维护性较低,也就是说会随着性能要求的变化而“腐烂”的真正原因有四个:过于僵硬、过于脆弱、复用率低、黏度过高。
①过于僵硬:很难在一个软件系统里加入一个新的性能,哪怕是很小的都很难。这是因为加入一个新新能,不仅仅意味建造一个独立的新模块,而且因为这个新性能会波及很多其他模块,最后变成跨越几个模块的改动。使得一个起初只需要几天的工作,最后变成持续好久的作战。由于这种设计上的缺陷,使得项目经理不敢轻易向系统加入新功能。这就造成一个软件系统一旦做好,就不能增加新功能的僵化情况。
②过于脆弱:与软件过于僵硬同时存在的,是软件系统在修改已有代码时过于脆弱。对一个地方的修改,往往会导致看上去没有什么关系的另一个地方发生故障。尽管在修改之前,设计师们会竭尽所能预测可能的故障地点,地那是在修改完成之前,系统的原始设计师们甚至都无法确切预测到可能会波及到的地方。这种一碰就碎的情况,造成软件系统过于脆弱。
③复用率低:所谓复用,就是指一个软件的组成部分,可以在同一个项目的不同地方甚至另一个项目中重复使用。每当程序员发现一段代码,函数,模块所做的事情是可以在新的模块、或者新系统中使用的时候,他们总会发现,这些已有的代码依赖于一大堆其他的东西,以至于很难将他们分开。最后,他们发现最好的办法就是不去“碰”这些已有的东西,而是重新写自己的代码。他们可能会使用源代码黏贴的办法,以最原始的复用方式,节省一些时间。这样的系统就有复用率低的问题。
④黏度过高:有的时候,一个改动可以保持原始的设计意图和原始设计框架的方式进行,也可以破坏原始意图和框架的方式进行。第一种办法无疑会对系统的未来有利,第二种办法是权宜之计,可以解决短期问题,但是会牺牲中长期的利益。
如果第二种办法比第一种办法容易很多的话,程序员就有可能牺牲中长期的利益,采取权宜之计:在模块中搭建一个短路桥,或者在一个通用的逻辑中制造一个特例,以便解决眼前的需要。
一个系统设计,如果总是使得第二种办法比第一种办法容易,就叫做年度过高。一个黏度过高的系统会诱使维护它的程序员采取错误的维护方案,并惩罚采取正确维护方案的程序员。
3、设计的目标
一个好的系统设计应该有如下的性质:可扩展性、灵活性、可插入性。这三条性质就是一个系统设计应当达到的目标。
①可扩展性:新的性能可以很容易的加入到系统中去,就是可扩展性。这就是系统“过于僵硬”的属性的反面。可扩展性要求一个新系统的加入,应该不会影响原有的功能,如果不是,则这个系统就不是扩展型很好的系统。
②灵活性:可以允许代码修改平稳的发生,而不会波及到很多其他的模块,这就是灵活性。比如一辆汽车的空调发生了故障,技师修理了空调。如果空调修好之后,发现系统的发动机不能启动了,这就不是一个灵活的系统。
③可插入性:很容易的讲一个类抽出去,同时将另一个有同样接口的类加入进来,这就是可插入性。比如应该可以很容易的将一辆汽车的防撞气囊取出来,换上一个新的。如果气囊拿出来后,汽车的传动杆不工作了,那么这个系统就不是一个可插入性很好的系统。
那么,怎样才能做出一个符合这三项要求的设计呢?关键是恰当的提高软件的可维护性和可复用性。
二、系统的可复用性
1、复用的重要性
软件的复用的好处有:①较高的生产效率;②较高的软件质量;③恰当使用复用可以改善系统的可维护性。更重要的是,复用与系统的可维护性有直接的关系。
2、传统的复用
在传统的理解中,复用有一下几种方式:①代码的黏贴复用;②算法的复用;③数据结构的复用;
3、可维护性与复用的关系
传统的复用方案的一个致命缺陷就是复用常常是以破坏可维护性为代价的。比如两个模块A和B同事使用另一个模块C中的功能。那么当A需要C增加一个新的行为的时候,B有可能不需要、甚至不允许C增加这个新行为。如果坚持使用复用,就不得不以系统的可维护性为代价;而如果从保持系统的可维护性出发,就只好放弃复用。可维护性与可复用性是有共同性的两个独立特性,他们就像是两只同时在奔跑的兔子,方向并不能一直保持一致。
因此,一个重要的概念就是支持可维护性的复用,也就是在保持甚至提高系统的可维护性的同时,实现系统的复用。
4、面向对象设计的复用
在面向对象的语言中,数据的抽象化、继承、封装和多态性是几项最重要的语言特性,这些特性使得一个系统可以在更高的层次上提供可复用性。数据的抽象化和继承关系使得概念和定义可以复用;多态性使得实现和应用可以复用;而抽象化和封装可以保持和催进系统的可维护性。这样一来,复用的焦点不再集中在函数和算法等具体实现细节上,而是集中在最重要的含有宏观商业逻辑的抽象层次上。换言之,复用的焦点发生了“倒转”。
发生复用焦点的倒转并不是因为实现细节的复用不再重要,而是因为这些细节上的复用往往已经做得很好,而且抽象层次是比这些细节更值得强调的复用焦点,因为它们是在提供复用性的同时保持和提高可维护性的关键。
既然抽象层次是一个应用系统做战略性判断和决定的地方,那么抽象层次就应当是较为稳定的,应当是复用的重点。如果抽象层次的模块相对独立于具体层次的模块的话,那么具体层次内部的变化就不会影响到抽象层次的结构,所以抽象层次的模块的复用就会较为容易。
5、对可维护性的支持
首先,恰当的提高系统的可复用性,可以提高系统的可扩展性。允许一个具有同样接口的新的类替代旧的类,是对抽象接口的复用。客户端依赖于一个抽象的接口,而不是一个具体实现类,使得这个具体类可以被另一个具体类所取代,而不影响到客户端。 系统的可扩展性是有“开-闭”原则,里氏代换原则、依赖倒转原则和组合/聚合复用原则所保证的。
其次,恰当的提高系统的可复用性,可以提高系统的灵活性。在一个设计得当的系统中,每一个模块都相对于其他模块独立存在,并只保持与其他模块的尽可能少的通信。这样一来,在其中某一个模块发生代码修改的时候,这个修改的压力不会传递到其他的模块。系统的灵活性是由“开-闭”原则、迪米特法则、接口隔离原则做保证的。
最后,恰当的提高系统的可复用性,可以提高系统的可插入性。在一个符合“开-闭”原则的系统中,抽象层封装了与商业逻辑有关的重要行为,这些行为的具体实现有实现层给出。当一个实现类不再满足需要,需要以另一个实现类取代的时候,系统的设计可以保证旧的类可以被“拔出”,新的类可以被“插入”。系统的可插入性是有“开-闭”原则、里氏代换原则,组合/聚合复用原则以及依赖倒转原则保证的。
这就是说,通过设计原则的灵活运用,是可以提高一个系统的可维护性同时,提高系统的可复用性的。灵活的使用设计原则进行系统设计,就可以抓到这两只同时在奔跑的兔子。
参照:《java与模式》
相关推荐
软件的可维护性与可复用性.doc
1、 良好的可复用性。开发同类项目的次数与开发新项目的时间成反比,谁也不愿做重复劳动吧 。 2、 易维护。基本上不用花太大的精力跟维护人员讲解,他们可以自己读懂源程序并修改了,要不然开发的系统越多,你的...
为了增强在构件组装过程中连接件的复用性,根据体系结构层的异常处理技术和理想容错构件的特点,提出了用四个基本连接件及其相互组合来实现构件间的连接,并将这一技术应用到理想容错构件结构中。相关的实践活动表明...
移动广告中可复用工作流的设计与实现,王宁,李炜,针对工作流管理系统在移动广告管理系统中面临的过程定义利用率低、可维护性差的问题,借鉴软件复用的思想,针对移动广告审批流程
第三,适当的使用复用可以改善系统的可维护性。复用不仅仅是代码的复用,代码复用只是复用的初等形式传统的复用:代码的剪贴复用,算法的复用,数据结构的复用。在一个面向对象的语言中,数据的抽象化、继承、封装和...
软件工程的目标是:在给定成本、进度的前提下,开发出具有可修改性、有效性、可靠性、可理解性、可维护性、可重用性、可适应性、可移植性、可追踪性和可互操作性并且满足用户需求的软件产品。追求这些目标有助于...
833提高软件可维护性的方法 84维护的副作用 85软件再工程 851软件再工程与逆向工程的概念 852实施软件再工程的原因 853软件再工程技术 86习题 第2篇UML与面向对象的软件工程 第9章UML简介 91...
基于部件的软件复用技术可以大大减少软件开发所需的时间和费用,提高软件的灵活性、可维护性、可靠性,缩短应用软件的开发周期,是21世纪软件技术发展的一个趋势,也是目前软件业的热点之一。在对现有各种报表系统与构件...
硕士论文 面向方面程序设计,软件横切关注点,IJML,重构,可维护性、可复用性
6.软件质量衡量标准:功能性、可靠性、可使用行、效率、可维护性和可移植性。 软件生存期大体可分为如下几个阶段:软件定义,软件开发,运行维护。 7.软件生存期模型:是从软件项目需求定义直至软件运行维护为止,...
" "可维护性:软件维护(主要是指软件错误的修改、遗漏功能的添加等)的难" "易程度。 " " " "11.6用你自己的话描述软件体系结构。 " " " "答:软件体系结构定义为根据结构组织模式构成的软件系统族,表达了部件" ...
目标:在给定成本、进程的前提下、开发具有可修改性、有效性、可靠性、可理解性、可维护性、可重用性、可适应性、可移植性、可追踪性、可互操作性并满足用户需要的软件产品。 2、常见的软件开发方法包括: (1)结构...
10.2软件可维护性 10.3软件维护的实施 10.3.1 维护机构 10.3.2维护申请报告 10.3.3软件维护工作流程 10.3.4维护记录 10.3.5维护评价 10.4对老化系统的维护 10.5逆向工程与再工程 10.6软件配置管理 10.6.1 ...
第12章可依赖性与信息安全性描述 12.1风险驱动的需求描述 12.2安全性描述 12.2.1危险识别 12.2.2危险评估 12.2.3危险分析 12.2.4风险降低 12.3可靠性描述 12.3.1可靠性度量 12.3.2非功能性的可靠性需求 12.3.3功能...
3.3.5 可复用性与可扩充性 3.4 质量检查 3.5 小结 第四章 可行性分析与需求分析 4.1可行性分析的要素 4.1.1 经济 一、成本——收益分析 二、短期——长远利益分析 4.1.2 技术 4.1.3 社会环境 4.1.4 人 4.2 可行性...
为了增强在构件组装过程中连接件的复用性,根据体系结构层的异常处理技术和理想容错构件的特点,提出了用四个基本连接件及其相互组合来实现构件间的连接,并将这一技术应用到理想容错构件结构中。相关的实践活动表明...
1. 软件 软件是计算机系统中与硬件相互依存的部分,它是包括程序、数据及相关文档的完 整集合。 2. 软件危机 软件危机是指在计算机软件的开发和维护过程中所遇到的一系列严重问题。 3. 软件工程 软件工程是研究和...