第5章:可复用性的软件构建方法 5.1可复用性的度量,形态和外部观察

大纲

什么是软件复用?
如何衡量“可复用性”?
可复用组件的级别和形态java

  • 源代码级别复用
  • 模块级别的复用:类/抽象类/接口
  • 库级别的复用:API /包
  • 系统级别的复用:框架

对可复用性的外部观察程序员

  • 类型变化
  • 例行分组
  • 实施变动
  • 表明独立
  • 分解常见行为

总结算法

什么是软件复用?

软件复用编程

软件复用是使用现有软件组件实施或更新软件系统的过程。设计模式

软件复用的两个观点数据结构

  • 建立:以系统方式建立可复用资源(面向复用编程:开发出可复用的软件)
  • 使用:复用资源做为建立新系统的构建块(基于复用编程:利用已有的可复用软件搭建应用系统)

为何复用?架构

  • “创造可重复使用而不是暂时性文物的动力具备审美和知识以及经济动机,而且是人类对不朽渴望的一部分。
  • 它将人与其余生物区分开来,并从原始社会文明“(Wegner,1989)。

为何复用?框架

重复使用具备成本效益,而且具备及时性下降成本和开发时间数据结构和算法

  • 经过缩短软件生产周期时间来提升软件生产力(开发速度更快,人员更少的软件)
  • 不浪费资源没必要要地“从新发明轮子”
  • 下降维护成本(可生产更好的质量,更可靠和更高效的软件)

通过充分测试,可靠,稳定,生成可靠的软件模块化

  • 重复使用已经存在一段时间并被调试的功能是构建稳定子系统的基础

重复使用标准化,在不一样应用中保持一致

  • 复用GUI库可在应用程序中产生常见的外观。
  • 与常规,一致的设计保持一致。

重复使用成本

可复用组件的设计和构建应该采用明确,开放的方式,具备简洁的接口规范,易于理解的文档以及面向将来的使用。作到这些,须要代价。
复用成本很高:涉及跨越组织,技术和流程变动,以及支持这些变动的工具成本,以及培训人员使用新工具和变动的成本。 不只面向复用编程代价高,基于复用编程代价也高

面向复用开发:开发可复用的软件

可复用组件的开发成本高于特定等价物的成本。 这种额外的可复用性加强成本应该是一个组织而不是项目成本。 开发成本高于通常软件的成本:要有足够高的适应性
通用组件的空间效率可能较低,执行时间可能长于其特定的等效项。 性能差些:针对更普通场景,缺乏足够的针对性。

基于复用开发:使用已有软件进行开发

必须开发和维护用于体系结构,设计,文档和代码的组件管理工具,例如存储库。可复用软件库,对其进行有效的管理

一个关键问题:适应每每没法拿来就用,须要适配

  • 可能须要将额外的功能添加到组件。 添加完成后,新组件能够从新使用。
  • 能够从组件中删除不须要的功能,以提升其性能或减小其空间要求
  • 某些组件操做的实现可能须要修改。

如何衡量“可复用性”?

衡量可复用性

软件资产在不一样应用场景中的重复使用频率如何?

  • 资产使用的可能性越高,其可复用性越高。
  • 编写一次,重复使用屡次。

为重复使用此资产需支付多少费用?

  • 购买资产和其余强制性库的成本
  • 调整和扩展它的成本
  • 实例化它的成本
  • 更改与其交互的系统的其余部分的成本

可复用性

可复用性意味着对构建,打包,分发,安装,配置,部署,维护和升级问题进行一些明确的管理。

具备高可复用性的软件资产应该:

  • 简短(小尺寸)和简单(低复杂度)
  • 便携式和标准合规性
  • 适应性和灵活性
  • 可扩展性
  • 通用和参数化
  • 模块化
  • 易变(可变)设计假设的本地化
  • 改变要求时的稳定性
  • 丰富的文档

可重复使用组件的级别和形态

复用水平

可复用组件多是代码

  • 最广泛:大多数程序员与复用有关

可是,从更普遍和更高层次上看待能够重复使用的观点带来的好处。

  • 要求
  • 设计和规格
  • 数据
  • 测试用例
  • 文件

咱们在这节课中关注的是什么

源代码级别:方法,语句等
模块级别:类和接口
库级别:API

  • Java库,.jar

架构级别:框架框架

代码复用的类型

