- 内容提要
- 序 1:程序里的世界
- 序 2:最后一层表象
- 关于本书
- 致谢
- 引言:简单的本源
- 篇一:计算系统
- 第 1 章 数,以及对数据的性质的思考
- 第 2 章 逻辑
- 第 3 章 抽象
- 篇二:语言及其面临的系统
- 第 4 章 语言
- 第 5 章 从功能到系统
- 篇三:程序设计的核心思想
- 第 6 章 数据结构:顺序存储
- 第 7 章 数据结构:散列存储
- 第 8 章 执行体与它在执行过程中的环境
- 第 9 章 语法树及其执行过程
- 第 10 章 对象系统:表达、使用与模式
- 篇四:应用开发基础
- 第 11 章 应用开发的背景与成因
- 第 12 章 应用开发技术
- 第 13 章 开发视角下的工程问题
- 第 14 章 应用程序设计语言的复杂性
- 篇五:系统的基础部件
- 第 15 章 分布
- 第 16 章 依赖
- 第 17 章 消息
- 第 18 章 系统
- 篇六:系统的基本组织方法与原理
- 第 19 章 行为的组织及其抽象
- 第 20 章 领域间的组织
- 附一:主要编程范式 及其语言特性关系
- 附二:继承与混合,略谈系统的构建方式
- 附三:像大师们一样思考——从 UML 何时死掉 谈起
- 附四:VCL 已死,RAD 已死
14.3 模块化思维在产品交付组织形式上的延伸:插件机制
对于一个应用程序来说,“插件”往往意味着它是一个动态链接库、静态链接库,或一个独立发布的脚本包。如前所述,库或包,只是一堆代码在组织上的措辞而已。因此插件的本质在于用组织形式来解决空间因素所致的复杂性 7 。
“插件”这一方案意味着插件的宿主(HOST)与插件本身(Plugins、Addons 或 Extensions 等)是分别发布的。这事实上与应用容器有一定的相似性,只是两者应付的问题集存有稍许差异而已:
- 应用容器主要提供可配置的、可重新实现的环境,并通过标准化来提供跨业务领域的应用支持。尽管应用容器也有应用范围的限制,但通常该范围的边界更大。
- 插件的宿主通常在产品、用户和功能这些方面基本确定,在技术方案上也通常是预先可确定的,因此“宿主+插件”更适宜作为一个具体应用产品的实现手段。
与应用容器类似,宿主也有跨平台的问题,例如 Firefox 浏览器。这个问题有两个解决方案:其一,如果产品的用户有能力在不同平台上编译并重新发布宿主 8 ,或者宿主是针对特定平台开发而无需重新发布的,那么插件通常实现为与环境相关的二进制模块;其二,如果宿主有明确的跨平台需求,而其编译过程复杂或不宜公开编译方案与代码,或者用户没有能力或没有必要去区别、编译不同平台中的插件版本,那么插件通常实现为文本形式的脚本或预先编译为跨平台的中间代码/代码包(前者例如 Firefox 浏览器中扩展名为.xpi 的插件,后者例如 Java 的.class 文件)。
插件技术是基于应用开发技术的“模块/单元”理念而来的。不同的是,宿主通常可以脱离部分或全部插件独立运行,而应用程序通常不能独立于模块/单元来完成编译。能否从“模块/单元”中去除强约束的依赖性,是识别能否代之以插件技术的可行方法。
如前所述,在面向对象的设计观念中,“类”替代了“function/unit/module…”等组织方式。因此在面向对象的设计中,“HOST 类 + 插件基类”是这一解决方案的基本设计。更进一步地,由于名字空间用于应付更大规模的组织,并且通常也具有“作用域”限制的能力,所以使用“HOST 框架 + (插件的)名字空间”也是一种可行的实现。这在本质上与前一种设计没有不同,只是应用的规模更大,而且作用域范围控制更为灵活,类似安全性、账户等级限制等特性也往往更加容易实现。
但是基于面向对象的插件技术的问题在于:通常宿主与插件都基于相同的“面向对象语言”,因此具体的对象实现技术、二进制编译技术、对象封装技术等限制了插件的通用性。例如很难用 Delphi 开发一个“类”,并将它作为一个插件用在 Visual C++开发的宿主上。
这个问题的核心在于如何实现“组件复用”。这里的“组件”(Component)与此前的“模块”的区别在于:组件通常用于表达面向对象中的 可复用对象/类 ,而模块通常用于表达结构化编程中的一个 可复用件9 。这两者所面临的问题是完全一致的,其解决方案也有着延伸关系,例如 Windows 中的 COM 复用与 DLL 复用其实是一脉相承的,而.NET 中的 Assembely 复用与 COM 复用也是类似的关系。
这通常涉及三种不同类型的复用(事实上划分它们的依据也并非唯一):
- 二进制复用,例如 COM;
- 公共指令集复用,例如 JAVA 类;
- 文本复用,例如脚本。
无论技术方案的提供商如何渲染这些技术,其最终的结果是一样的:开发人员终于可以用 Delphi 写一个 COM 组件,并让它运行在一个 Visual C++写的类工厂中;或者用任意的 Java 编译器编译一个.class,并分发给其他编译、运行环境下的宿主。当这一切成为现实 10 之后,组件技术的核心便集中在了宿主框架的设计、插件的加载机制,以及隔离宿主与插件之间或多个插件之间的安全性这几个方面 11 。
插件提供了通过剪裁功能来重新定义产品的不同版本(例如标准版、专业版)的能力。与此同时,正因为它在概念上继承自“模块/单元”,所以也是一个“化整为零”的典型方案,这使得在大型项目中实施持续集成具有了可能性。这其中的一个有趣的事实是:如果集成需要所有“模块/单元”的参与,那么集成的失败率就会在系统规模达到一定程度后出现级数性的增长;只有被集成的产品可以通过类似插件、可复用件的机制,将单一部件的规模控制在一定范围内,持续集成——而不致阻碍整个 Team 的推进——才成为可能。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论