软件的可维护性和可复用性

        

      通常认为,一个易于维护的系统是一个复用率较高的系统,而一个复用性较好的系统就是一个易于维护的系统,但实际上可维护性和可复用性是两个独立的目标,方向并不是总是一致的,对于面向对象的软件系统的设计来说,在支持可维护性(Maintainability)的同时,提高系统的可复用性(Reuseability)是一个核心问题。

                                                                   软件的可维护性

       导致一个软件的可维护性较低的原因:

    过于僵硬(Rigidity):

      很难在一个软件系统里加入新的特性,一旦加入新的特性就会影响到其他模块的功能,最后会变成跨越几个模块的改动,由于设计上的缺陷,导致不敢轻易往原有的系统中添加新的特性的僵硬化的情况。

    过于脆弱(Fragility):

      修改已有的代码时过于脆弱,对一个地方的修改,往往会导致看起来没有什么关系的另一个地方发生故障,尽管在修改前,设计师会竭尽所能预测可能的故障点,但是在修改完成之前,系统的原始设计师甚至都无法预测到可能会波及的地方,这种一碰就碎的情况,就是软件系统过于脆弱。 

    复用率低(Immobility):

      所谓复用,就是指一个软件的组成部分,可以在一个项目的不同地方甚至不同的项目中重复使用。每当程序员发现一段代码、函数、模块的功能可以在新模块或者新系统中使用,但是发现这些现存的代码、函数、模块依赖于一大堆其他的东西,以至于很难将他们分开。最后,他们发现最好的办法就是不去碰这些东西,而是重写自己的代码。

这样的系统存在复用率低的问题。 

    黏度过高(Viscosity):

有的时候,一个改动可以以保持原有的设计意图和原有的设计框架的方式进行,也可以以破坏原始意图和框架的方式进行。第一种办法无疑会对系统的未来有利,第二种办法是权宜之计,可以解决短期问题,但是会牺牲中长期利益。

如果第二种办法比第一种办法容易得多的话,程序员就有可能牺牲长期利益,采取权宜之计,在一个通用的逻辑种建立一种特例,以便解决眼前的问题。

一个系统设计,如果总是使得第二种办法比第一种办法来得容易,说明黏度过高。一个黏度过高的系统会诱使维护她的程序员采取错误的维护方案,并惩罚采取正确方案的程序员。

 

    设计的目标:

    一个好的系统设计应该具备如下的性质:

    可扩展性(Extensibility):

新的特性很容易加入到系统中去,就是可扩展性,就是“过于僵硬”反面。

    灵活性(Flexibility):

      可以允许代码修改平稳地发生,而不会波及到很多其他的模块。灵活性就是“过于脆弱”的反面。

    可插入性(Pluggability):

      可以很容易的将一个类抽出去,同时将一个有同样接口的类加入进来,这就是可插入性。 

                                                                                   软件的可复用性

    复用的重要性: 

较高的生产率,较高的软件质量,恰当的复用可以改善系统的可维护性。

    传统的复用:

代码的剪贴复用,算法的复用,数据结构的复用。

    面向对象的设计的复用:

面向对象的语言中,数据的抽象化、继承、封装和多态的特性是几项最重要的语言特性,这些特性使得一个系统可以在更高的层次上提供可复用性。数据的抽象化和继承可以使得概念和定义得以复用,多态性使得实现和应用可以复用,而抽象化和封装可以保持和促进系统的可维护性。这样,复用的焦点不再集中在函数、算法等具体的实现细节上,而是集中在最重要的具有宏观商业逻辑的抽象层次上。

抽象层是一个应用系统做战略性判断和决定的地方,那么抽象层次应当是较为稳定的,应当是复用的重点。如果抽象层次的模块相对独立于具体层次的模块,那么具体层次的变化不会影响到抽象层次的,所以抽象层次模块的复用会比较容易。

在面向对象的设计里,可维护性复用是以设计原则和设计模式为基础的。

    对可维护性的支持:

首先,适当地提高系统的可复用性,可以提高系统的可扩展性。允许一个具有同样接口新类代替旧的类,是对抽象接口的复用。客户端依赖于一个抽象的接口,而不是一个具体的实现类,使得这个具体的类可以被其他的类取代,而不需要修改客户端的代码。

系统的可扩展性是由“开-闭”原则、里氏代换原则、依赖倒转原则和组合/聚合复用实现的。

其次,适当地提高系统的可复用性,可以提高系统的灵活性。在一个设计得当的系统中,每一个模块都相对于其他模块独立存在,并且保持与其他模块尽可能少的通信。这样一来,在其中一个模块的代码发生修改的时候,这个修改的压力不会传递到其他模块。

系统的灵活性是有“开-闭“原则、迪米特法则、接口隔离原则保证的。

最后,适当地提高系统的可复用性,可以提高系统的可插入性,在一个符合“开-闭“原则的系统中,抽象层封装了与商业逻辑有关的重要行为,这些行为的具体实现由实现层给出。当一个实现类再满足需要,需要以另一个实现类取代的时候,系统的设计就可以保证旧的类可被拔出,新类可以被插入。

可插入性有“开-闭“原则、里氏代换原则、组合/聚合复用原则、依赖倒转原则保证。 

设计原则:

开-闭原则:OCP

里氏代换原则:LSP

依赖倒转原则:DIP

接口隔离原则:ISP

组合/聚合复用原则:CARP

迪米特法则:LOP

这些原则首先都是复用的原则,遵循这些原则可以提高系统的可复用性,同时提高系统的可维护性。

            

 

posted @ 2009-03-08 21:30  忠歌  阅读(512)  评论(0)    收藏  举报