白盒复用:源代码可见,可修改和扩展

  • 代码自己可用时复用代码。 一般须要某种修改或改编
  • Pro:您能够自定义模块以适应特定的状况,这容许在更多状况下复用
  • Con:你如今拥有自定义的结果,因此它增长了你的代码复杂度。 您须要内部组件的内在知识。

黑盒复用:源代码不可见,不能修改

  • 经过提供一些“胶水”来从新组合现有代码的形式,但没必要更改代码自己 - 一般是由于您没法访问代码。只能经过API接口来使用,没法修改代码
  • Pro:简洁和清洁
  • Con:不少时候这是不可能的

可复用组件分布的格式

形式:

  • 源代码
  • 包,如.jar,.gem,.dll,

可复用软件组件的来源:

  • 组织的内部代码库(Guava)
  • 第三方提供的库(Apache)
  • 语言本身提供的库(JDK)
  • 来自教程,示例,书籍等的代码示例
  • 本地代码专家或知识渊博的同事
  • 现有的系统代码
  • 开源产品(请务必遵照任何许可协议)

(1)源代码复用

复用代码 - 最低级别
将部分/所有复制/粘贴到您的程序中

维护问题

  • 须要在多个地方更正代码
  • 使用太多的代码(不少版本)

过程当中出现错误的风险很高
可能须要知道如何使用的软件工做
须要访问源代码

(2)模块级复用:类/接口

复用类
类是代码复用的原子单元

  • 不须要源代码,类文件或jar / zip
  • 只须要包含在类路径中
  • 可使用javap工具来获取类的公共方法头

文档很是重要(Java API)
封装有助于复用
代码管理较少
版本控制,向后兼容性仍然存在问题
须要一块儿打包相关的类 - 静态连接

复用类的方法:继承
Java提供了一种名为Inheritance的代码复用方法

  • 类扩展示有类的属性/行为
  • 另外,他们可能会覆盖现有的行为

不须要放置仅仅转发或委托工做的虚拟方法
更好地捕捉现实世界
一般须要在实现以前设计继承层次结构
没法取消属性或方法,所以必定要当心,不要过度

复用类的方法:委托

委托只是当一个对象依赖另外一个对象来实现其功能的某个子集时(一个实体将某个事物传递给另外一个实体)

  • 例如分拣机正在委托比较器的功能

审慎的委托支持代码复用

  • 分拣机能够重复使用任意的排序顺序
  • 比较器能够重复使用须要比较整数的任意客户端代码

显式委托:将发送对象传递给接收对象
隐式委托:由语言的成员查找规则

委托能够被描述为在实体之间共享代码和数据的低级机制。

(3)库级复用:API /包
库:一组提供可复用功能的类和方法(API)

框架:能够定制到应用程序中的可重复使用的框架代码
框架调用回客户端代码

  • 好莱坞原则:“不要打电话给咱们。 咱们会打电话给你。“

通常区别:库与框架

框架做为主程序加执行,执行过程当中调用开发者所写的程序
开发者构造可运行软件实体,其中涉及到对可复用库的调用

(4)系统级复用:框架

应用程序框架

框架是子系统设计,包含一系列抽象和具体类以及每一个类之间的接口
框架:一组具体类,抽象类,及其之间的链接关系 - 只有“骨架”,没有“血肉”
框架是一种抽象,其中提供通用功能的软件能够经过额外的用户编写的代码进行选择性更改,从而提供特定于应用程序的软件。 开发者根据框架的规约,填充本身的代码进去,造成完整系统

可复用性利用了应用领域知识和经验丰富的开发人员的先前努力

  • 数据处理,图形用户界面等
  • 将框架看做是更大规模的API复用,除了提供可复用的API,还将这些模块之间的关系都肯定下来,造成了总体应用的领域复用

框架:领域复用

系统经过添加组件来填充缺失的设计元素并实例化抽象类来实现

  • 一般经过选择性覆盖来扩展框架; 或者程序员能够添加专门的用户代码来提供特定的功能---定义从抽象类祖先继承操做的具体类
  • 钩子方法,被应用程序覆盖以扩展框架。 钩子(Hook)方法系统地将应用程序域的接口和行为与应用程序在特定上下文中所需的变体解耦。
  • 控制反转:与库或标准用户应用程序不一样,控制流不是由调用者决定的,而是由框架决定的。
  • 不可修改的框架代码:框架代码不该该被修改,同时接受用户实现的扩展。 换句话说,用户能够扩展框架,但不该修改其代码。

