设计可复用类
上节复用类和接口介绍了继承与重写,重载,参数多态与泛型编程等方法。
行为子类型与Liskov替换原则
子类型多态:客户端可用统一的方式处理不同类型的对象 。来看下面这个例子
Animal a = new Animal();
Animal c1 = new Cat();
Cat c2 = new Cat();
在可以使用a的场景,都可以用c1和c2代替而不会有任何问题。
a = c1;
a = c2;
Let q(x) be a property provable about objects x of type T, then q(y) should be provable for objects y of type S where S is a subtype of T. ——Barbara Liskov
Java中编译器执行的规则(静态类型检查):
子类型可以增加方法,但不可删
子类型需要实现抽象类型中的所有未实现方法
子类型中重写的方法必须有相同或子类型的返回值
子类型中重写的方法必须使用同样类型的参数
子类型中重写的方法不能抛出额外的异常
Liskov Substitution Principle (LSP)也适用于指定的行为(methods):
更强的不变量
更弱的前置条件
更强的后置条件
Example 1 for Behavioral subtyping (LSP)
子类实现相同的不变量(同时附加了一个)
重写方法有相同的前置条件和后置条件
Example 2 for Behavioral subtyping (LSP)
子类实现相同的不变量(同时附加了一个)
重写方法start有更弱的前置条件
重写方法brake有更强的后置条件
LSP是子类型关系的一个特殊定义,称为(强)行为子类型化。在编程语言中,LSP依赖于以下限制:
前置条件不能强化
后置条件不能弱化
不变量要保持
子类型方法参数:逆变
子类型方法的返回值:协变
异常类型:协变
Covariance (协变):
父类型->子类型:越来越具体specific 。
返回值类型:不变或变得更具体 。
异常的类型:也是如此。
Contravariance (反协变、逆变):
父类型->子类型:越来越具体specific 。
参数类型:要相反的变化,要不变或越来越抽象。
这在Java中是不允许的,因为它会使重载规则复杂化。
几种不同的复用
(1)代码的复用
包括目标代码和源代码的复用。其中目标代码的复用级别最低,历史也最久,当前大部分编程语言的运行支持系统都提供了连接(Link)、绑定(Binding)等功能来支持这种复用。源代码的复用级别略高于目标代码的复用,程序员在编程时把一些想复用的代码段复制到自己的程序中,但这样往往会产生一些新旧代码不匹配的错误。想大规模的实现源程序的复用只有依靠含有大量可复用构件的构件库。如”对象链接及嵌入”(OLE)技术,既支持在源程序级定义构件并用以构造新的系统,又使这些构件在目标代码的级别上仍然是一些独立的可复用构件,能够在运行时被灵活的得新组合为各种不同的应用。
(2)设计的复用
设计结果比源程序的抽象级别更高,因此它的复用受实现环境的影响较少,从而使可复用构件被复用的机会更多,并且所需的修改更少。这种复用有三种途径,第一种途径是从现有系统的设计结果中提取一些可复用的设计构件,并把这些构件应用于新系统的设计;第二种途径是把一个现有系统的全部设计文档在新的软硬件平台上重新实现,也就是把一个设计运用于多个具体的实现;第三种途径是独立于任何具体的应用,有计划地开发一些可复用的设计构件。
(3)分析的复用
这是比设计结果更高级别的复用,可复用的分析构件是针对问题域的某些事物或某些问题的抽象程度更高的解法,受设计技术及实现条件的影响很少,所以可复用的机会更大。复用的途径也有三种,即从现有系统的分析结果中提取可复用构件用于新系统的分析;用一份完整的分析文档作输入产生针对不同软硬件平台和其它实现条件的多项设计;独立于具体应用,专门开发一些可复用的分析构件。
(4)测试信息的复用
主要包括测试用例的复用和测试过程信息的复用。前者是把一个软件的测试用例在新的软件测试中使用,或者在软件作出修改时在新的一轮测试中使用。后者是在测试过程中通过软件工具自动地记录测试的过程信息,包括测试员的每一个操作、输入参数、测试用例及运行环境等一切信息。这种复用的级别,不便和分析、设计、编程的复用级别作准确的比较,因为被复用的不是同一事物的不同抽象层次,而是另一种信息,但从这些信息的形态看,大体处于与程序代码相当的级别。
由于软件生产过程主要是正向过程,即大部分软件的生产过程是使软件产品从抽象级别较高的形态向抽象级别较低的形态演化,所以较高级别的复用容易带动较低级别的复用,因而复用的级别越高,可得到的回报也越大,因此分析结果和设计结果在目前很受重视。用户可购买生产商的分析件和设计件,自己设计或编程,掌握系统的剪裁、扩充、维护、演化等活动
复用的意义
1)提高生产率
软件复用最明显的好处在于提高生产率,从而减少开发代价。牛产率的提高不仅体现在代码开发阶段。在分析、设计及测试阶段同样可以利用重用来节省开销。
2)减少维护代价
这是软件复用的一个重要优点需要维护的部分也减少了。
3)提高互操作性
一个更为重要的好处在于使用经过检验的构件,减少丁可能的错误,同时软件4个更为重要的好处在于软件复用技术提高了系统问的互操作性。基于复用技术生产的幻件系统。大多使用相同的接口对外实现通信。因此,系统将更为有效地实现与其他系统之间的互操作。
4)支持快速原型
软件复用技术的另一个好处在于对快速原型的支持,即可以快速构造出系统可操作的模型,以获得用户对系统功能的反馈。利用可复用构件可以快速有效地构造出应用程序的原型。
5)减少培训开销
软件复用技术还有利于减少培训开销,即雇员在熟悉任务时所需的非正式的开销程师将使用一个可复用构件库,其中的构件都是他们所熟悉和精通的。