软件的可复用性和维护性
一、软件系统的可维护性
无论对于软件的开发者或是维护者,面向对象的软件系统在支持可维护性的同时,提高系统的可复用性都是很重要的。
一个可维护较好的系统,应当允许维护工作容易,准确,安全和简单的形式进行。但是好多软件系统都不具备这样的特性。
导致一个软件可维护性底的真正原因是:过于僵硬,过于脆弱,复用率低,黏度过高。
(1). 过于僵硬
很难给系统增加一个新的特性,哪怕是很小的一个特性。
(2).过于脆弱
对于一个地方的修改往往是看上去没有什么关系的导致别的地方故障。
(3).复用率低
复用就是指一个软件的组成部分不仅能在同一个项目的不同地方使用甚至在其他项目中使用。
(4).黏度过高
有时候一个改动可以牺牲系统原始的设计意图和框架设计,也可以保存。第二种当然对系统有利,第一种是权益之计,破坏长远利益。一个系统,总是使得第一种方式比第二种方式容易,就是黏度过高。
一个好的系统应该具备如下性质:可扩展性,灵活性,可插入性。
(1).可扩展性
新的特性很容易的插入到系统中去。
(2).灵活性
可以使代码平稳的修改,不会波及到其它模块。
(3).可插入性
可以很容易的将一个类抽出去,同样很容易的可以将有同样接口的类加进来。
二、系统的可复用性
1、复用的重要性
软件的复用的好处有:
①较高的生产效率;②较高的软件质量;③恰当使用复用可以改善系统的可维护性。更重要的是,复用与系统的可维护性有直接的关系。
2、传统的复用
在传统的理解中,复用有一下几种方式:①代码的黏贴复用;②算法的复用;③数据结构的复用;
3、可维护性与复用的关系
传统的复用方案的一个致命缺陷就是复用常常是以破坏可维护性为代价的。比如两个模块A和B同事使用另一个模块C中的功能。那么当A需要C增加一个新的行为的时候,B有可能不需要、甚至不允许C增加这个新行为。如果坚持使用复用,就不得不以系统的可维护性为代价;而如果从保持系统的可维护性出发,就只好放弃复用。可维护性与可复用性是有共同性的两个独立特性,他们就像是两只同时在奔跑的兔子,方向并不能一直保持一致。
因此,一个重要的概念就是支持可维护性的复用,也就是在保持甚至提高系统的可维护性的同时,实现系统的复用。
4、面向对象设计的复用
在面向对象的语言中,数据的抽象化、继承、封装和多态性是几项最重要的语言特性,这些特性使得一个系统可以在更高的层次上提供可复用性。数据的抽象化和继承关系使得概念和定义可以复用;多态性使得实现和应用可以复用;而抽象化和封装可以保持和催进系统的可维护性。这样一来,复用的焦点不再集中在函数和算法等具体实现细节上,而是集中在最重要的含有宏观商业逻辑的抽象层次上。换言之,复用的焦点发生了“倒转”。
发生复用焦点的倒转并不是因为实现细节的复用不再重要,而是因为这些细节上的复用往往已经做得很好,而且抽象层次是比这些细节更值得强调的复用焦点,因为它们是在提供复用性的同时保持和提高可维护性的关键。
既然抽象层次是一个应用系统做战略性判断和决定的地方,那么抽象层次就应当是较为稳定的,应当是复用的重点。如果抽象层次的模块相对独立于具体层次的模块的话,那么具体层次内部的变化就不会影响到抽象层次的结构,所以抽象层次的模块的复用就会较为容易。
5、对可维护性的支持
首先,恰当的提高系统的可复用性,可以提高系统的可扩展性。允许一个具有同样接口的新的类替代旧的类,是对抽象接口的复用。客户端依赖于一个抽象的接口,而不是一个具体实现类,使得这个具体类可以被另一个具体类所取代,而不影响到客户端。 系统的可扩展性是有“开-闭”原则,里氏代换原则、依赖倒转原则和组合/聚合复用原则所保证的。
其次,恰当的提高系统的可复用性,可以提高系统的灵活性。在一个设计得当的系统中,每一个模块都相对于其他模块独立存在,并只保持与其他模块的尽可能少的通信。这样一来,在其中某一个模块发生代码修改的时候,这个修改的压力不会传递到其他的模块。系统的灵活性是由“开-闭”原则、迪米特法则、接口隔离原则做保证的。
最后,恰当的提高系统的可复用性,可以提高系统的可插入性。在一个符合“开-闭”原则的系统中,抽象层封装了与商业逻辑有关的重要行为,这些行为的具体实现有实现层给出。当一个实现类不再满足需要,需要以另一个实现类取代的时候,系统的设计可以保证旧的类可以被“拔出”,新的类可以被“插入”。系统的可插入性是有“开-闭”原则、里氏代换原则,组合/聚合复用原则以及依赖倒转原则保证的。
在一个像java这样的面型对象的语言中,数据的抽象化,继承,封装和多态性是几项重要的语言特性,这些特性使得一个系统可以再更高层次上提供可复用性。数据的抽象化和继承关系使得概念和定义可以复用;多态性使得实现和应用可以复用;而抽象化和封装可以保持和促进系统的可维护性。这样,复用的焦点不在集中在函数和算法等具体实现细节上,而是集中在最终的含有商业逻辑的抽象层次上。