控制反转(Inverse of Control)

由第三方的容器来控制对象之间的依赖关系,而非传统实现中由代码直接操控。
控制权由代码中转到了外部容器,带来的好处就是下降了对象之间的依赖程度,提升灵活性和可维护性。

框架设计

框架与应用程序不一样

  • 抽象级别不一样,由于框架为相关问题家族提供解决方案,而不是单一解决方案。
  • 为了适应这一系列问题,该框架是不完整的,包含热点和挂钩以容许定制

框架能够用扩展它们的技术来分类。

  • 白盒框架
  • 黑盒框架

白盒和黑盒框架

白盒框架:

  • 经过继承和动态绑定实现的可扩展性。
  • 经过继承框架基类并重写预约义的钩子方法来扩展示有功能
  • 一般使用模板方法模式等设计模式来覆盖钩子方法。

黑盒框架

  • 经过为可插入框架的组件定义接口来实现可扩展性。
  • 经过定义符合特定接口的组件来复用现有功能
  • 这些组件经过委托与框架集成。

类库与框架

类库:

  • 较少的域特定
  • 提供更小的复用范围。
  • 类库是被动的; 对控制流程没有限制。

框架:

  • 类为相关应用系列合做。
  • 框架活动; 影响控制流程。

在实践中,开发人员常用两种:

  • 框架一般在内部使用类库来简化框架的开发。
  • 框架事件处理程序使用类库来执行基本任务(例如字符串处理,文件管理,数值分析......)。

组件与框架

组件

  • 类的独立实例
  • 链接在一块儿造成完整的应用程序。
  • 黑盒定义了一套连贯的操做,
  • 能够基于接口的语法和语义使用。
  • 组件甚至能够在二进制代码级复用。

•优势是应用程序不必定须要在组件更改时从新编译。
构架:

  • 常常用于开发组件
  • 组件一般插入黑盒框架。

可复用性的外部观察

对可复用性的外部观察
类型可变
功能分组
实现可变
表示独立
共性抽取

类型可变
可复用组件应该是类型参数化的,以便它们能够适应不一样的数据类型(输入,计算和输出);

  • 可重复使用的模块应该适用于许多不一样类型的元素,而不须要开发人员对软件文本进行手动更改。

换句话说,咱们须要一个用于描述类型参数化模块的工具,这个模块也被称为通用模块。
通用性:可复用组件应该是通用的。
类型可变(泛型):适应不一样的类型,且知足LSP

实现可变
在实践中有不少种适用的数据结构和算法。
咱们不能指望单个模块可以处理全部可能性,这种变化确实是这样; 这将是巨大的。
咱们须要一系列模块来涵盖全部不一样的实现。
实现可变:ADT有多种不一样的实现,提供不一样的表示和抽象功能,但具备一样的规范(前置条件,后置条件,不变式),从而能够适应不一样的应用场景

功能分组
一个自给自足的可复用模块须要包含一组功能,每一个操做一个功能。
完整性
提供完备的细粒度操做,保证功能的完整性,不一样场景下复用不一样的操做(及其组合)

表示独立性
可复用模块的通常形式应该使客户可以指定一个操做而不知道它是如何实现的。
表示独立性是信息隐藏规则的延伸,对于大型系统的顺利开发相当重要:实施决策常常会改变,客户应该受到保护。 内部实现可能会常常变化,但客户端不该受到影响。
表示独立反映了客户对可复用性的见解 - 忽略内部实现细节和变体的能力
表示独立性,信息隐藏

共性抽取
分解共同行为,反映了供应商的观点,更通常地反映了可复用类的开发者的观点。
目标是利用家庭或实施子系列中可能存在的任何通用性。
将共同的行为(共性)抽象出来,造成可复用实体
如上所述,在某些问题领域可用的各类实现一般须要基于模块族的解决方案。
这些类别中的每个都涵盖了许多变体,但一般能够在这些变体之间找到显着的共性。

总结

什么是软件复用?
如何衡量“可复用性”?
可复用组件的级别和形态

  • 源代码级别复用
  • 模块级复用:类/接口
  • 库级:API /包
  • 系统级复用:框架

对可复用性的外部观察

  • 类型可变
  • 功能分组
  • 实现可变
  • 表示独立
  • 共性抽取
相关文章
相关标签/搜索