4-1可复用性的度量、形态与外部表现

▪ 软件复用的优缺点
▪ 再利用组件
▪ 通用可重用组件的特性

大纲
▪ 什么是软件重用?
▪ 如何衡量“可重用性”?
▪ 可重用组件的级别和形态
-源代码级重用:
模块级别的复用:类/抽象类/接口
库级别的复用:API/包
系统级别的复用:框架
▪ 可重用性的外部观察
-类型变化
-例行分组
-实现变化
-表示独立
-分解常见行为

1什么是软件重用?
▪ 软件重用是使用现有软件组件实现或更新软件系统的过程。▪ 软件重用的两个视角
——创建:以系统的方式创建可重用的资源(为重用而编程——使用:将资源重用为创建新系统的构建块(为重用而编程
▪ 为什么要重复使用?
——“创造可重复使用而非短暂的艺术品的动力具有审美、智力和经济动机,是人类对永生的渴望的一部分。
–它将人类与其他生物区分开来,将文明与原始社会区分开来”(Wegner,1989)。

4-1可复用性的度量、形态与外部表现
为什么要重用?
▪ 重用具有成本效益和及时性,可以生产出更可靠、更高效的软件)
▪ 再利用产生可靠的软件,在一段时间内被调试并重用,是建立稳定子系统的基础。
▪ 重复使用会产生标准化的效果
—图形用户界面库的重复使用会在应用程序中产生一致外观和感觉。
–与常规、连贯的设计保持一致。

再利用成本
▪ 可重用的组件应该以一种明确定义的、开放的方式设计和构建,具有简明的接口规范、可理解的文档,并且着眼于将来的使用。
做到这些,需要代价
▪ 重用是昂贵的:它涉及跨组织、技术和过程的变更,以及支持这些变更的工具的成本,以及培训人员使用新工具和变更的成本

4-1可复用性的度量、形态与外部表现
开发可复用的软件

▪ 可重用组件的开发成本高于特定等价组件的开发成本。这种额外的可重用性增强成本应该是一个组织而不是一个项目成本。
▪ 通用组件的空间效率可能较低,执行时间可能比它们的特定等效组件更长。

4-1可复用性的度量、形态与外部表现
▪ 必须开发和维护用于架构、设计、文档和代码的组件管理工具,如存储库。可复用软件库,对其进行有效的管理 ▪ 一个关键问题:组件可能需要添加额外的功能。添加后,新组件可供重用。
–可以从组件中删除不需要的功能,以提高其性能或减少其空间需求
4-1可复用性的度量、形态与外部表现
–可能必须修改某些组件操作的实现。

4-1可复用性的度量、形态与外部表现
2如何衡量“可重用性”?
测量可重用性
▪ 在不同的应用程序场景中,软件资源
的重用频率如何??
–资源
被使用的机会越多,其可重用性就越高。
–写一次,重复使用多次。
▪ 重复使用这项资源 要付多少钱?
–购买资产和其他强制库的成本(搜索)
–调整和扩展它的成本
–实例化它的成本
–更改与它交互的系统其他部分的成本

▪ 可重用性意味着对构建、打包、分发、安装、配置、部署、维护和升级问题进行一些明确的管理。
▪ 具有高可重用性的软件资源应该:
–简短(小尺寸)和简单(低复杂度)
-与标准兼容
-灵活可变
– 可扩展
– 泛型、参数化
– 模块化
– 变化的局部性
– 稳定
– 丰富的文档和帮助

3可重用组件的级别和形态
重用级别
▪ 最主要的复用是在代码层面

▪ 但好处来自于对可重用内容的更广泛和更高层次的看法。
软件构造过程中的任何实体都可能被复用
–要求
–设计和规范
–规范
–数据
–测试案例投资
–文件

代码重用的类型
▪ 白盒重用——当代码本身可用时重用代码。通常需要进行某种修改或调整
—Pro:您可以自定义模块以适应特定情况,这允许在更多情况下重用
—Con:您现在拥有自定义结果,因此它增加了代码复杂性。您需要了解组件内部的内在知识。
▪ 黑盒重用
-通过提供一些“粘合剂”(API接口等)以组合现有代码的形式重用,但不必更改代码本身
-通常是因为您无法访问代码
-Pro:简单和干净
-Con:很多时候这是不适用的

可重用组件分发格式
▪ 表单:–源代码
–包,如.jar、.gem、.dll,
▪ 可重用软件组件的来源:
内部(公司)代码库(番石榴)
-第三方库(阿帕奇)-内置语言库(JDK)
-教程、示例、书籍等的代码示例
-现有系统代码-开源产品(确保遵守任何许可协议)

(1) 源代码重用
重用代码-最低级别的重用
▪ 将部分/全部复制/粘贴到程序中
▪ 维护问题-需要在多个地方更正代码
-太多代码无法使用(很多版本)
▪ 过程中出错风险高
▪ 可能需要了解所用软件的工作原理
▪ 需要访问源代码

(2) 模块级重用:类/接口
▪ 类是代码重用的基本单元
——不需要源代码、类文件或jar/zip
——只需要包含在类路径中
——可以使用javap工具来获取类的公共方法
▪ 文档非常重要(JavaAPI)
▪ 封装有助于重用
▪ 要管理的代码更少
▪ 版本控制,向后兼容性仍然存在问题
▪ 需要用静态链接将相关类打包在一起

重用类的方法:继承
▪ Java提供了一种代码重用的方式,称为继承
——类扩展了现有类的属性/行为
——此外,它们可能覆盖现有行为
▪ 无需使用只转发或委托工作的虚拟方法
▪ 更好地符合现实世界
▪ 通常需要在实现之前设计继承层次结构
▪ 不能取消属性或方法,因此必须小心不要过度使用

重用类的方法:委托
▪ 委托仅仅是当一个对象依赖于另一个对象来实现其功能的某个子集(一个实体将某些东西传递给另一个实体)时——例如,排序器将功能委托给某个比较器
▪ 明智的委托可以实现代码重用-排序器可以用任意排序顺序重用-比较器可以用需要比较整数的任意客户端代码重用
▪ 显式委托:将发送对象传递给接收对象
▪ 隐式委托:由语言的成员查找规则
▪ 委托可以描述为实体之间共享代码和数据的低级机制。

(3) 库级重用:API/Package
▪ 库:一组提供可重用功能的类和方法(api)
框架
▪ 框架:可自定义到应用程序中的可重用框架代码▪ Framework重新调用了客户代码
——好莱坞原则:“不要给我们打电话。我们会打电话给你的。”

4-1可复用性的度量、形态与外部表现

良好API的特性
▪ 易学
▪ 易于使用,即使没有文档
▪ 难以滥用
▪ 易于阅读和维护使用它的代码
▪ 足够强大以满足需求▪ 容易进化
▪ 适合使用者

(4) 系统级重用:框架
应用框架
▪ 框架是包含抽象和具体类的集合以及每个类之间的接口的子系统设计
▪ 框架是一种抽象,在这种抽象中,提供通用功能的软件可以通过附加的用户编写的代码进行选择性更改,从而提供特定于应用程序的软件。

▪ 可重用性利用了应用程序领域的知识和经验丰富的开发人员的前期工作—数据处理、图形用户界面等
4-1可复用性的度量、形态与外部表现
框架设计
▪ 框架不同于应用程序
——抽象级别不同,因为框架为一系列相关问题提供解决方案,而不是单一问题。
–为了适应这一系列问题,框架是不完整的,包含了热点和挂钩,允许定制
▪ 框架可以根据用于扩展它们的技术进行分类。
▪ 白盒框架——通过继承和动态绑定实现的可扩展性。
–通过子类化框架基类和重写预定义的钩子方法来扩展现有功能
–通常设计模式(如模板方法模式)用于重写钩子方法。
▪ Blackbox框架——过实现特定接口/delegation进行 框架扩展
–通过定义符合特定接口的组件来重用现有功能
–这些组件通过委托与框架集成。

4可重用性的外部观察
类型可变 ▪功能分组 ▪ 实现可变 ▪ 表示独立 ▪ 共性抽取
类型变化
▪ 可重用组件应该是类型参数化的,以便它们能够适应不同的数据类型(输入、计算和输出);
—可重用模块应该适用于许多不同类型的元素,而不需要开发人员对软件文本执行手动更改。
–换句话说,我们需要一个描述类型参数化模块的工具,也称为泛型模块(generic modules)。
▪ 通用性:可重用组件应该是通用的。

实施变更
▪ 在实践中有各种各样适用的数据结构和算法。
▪ 这种多样性确实使我们不能指望一个模块来处理所有的可能性;否则工作量将是巨大的。
▪ 我们需要一系列模块来覆盖所有不同的实现。
▪ 实现可变:ADT有多种不同的实现,提供不同的representations和 abstract function,但具有同样的specification (pre-condition, postcondition, invariants),从而可以适应不同的应用场景
例行分组
▪ 一个自给自足的可重用模块需要包含一组例程,每个例程对应一个操作。
▪ 完整性
▪ 提供完备的细粒度操作,保证功能的完整性,不同场景下复用不同的 操作(及其组合)
表示独立性
▪ 可重用模块的一般形式应使客户机能够在不知道如何实现操作的情况下指定操作。
▪ 表示独立性是信息隐藏规则的扩展,对于大型系统的顺利开发至关重要:实现决策经常会发生变化,客户机应该受到保护。内部实现可能会经常变化,但客户端不应受到影 响。 ▪ 表示独立性反映了客户机对可重用性的看法,即忽略内部实现细节和变量的能力

▪ 分解常见行为,反映了可重用类开发人员的观点。
▪ 目标是利用实现的一个系列或子系列中可能存在的任何共性。▪
▪ 如前所述,在某些问题领域中可用的各种实现通常需要基于一系列模块的解决方案。
▪ 这些类别中的每一个都涵盖了许多变体,但通常可以在这些变体之间找到显著的共性。

摘要
▪ 什么是软件重用?
▪ 如何衡量“可重用性”?
▪ 可重用组件的级别和形态
-源代码级重用
-模块级重用:类/接口-库级:API/包
-系统级重用:框架
▪ 可重用性的外部观察-类型变化-例行分组-实现变化-表示独立-总结常见行为