软件复用(SoftWare Reuse)是将已有软件的各种有关知识用于建立新的软件,以缩减软件开发和维护的花费。软件复用是提高软件生产力和质量的一种重要技术。早期的软件复用主要是代码级复用,被复用的知识专指程序,后来扩大到包括领域知识、开发经验、设计决定、体系结构、需求、设计、代码和文档等一切有关方面。
软件复用的思想
将软件看成是由不同功能部分的“组件”所组成的有机体,每一个组件在设计编写时可以被设计成完成同类工作的通用工具,这样,如果完成各种工作的组件被建立起来以后,编写一特定软件的工作就变成了将各种不同组件组织连接体来的简单问题,这对于软件产品的最终质量和维护工作都有本质性的改变。
软件复用的级别
- 代码级复用:就是通过编写大量的公共类,公共函数等等,供开发人员直接使用。
- 组件级复用:通过将功能的组件化封装,对外提供一组或多组的API接口。
- 模块级复用:在我们开发的项目或者产品中,会发现大量重复的功能模块,比如用户管理,机构管理等等,如果我们在这些模块设计的时候,注重一下扩展性,那么可以应用到有其它类似功能的项目中。在这个级别需要一定的项目的积累,否则在模块功能上以及实用性上会遭遇风险。
- 构架级复用:构架级在设计概念上最为高级的一种。它相当于一个平台或者思想,在这个平台上,可以开发出根据此平台思想稳定而又高效的软件产品。打个比方,数据库中的设计范式可以看成是一个小的构架,你按照范式来设计数据库,一般来说设计质量是有保证的。再举个例子,Windows中的消息机制也算是一个构架,就是说在 Windows中所有运行的程序都遵循它的这个机制,并且在这个机制的保证下,运行的顺畅良好,Linux中的IP Chains也是一个非常优秀的网络防火墙构架,这个构架中其他人可以方便进行外挂程序的嵌入。我拿我们将要开发的公司内部的物资管理系统来举个例子,在这个系统中,有一个很重要的功能,那就是审批,如何把审批这个功能做好,有良好的扩展性,并且可以沿用到其他的也有审批功能的项目中,就是一个我们需要思考的问题。
由于软件生产过程主要是正向过程,即大部分软件的生产过程是使软件产品从抽象级别较高的形态向抽象级别较低的形态演化,所以较高级别的复用容易带动较低级别的复用,因而复用的级别越高,可得到的回报也越大,因此分析结果和设计结果在目前很受重视。用户可购买生产商的分析件和设计件,自己设计或编程,掌握系统的剪裁、扩充、维护、演化等活动。
设计可复用的类
类是面向对象程序设计(OOP,Object-Oriented Programming)实现信息封装的基础。类是一种用户定义的引用数据类型,也称类类型。每个类包含数据说明和一组操作数据或传递消息的函数。类的实例称为对象。
类库技术是软件复用的基础,在软件开发过程中,程序员通过调用类库中的函数可以达到软件复用的目的。如:调用C++类库中的输入输出流函数可以实现输入输出的功能。
- 封装和信息隐藏
- 继承和重写
- 多态、子类和重载
- 泛型编程
- LSP原则
- 委派和组合
LSP原则
- 里氏替换原则的主要作用就是规范继承时子类的一些书写规则。其主要目的就是保持父类方法不被覆盖。
- 含义:子类必须完全实现父类的方法;子类可以有自己的个性;覆盖或实现父类的方法时输入参数可以被放大;覆盖或实现父类的方法时输出结果可以被缩小
委派和组合
- 功能:一个对象请求另一个对象
- 委派分为显性委派和隐形委派:
显性委派:将发送对象传递给接收对象;
隐性委派:由语言的成员查找规则。
API:应用接口编程
API是一些预先定义的函数,或指软件系统不同组成部分衔接的约定。用来提供应用程序与开发人员基于某软件或硬件得以访问的一组例程,而无需访问原码,或理解内部工作机制的细节。
- 远程过程调用(RPC):通过作用在共享数据缓存器上的过程(或任务)实现程序间的通信。
- 标准查询语言(SQL):是标准的访问数据的查询语言,通过通用数据库实现应用程序间的数据共享。
- 文件传输:文件传输通过发送格式化文件实现应用程序间数据共享。
- 信息交付:指松耦合或紧耦合应用程序间的小型格式化信息,通过程序间的直接通信实现数据共享。
- 建议:始终以开发API的标准面对任何开发任务;面向“复用”编程而不是面向“应用”编程。
- 难度:要有足够良好的设计,一旦发布就无法再自由改变。
- 编写API:1.API应该做一件事,且做得很好 2.API应该尽可能小,但不能太小 3.Implementation不应该影响API 4.类的设计:尽量减少可变性,遵循LSP原则 5.方法的设计:不要让客户做任何模块可以做的事情,及时报错。
框架
一组具体类、抽象类、及其之间的连接关系 开发者根据 framework的规约,填充自己的代码进去,形成完整系统。通常通过选择性覆盖来扩展框架;或者程序员可以添加专门的用户代码来提供特定的功能。我们从应用方面和目的方面给出框架的定义:
应用方面:框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法。
目的方面:框架是可被应用开发者定制的应用骨架。
为了增加代码的复用性,可以使用委派和继承机制。同时,在使用这两种机制增加代码复用的过程中,我们也相应地在不同的类之间增加了关系(委派或继承关系)。而对于一个项目而言,各个不同类之间的依赖关系就可以看做为一个框架。一个大规模的项目可能由许多不同的框架组合而成。
框架与设计模式
- 框架、设计模式这两个概念总容易被混淆,其实它们之间还是有区别的。构件通常是代码重用,而设计模式是设计重用,框架则介于两者之间,部分代码重用,部分设计重用,有时分析也可重用。在软件生产中有三种级别的重用:内部重用,即在同一应用中能公共使用的抽象块;代码重用,即将通用模块组合成库或工具集,以便在多个应用和领域都能使用;应用框架的重用,即为专用领域提供通用的或现成的基础结构,以获得最高级别的重用性。
- 框架与设计模式虽然相似,但却有着根本的不同。设计模式是对在某种环境中反复出现的问题以及解决该问题的方案的描述,它比框架更抽象;框架可以用代码表示,也能直接执行或复用,而对模式而言只有实例才能用代码表示;设计模式是比框架更小的元素,一个框架中往往含有一个或多个设计模式,框架总是针对某一特定应用领域,但同一模式却可适用于各种应用。可以说,框架是软件,而设计模式是软件的知识。
白盒框架和黑盒框架
白盒框架
- 白盒框架是基于面向对象的继承机制。之所以说是白盒框架,是因为在这种框架中,父类的方法对子类而言是可见的。子类可以通过继承或重写父类的方法来实现更具体的方法。
- 虽然层次结构比较清晰,但是这种方式也有其局限性,父类中的方法子类一定拥有,要么继承,要么重写,不可能存在子类中不存在的方法而在父类中存在。
- 通过子类化和重写方法进行扩展(使用继承)。
- 通用设计模式:模板方法。
- 子类具有主要方法但对框架进行控制。
- 允许扩展每一个非私有方法。
- 需要理解父类的实现。
- 一次只进行一次扩展。
- 通常被认为是开发者框架
黑盒框架
- 黑盒框架时基于委派的组合方式,是不同对象之间的组合。之所以是黑盒,是因为不用去管对象中的方法是如何实现的,只需关心对象上拥有的方法。
- 这种方式较白盒框架更为灵活,因为可以在运行时动态地传入不同对象,实现不同对象间的动态组合;而继承机制在静态编译时就已经确定好。
- 通过实现插件接口进行扩展(使用组合/委派)。
- 常用设计模式:Strategy, Observer 。
- 插件加载机制加载插件并对框架进行控制。
- 允许在接口中对public方法扩展。
- 只需要理解接口。
- 通常提供更多的模块。
- 通常被认为是终端用户框架,平台。