- 内容提要
- 序 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 已死
12.5 交付形式相关的组织方式
库,通常是一种代码或其对应产品构件的交付形式。这意味着库的表现形式是多样的,例如可以是源代码的一种组织形式,也可以是由源代码编译成的二进制结果;它既可能是一些单元或模块的、有或没有规则的包装或集合,也可能是将某些“类”有序集中在一起的一个泛指。一些常见的形式包括:
- 在编译语言中,库可能用来组织代码,或翻译阶段中的中间代码。例如汇编语言中的库(.lib),就用于管理一些目标文件(.obj)的集合。
- 在目标系统中,库可能用来指应用发布的一个组成部分。例如 Windows 中的动态链接库(.DLL)。
- 在面向对象系统中,(类)库通常用来指一些类的集合,但并不表明这些类是以源码形式或是二进制形式提供。例如开源项目中的类库可能是源代码包,而.NET 的类库则是一些可以注册到系统中的、二进制的程序集(Assembly)。
- 在应用环境例如操作系统中,库通常是指可在不同应用产品之间复用的运行期代码。例如 COM 库,或前面提到的动态链接库(.DLL) 8 。
综合上述以及更多的应用环境,“库”通常都不是指代码本身的组织,而是指它们的交付,包括最终交付之前的某种阶段。
“库”究竟以何种形式交付,以及包含何种内容交付,都取决于最终应用产品对未来交付形式的需求。换而言之,既然库是某个产品(在特定运行环境中)的构件,那么它必然满足该环境的要求和该产品的限制。例如:
- 如果产品以平台依赖的二进制共享文件发布,那么库可能以编译阶段的中间文件,或者执行阶段的依赖模块的形式提供,例如 Pascal 的*.tpu 和*.bpl,或者 delphi 的*.bpk,C/C++的*.lib,以及.NET 的程序集、COM 组件等。
- 如果产品设计为支持插件的,那么库将以动态链接库(DLL)的形式交付,例如 Windows 操作系统中的屏保(*.scr)、控制面板应用(*.cpl)、管理模块(*.msc)等,或者 Photoshop 中的特效插件(*.8bf),这些其实都是修改了文件扩展名的动态链接库。
- 如果产品设计为动态资源的,那么库将以资源包的形式交付,例如 Android 开发中的*-res.apk 文件,通常就是作为某个主应用程序的资源包来提供的,这样便于提供同一个应用程序的不同国家/地区的版本。
- 如果产品设计为支持动态脚本的,那么库将以源代码包或脚本库的形式交付,例如 Mozilla Firefox 的*.xpi 插件,本身就是一个.zip 文件包,其内容则是一些 javascript 脚本及其依赖的资源。
“库”作为交付物以及最终产品的一个组成部件来提供,也意味着它是具有版本信息的 9 。这种版本信息与交付产品的版本相关,例如不能直接将用于 Mozilla Firefox 3 的插件直接应用于 Mozilla Firefox 6,而这一限制是作为版本信息(install.rdf 文件)包含在插件中一起交付的。
然而作为一个完整的交付物,应用产品可能是一个不带有任何“库”的独立程序(例如 Windows 环境中的.exe 文件),也可能带有更为丰富的产品信息,例如包括:
- 产品依赖的操作系统或主程序版本,例如 Firefox 插件中的 install.rdf 文件;
- 自身基于的运行库,例如 VC 的 Runtime 库 vcredist_x86.msi;
- 与此前的发布版本的冲突或依赖,例如配置文件检查或修复;
- 当前产品版本发布时附带的完整库、文件或资源,例如文件清单;
- 当上述依赖缺失时,可能的获取渠道,例如 ActiveX 组件的 codebase;
- 产品文档或相关信息,例如 readme.txt、帮助文件或在线帮助的网址链接。
通常应用程序开发的集成环境(或某些推荐性的套件、开发工具组合)会提供一系列的方式来生成上述的产品内容 10 ,最后将这些文件打包并提供某种统一、便捷的安装方式。这些最终可以由“用户”在其机器环境下自主使用的交付物,在商业意义上称为“产品”,而在程序世界中通常就称为“包” 11 。
综上所述,我们将库(library)与包(package)作为产品交付形式相关的两个组织方法如图 37 所示。
图 37 (产品的)交付形式相关的组织方式
- 这里的空间与时间因素,是基于在《我的架构思想:基本模型、理论与原则》中对目标属性的分类方式来讨论的:所谓空间需求,是指它们可以通过组成部件的增减来解决;所谓时间需求,是指它们可以划分为多个时间阶段来实施。 ↩
- 语句与行的不同,通常也被称为逻辑行与物理行概念上的不同。此外,有些语言是强制要求以物理行来表达“语句”这一概念的,即一行语句必须书写于一行代码中。 ↩
- 单元与模块除了称谓的不同,很多时候其抽象概念也并不完全相同或者互相覆盖,例如一个单元可以是(或不是)一个模块。我们这里只取在某些语言中、将模块特指为“一系列函数”的这一概念。 ↩
- 早期的应用开发语言也直接将应用称为“程序”(program)。 ↩
- 参见《人月神话》中“关于信息隐藏,Parnas 是正确的,我是错误的”小节,以及 David Parnas 关于信息隐蔽理论的著名论文:《论将系统分解为模块的准则》、《设计易于扩展和收缩的软件》和《复杂系统的模块化架构》。 ↩
- DFD(DataFlow Diagram,数据流图)通常用于解释在上述执行过程中 m-n 之间的转换关系不变(即数据单一入口与单一出口)。但在本例中,它亦用于解释自顶向下过程中的逻辑关系不变,整体保持着顺序执行关系。这一过程是抽象概念——从程序语言中逻辑的 结构化 ,到应用系统中组织的 模块化 ——的延伸。 ↩
- 这里指的是对象库(object library)或类库(class library),而普遍意义上的“库”是下一小节讨论的重点。 ↩
- 动态链接库也有动态加载和静态加载两种形式,前者是用户代码可以使用 loadLibrary() 等函数将该库装载到应用环境中,后者是指在编译期由编译器决定的、在应用运行的初始化阶段由操作系统负责装载的库。在 Windows 环境中,一个库是用于静态加载或动态加载,通常是由应用决定的——这也意味着它的发布与依赖也由应用来决定。 ↩
- 版本也是导致“DLL 地狱”(DLL Hell)问题的根源之一。所谓“DLL 地狱”,是指在同一执行环境的不同软件产品中,由于使用了同名但版本不同的 DLL 而导致的冲突。这一问题并非 Windows DLL 或 Linux Library 所特有。不同的库,在解决这一问题的策略上不尽相同,但大体上都是以“声明版本依赖关系”为基本思路。 ↩
- 这些内容可能被称为“库”,也可能被称为“构件”,还可能被称为“依赖项”,如此等等。 ↩
- 例如对象库或类库的交付物称为“类包”(class package),可执行应用及其完整交付称为“安装包”(install package),而 linux/debian 环境下一个产品或产品系列的发布称为“debian package”。 ↩
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论