4-1主要讲述了软件的可复用性。这可以说是软件的一个质量目标,也是第三章ADT的一个应用。
一般来说,复用的等级有以下几种
1.源代码级别的复用。
2.模块级别的复用。例如类或者抽象类或者接口。
3.库级别的复用。例如API或者包。
4.系统级别的复用。例如框架。
对于软件的复用,有两个部分,首先是面向复用的编程,也就是开发类,开发出可以复用的软件,这是一种抽象产品。
然后是基于复用的编程,也就是利用已有的可复用软件搭建应用,这是一种使用类的方法。
对于软件类来说,显然是越抽象的软件类复用度越高,但是太过抽象的软件类往往无法拿来就用。
对于可复用的软件类,它有许多优点:
1.有很强的适应性且测试充分,不需要重复的软件测试,较为可靠。
2.可以降低开发人员的开发成本和开发时间。
3.可以使软件标准化,一致化,而且在不同的应用中保持一致。
当然它也有自己的缺点:
1.针对性不高,对于某些问题来讲,它的性能不高。
2.它的开发成本高于一般的程序。
对于可复用的软件的开发成本,如图所示,前期的开发成本显然是较高的,因为要满足适应性。但是后期可以大大降低开发成本与发时间。
·那么如何衡量软件的复用性,一般是从以下几个方面。
首先是复用机会和场合的多少,也就是应用的频率。
然后是复用的代价分为以下几个方面
1.搜索和获取的代价。
2.适配和扩展的代价。
3.实例化的代价。
4.与其他模块相互连接的代价。
对于代码的可复用性衡量标准,有以下几个。
1.小,简单。
2.与标准兼容。
3.灵活可变。
4.可扩展。
5.使用的泛型和参数化。
6.模块化。
7.变化的局部性。
8.稳定性。
9.拥有丰富的文档和帮助信息。
其实对于开发人员来说,最主要的复用是代码层面的,但是复用绝对不止代码,还有文档,数据,测试等等。
对于代码层面的复用,分为两种,一种是白盒复用,一种是黑盒复用。
白盒复用 | 黑盒复用 |
---|---|
源代码可见,可以进行修改或者扩展 | 源代码不可见 |
复制已有代码进行修改 | 只能通过API接口来使用 |
可定制化程度高 | 可适应性差 |
修改增加了软件复杂度 | 简单方便安全 |
复用的等级有以下几种:
1.代码复用。
也就是简单的对代码进行复制粘贴,这样的做法很容易导致代码存在于多个文件中,而且修改的时候很难集体修改,繁琐而且容易出错。
2.模块复用。
也就是从类的角度来复用 ,例如ADT。
显然这复用可以通过两种形式,一种是继承,也就是白盒复用,可以对类的方法进行修改与扩充。还有就是委托,直接调用类,是一种黑盒复用。
对于委托,分为显式委托和隐式委托,显示委托,也就是指直接调用指定的类。
隐式委托,是指使用者提出需求,但是不一定调用什么方法来执行需求。常见于电脑完成命令。
3.库的复用。
就是例如Java的编程中程序员用到了库文件,这种复用是通过API的。
4. 框架复用
框架就是一种由一组具体的类,抽象类以及它们之间的联系关系构成的骨架。
而开发者可以根据规约来填充自己的代码,形成一个完整的系统。
显然框架是一种领域知识的复用。
而且框架也分为白盒框架和黑盒框架。
白盒框架,与之前的相同,是一种通过代码层面的继承进行的框架扩展。
黑盒框架,就是通过实现特定的接口来进行框架的扩展。
框架的复用有一个很重要的原则,也就是可复用性原则,分为以下几个。
1.类型可变
也就是指泛型,需要适应不同的类型,而且要满足LSP原则,也就是子类可以替代父类。
2.实现可变
也就是ADT可以有多种不同的实现,也可以有不同的REP和AF,但是SPEC必须是相同的。
3.方法组合
复用必须提供完备的细粒性操作,来保证功能的完整性,不同的场景下可以复用不同的操作或者组合。
4.表示独立性
也就是信息的隐藏,也就是内部的具体实现是不能影响外部的。
5.共性抽取
也就是将共同的行为抽象出来,形成父类或者抽象类,指可复用实体。
最后讲讲LSP原则,也就是可替换原则。
要实现这个原则,就是要做到可以用到父类的地方,一定可以使用子类。
只需要做到以下几点:
1.比起父类,子类的前置条件不能更强。
2.比起父类,子类的后置条件不能更弱。
3.比起父类,子类的不变量不能更弱。
4.比起父类,子类型的方法参数只能逆变或者相同。
5.子类型的返回值只能协变或者相同。
6.子类型的异常类型只能协变,也就是不允许抛出比父类更多的异常。