【IT168 技术文章】
3.1 警告
必须注意到我们讨论的概念和系统都是现实存在的,而不是一个完全的总结或者现存的演化。对于每一个概念,会讨论一个CM系统。也必须注意,有一些CM系统确实提供了图谱中显示的很多功能。概念是从特定CM系统直接获取的,每一种CM系统都有各自的概念和语义,因此对于自动化功能没有通用的术语。为了重点突出,对概念的描述将会简化,因此有可能没有将概念(和它们的系统)的能力完全描述出来。但是,为了更好的展示一个图谱和专著于CM的基本概念,简化是有必要的。本文引用的CM系统的在附录中有汇总,这个汇总提供了一个每一种CM能力更全面的列表。
3.2 组件概念
组件概念用来标识和访问软件产品的组件,就是下面描述的是版本库和分布式的组件。
3.2.1 版本库
版本库概念是一个CM系统的基础,Revision Control System (RCS) [15] 提供了针对ASCII文件的版本库,实际上,版本库是一个文件的中央仓库,并且提供了版本库中文件的版本控制。版本库中的任何文件,可以看作在CM控制下。版本库中的文件是不可变的,不可以更改。作出修改意味着创建文件的一个版本,所有关于文件和其内容的CM信息都保存在版本库中,因此,CM控制适应于版本库中的任何文件。为了修改一个文件,用户需要检出(check out)特定版本的文件到它们的工作目录(working directory),然后根据自己的判断开始修改,最后检入(check in)回版本库,这样就创建了文件的一个新版本。这样用户就不能同时检出同一个文件并修改,在这个用户将其检入回去之前,检出的文件会被锁定(以版本库的视角)。一个版本号码会自动与新版本关联;此后,用户可以在任何时候检出特定版本的文件,当然缺省检出的是最新的版本。对最新版本的更改会产生新的版本,然而对老版本的修改会导致一个不同的版本。总之,版本号方案和使用模式产生了文件的版本历史树,指出了版本的前任和后继。版本库保存了文件的历史信息,包括文件的不同版本和修改的原因、作者和时间。需要注意的是并没有保存所有版本的完整代码,而只是保存了版本的区别,也就是所说的增量,这样就节省了存储空间和对最新版本的访问时间。文件可以使用某个状态标记,并可以根据这个状态值检出。文件也可以根据修订版本号、时间和作者检出。版本库通常与其保存文件的目录关联,总之,一个版本库捕获CM信息并以不可变对象的形式保存文件的版本。
3.2.2 分布式组件
Sherpa Design Management System (DMS) [7] 提供了一种文件分布在不同硬件平台上的版本库,这个版本库逻辑上是集中式的,但版本库中的数据可以是物理上分离的。Sherpa DMS可以识别分布式并在执行CM时考虑分布式这一点,例如,通过对文件格式的必要转换提供容错灵活性。所以,对用户来说,分布式是透明的--用户可以像处理自己工作站的文件一样处理版本库的文件。一组地域上分离的用户可以工作在同样的文件配置下,文件的多份拷贝可以存在于不同的工作站,Sherpa DMS知道文件最新版本的位置,版本库中文件的任何修改都会更新到工作站中的所有本地拷贝中去,因为系统清楚所有本地拷贝的位置。更新可以是交互模式或者批量模式,实际上,分布式用户已经访问了中央版本库,对他们来说,这个CM工具使异种工作站跨越了网络。
3.3 过程概念
处理过程相关功能的概念包括环境管理、契约、变更请求和生命周期模型,将会在下面描述。
3.3.1 环境管理
PowerFrame [13] 是为电脑辅助工程/设计领域设计的系统,可以帮助用户不必关心系统和配置的底层细节,用户只能看到电路设计这个特定领域,而PowerFrame管理用户工作的环境。项目的数据以图像的形式展现,而不是隐藏在目录的形式,PowerFrame提供了工作流程管理来指导团队成员的工作过程。例如,一个工具运行会包括线路的创建,验证和检测性能特性的模拟。在这些活动中,PowerFrame自动得出工具相关的当前环境,如数据集,命令文件和调用工具的选项。下一次,用户只需要选择线路设计和工具功能就可以重新开始工作。用户只能见到:执行特定任务的合适工具;逻辑模式或布局设计之类特定表单的数据展示;属于特定领域的命令表单。用户可以执行不同粒度的动作,例如某个环境数据的条目或配置。用户不必担心版本控制或文件之间的关系,因为系统知道数据来自不同版本的电路,在后台处理了这些任务。实际上,CM系统以一种领域特定的方式捕获用户的工作环境,消除了用户记住工作状态以及所有数据项目及其关系的必要。
3.3.2 契约
ISTAR [9] 环境支持对软件开发过程的正式确认方面进行建模,也就是建立一种契约,确定某种任务的输入和交付,契约的制品被记录下来并成为配置项目,这些项目包括契约模型信息流,任务的开始和完成,产品的任务和组件结果的传递及其交换。一个契约被满足接受条件的交付件的传递完成,交付件被传递到过程模型的特定元素,如生命周期的不同阶段或不同的人,这些制品的移动会被顺序记录下来。契约中的过程会被监控,因此不同的制品(例如交流)会被记录下来。实际上,契约代表了某个配置项上的正式计划、记录和一个单元的工作。
3.3.3 变更请求
在LIFESPAN [11] 中,一个变更请求代表了对一个变更的文档请求和模型关联的过程。LIFESPAN通过一系列的表单和一系列状态表示的过程为变更请求建模,一个客户可能提交一个即时的软件表现报告(SPR),指明了一个问题或者是对某个组件进行加强的请求,这允许报告调查最初的能够诊断这个问题的设计者和实现者。作为SPR和变更影响分析的反馈,会提交一份设计变更(DC),这是组件变更和变更方式的细节。然后这些人会自动进入变更控制委员会,他们会收到关于DC的电邮通知,并且必须投票确定是同意还是否决变更。一旦通过DC,就会产生一份代码的开发版本,DC的状态变为活动,并且锁定变更的代码。当完成了修改,就会冻结新版本,并且提交,以便有QA权限的人检查和确定。经过代码的确认,就会进入“确认”状态,DC的状态变为“确认”会发送“新版本已经可用”的邮件到用户。用户会收到一份Software Status Report(SSR),会关闭最初的SPR。尽管SPR,DC和SSR没有提供用户和维护者交流的方式,但是提供了:特定变更请求关联的历史变更;变更过程的状态报告;变更完成的审计;变更影响分析和确保合适的人在合适时间执行各自任务的支持机制。实际上,变更请求是控制变更过程的辅助。
3.3.4 生命周期模型
Change and Configuration Control (CCC) [5] 提供了支持特定生命周期模型的概念,包括各个阶段的转换和这些阶段的数据管理,这是通过将整个生命周期分为开发、测试、确认和发布来完成的。这种分离允许不同的用户如软件工程师和测试员可以在同一份代码独立的执行他们自己的工作。这种阶段的分离和转换,以及独立的工作是通过将代码存入每个阶段独立的配置实现的,也就是说,产品是在某一基线基础上开发的。每个基线作为四种配置存在:开发、测试、确认和产品。配置是组件的一种等级关系,每个基线都有自己的方式。代码开发出现在开发配置,传递到测试配置以进行审查,然后是确认配置,最后是用户使用的产品配置。为了进入到下一个阶段,需要经过不同用户必须授权这个转换的交互(例如项目经理和测试经理)。在任何时候,对某个组件确认的等级可以从其所属的配置来得到,实际上,一个生命周期模型是通过不同配置状态实现的。
3.4 结构和构建概念
这个概念将处理:选择一个结构的组件;捕获一个组件及其结构的变更;访问结构的一部分;描绘和保持一个结构一致性的特性,包括:变更集、系统建模、子系统、对象池、属性和一致性维护,这些将在下面描述。
3.4.1 变更集
Aide-De-Camp (ADC) [1] 抽象了版本库中组件不同版本的区别的这一基本概念,使之成为一个区别关系并可以被访问。区别的关系,以及其应用的文件和其他变更的细节组成了变更集。ADC 捕获对一个配置的变更集,并且这个变更集可以用来构建一个配置的自定义版本。这个变更集有一个名字,可以在操作中使用,用户可以指定一个表达式来创建配置的特定实例,这个表达式可以为某个变更集指派一个应用的基线。一个变更集可以看作是和前一个变更集是相互独立的(会创建一个版本历史),也可以看作是非独立的(历史中选定的一部分被应用)。因此,用户可以工作在最新的版本上,也可以在自定义的版本上。变更集捕获对所有文件的所有修改,包括修改的原因和细节,以及修改的作者和时间。用户检验修改的范围,ADC会自动记录所有的变更细节。例如,用户希望对一个配置作出一个主要的修改来修正一个问题,用户指派一个变更集并且修改这个文件。这个变更集捕获:对配置中所有文件作出修正的原因;所有实际修改的代码(在配置中每个文件的区别);所有关联的文件变更;和作出修正的人和时间。用户在浏览每个文件或变更集时可以看到这些信息的大部分,作为汇总,变更集代表了一个产品的逻辑变更,也意味着创建版本的任何配置不必依赖于那个配置的最新版本。
3.4.2 系统建模
系统建模描述了一个软件产品的结构和它的组件及组建的创建方式。Jasmine [10] 系统模型是一个文本描述,用户可以调整,并且用来执行他们的任务。Jasmine系统建模由代表了四类信息的功能描述:(1)产品组件的关系,(2)版本绑定信息,(3)构建规则和(4)验证规则。关系描述了:产品的模块分解,如子模块的等级;组件的依赖关系,例如模块的创建次序;还有根据共同属性对组件的分类,如建立源程序或对象模块组。这种根据关系的产品描述叫做模板,这个描述捕获了它的结构。使用功能操作和关系,用户可以从简单中构建复杂的关系。这使的Jasmine可以回答用户定义的查询,例如修改某个模块会影响哪些组件。系统模型包括了族的概念,可以用来捕获产品的历史。一个族描述了组件版本的更迭,许多用户定义的产品版本组成了族,与之相关的还有每个版本的属性如创建日期和作者。查询,版本选择和规则都是基于这些属性,构建规则记录了当前组件是如何生成的,以及未来会怎样生成,例如记录编译器的版本和编译选项。验证规则指定和记录了产品的结构和组织约束,例如源代码和库模块必须一致(所有的二进制模块都是从这些源代码模块编译而得)。通过选择一个组件的一个版本,就会使用族的选择表达式执行评估,来确认这个模块查找的路径,选择的作为结果的模块就会以一个镜像(image)的形式绑定到模板。许多工具,如浏览器,模块retriever,调试器和内置模块分析器可以引用和处理这个系统模型。实际上,系统建模是对产品某个实例的一种抽象,通过对产品的完全描述,辅助其他工具来维护产品的完整性。
3.4.3 子系统
Ratinal [14] 环境支持将一个大的Ada产品分解成几个部分,允许限制变更影响的范围,这几个部分叫做子系统。子系统接口规范及其实现,代表了配置项目。因此,它们可以被看作一个整体,并通过它们的名字访问。子系统中的组件对其他子系统的组件不可见,除非是通过结构规范指派公开的。Ratinal环境会在运行时检查实现满足了接口说明,作为结果,可以在接口规范的实现上独立进行工作,只要用户愿意。重复编译只会在子系统的范围内进行,除非接口有改变;在任何时候,任何使用这些组件的产品需要重新编译,对接口规范的修改可能会需要整个产品的重新编译。子系统对它们的组件有版本控制,子系统可以是某个特定的版本。用户可以混合匹配子系统来组合一个产品的特定版本。总之,子系统代表了是一种限制变更和编译影响的方法,对于环境来说,检查了产品组合部分的正确性。
3.4.4 对象池
在系统建模中使用了这个概念,Domain Software Engineering Environment (DSEE) [8] 拥有生成特定导出的对象版本必要的信息。导出的对象放置在对象池中共享给用户,DSEE可以让用户为共享的对象指定对象期望的来源属性。导出的对象池保存了一组二进制文件和其他转换工具产生的产品。每个导出的对象都有对应系统模型的信息,包括源代码的版本和转换器用的转换选项,关于导出的用户注释,日期,时间,参与人和导出的位置。这些信息被叫作bound configu-file lists.ration thread (BCT),当DSEE进行了系统创建,它会为系统模型的每个组件计算目标BCT,DSEE会查看池来确定是否有符合期望的导出对象存在。如果有,就会被使用;如果没有,就会创建。因此,每当用户需要一个特定的导出对象(或是兼容的),DSEE可以重新使用池中的对象,而不需要重新生成对象。用户不必知道是否有导出对象存在;DSEE会检查所有的事情。一旦池中的某个对象已死(根据未使用时间),DSEE可以删除它们,清理空间。这样节约了编译时间和空间需要,并且重用了以前的工作。DSEE也提供了不同类型的对象池,例如对于源文件导出的对象一直会从版本库检出到特定的用户。实际上,CM系统优化了重新生成组件,并且使共享导出对象最大化。
3.4.5 属性
Adele [2] 系统通过使用具备建模能力的实体关系数据库来归纳版本库和系统建模。一个产品用数据模型描述,而Adele根据模型执行操作。产品组件通过有属性和关系的数据库对象代表,属性关联到每个对象以描述对象。一个属性有一个名称和一个值,例如属性名“delta”代表了对象是以ASCII形式保存,可以被压缩;它的值可以是“true”或“false”。需要区分两种类型的属性:预定义的和用户定义的。前者是Adele管理的,后者则是用户声明和管理的。一个预定义的,特别的属性是“type”,这个属性对每个对象是不可变的,在Adele中它代表了主要的CM类型(例如组合对象,文档,修订版本和元素)。关系定义了对象之间的依赖关系,例如,对象B源自对象A,用户可以按照对象间的属性描述配置,而不是对象特定版本的列表。Adele根据对属性及关系使用选择的规则和限制进行初始化和创建配置,用户可以对产品的期望特性定义任何结构(而不只是一个等级结构),因此,用户可以用一种高级别的方式来描述一个产品,而不仅仅是组合冗长的文件列表。
3.4.6 一致性维护
Configuration Management Assistant (CMA) [6] 支持基于产品抽象描述的配置构建和验证,也就是组成配置的组件的使用成功和失败的信息。数据建模工具包括了用户用来描述配置的预定义属性和关系,基于这些属性和关系的语义,CMA可以确定哪个配置(组件实例集)是可用的,为了可用性,一个配置必须完全的,毫不含糊的,完整的和没有版本问题的。这意味着配置必须包括所有组件的实例而不会包含某个组件的多个实例。属性的类别代表了用户定义特性的属性,如约束,类型和版本,关系的类别代表了依赖的类型,例如逻辑,兼容组件,实例和等级依赖。每当构建一个新的配置,CMA会利用前一次的信息构成配置,通过这种方式,CMA可以预测配置是否可用。新的配置会被添加到数据库,用来分析以后的可用性,因此用户可以反馈系统来识别任何不完整性,或者是在创建和重用配置时保存完整性。
3.5 团队概念
处理工作在一个产品的软件工程团队的隔离、协作和同步的概念有工作区、透明视图和事务,将在下面描述。
3.5.1 工作区
"shape" [17] 的工作区概念主要用来防止用户干扰其他人的工作,它支持在CM下的易变对象上持续工作的概念,工作区是通过版本状态模型实现的,这意味着一个属性 “state”是与一个组件的版本关联,根据这个状态(例如“busy”或“frozen”,),决定了一个组件是在私有工作区还是在公共版本库。一个 “busy”的组件是在改变的,不可以被公共使用,而一个“frozen”的组件不是在变的并可以被公共使用。组件在经过合适的人确认后,可以提升到公共版本库并被公共使用。实际上,工作区提供了隔离的工作,并且提供了针对不易变对象公共的长期版本库和针对易变对象的私有的短期版本库的建议。
3.5.2 透明视图
Software Management System (SMS) [18] 通过使对象显示和提供了版本库的透明视图加强了工作区的概念,这意味着只有用户关心的文件版本可以被看到;所有其他版本在视图(尽管这些版本在物理上都存在)中被隐藏。例如,任何对最新公共版本的修改可能不需要在工作区中可见,用户被隔离在公共修改之外,工作区给了用户特定版本的样子。工作区里还提供了工作区相关的版本号码,新版本是私有的,在从工作区发布之前对公共不可见。一个配置从公共版本库检出,然后用户被指派访问这个工作区。工作区的组件属于工作区而不是用户,只有工作区注册的用户可以修改配置,只有工作区中的组件可以访问。总之,透明视图提供了一种视图机制,保护了对配置的非授权访问。
3.5.3 事务
Network Software Environment(NSE) [12] 的事务概念代表了工作的分类,反映了产品的结构,支持不同用户工作的隔离,修改的合并。一个事务包括了一个环境和一组命令,环境提供了类似于工作区和透明视图的概念,它显示了保存源文件和导出对象的目录结构,如"acquire"、"reconcile"、"resynch"和"resolve"的命令提供了穿越环境的交互。它们代表了用来协调和同步动作的协议,也代表了实际修改的交流。用户可以在自己的环境中独立工作,修改同一个或不同的配置。用户可以用一个新版本的配置更新版本库,NSE帮助合并修改。但是它会检查当前版本库存在的东西(可能是其他用户放置的)不会与新的变更发生冲突。如果有冲突, NSE会通知用户合并的问题,并提供解决冲突的帮助,用户可以请求版本库的任何修改进入到他们各自的工作区。总之,事务同步和分类小组修改了产品的相同或不同部分。
3.6 总结和图谱分析
图2展示了不同CM系统提供的CM概念,概念和它们的目的是:一个捕捉历史和易变文件的版本库;实现版本控制下的分布式数据的分布式组件;表示一组工作的计划的契约;一个捕获对配置的修改和独立选择配置的修改集;加强软件演进的组织过程的生命周期模型;完全描述和记录产品结构和记录的系统建模。建立重用导出对象并优化产品创建的对象池;允许通过特性而不是列表选择配置的特性;对配置组件不一致性自动检测和预测的一致性维护;用来隔离易变配置的工作区;查看配置并保护非授权访问的透明视图;最后是针对配置的分类修改的事务。这些概念代表了CM系统功能的进展。 图谱的拓扑图意在展示概念的演进,例如图2的从左到右,通常来说,有一定的进展,分别在对建模不同的过程,捕获组件,描述产品的组件,优化产品的构建,描述组件依赖和分组工作等方面。图的一翼指出了相关的进程,例如,本文描述的变更请求和生命周期模型是相关的:生命周期模型包含特定的变更请求模型,变更请求操作版本库。
这个图谱没有显示所有的概念,没有说的概念包括:组件演进的粒度(例如从版本识别到配置识别,再到配置的版本);系统模型的进展(例如从命令文件到make文件,再到作为版本化对象的系统模型);识别不同角色和不同类型的变更(例如缺陷对增强对紧急补丁);和当前的研究工作。
考虑到是从CM系统概念的抽象,与实现相比本文中的描述是简化的,只是要发现一些共同概念,但对这些概念确实没有共同的术语。概念和其实现的区别并不是很清楚,例如,工作区的实现在不同CM系统中并不相同,因而为用户提供了不同的功能。因此,这些概念一定要是所有实现的最低共同点吗?因为事务包含了工作区和透明视图,那么工作区,透明视图和事务就真的是一个概念吗?或者它们是三个概念,就像图上显示的?
抽取CM概念的另一个困难是过载的概念,也就是概念有太多的目的(这些目的在CM系统中并不统一),例如,图谱中的Rational子系统概念支持限制变更的范围,尽管子系统提供了更多的功能,它可以:提供名称范围边界,对工作区来说则代表了工作在一个团队的不同配置或同样配置,提供了接口检查或者代表了一个不易变和可执行组件(Rational术语的"load view")。所以,为了讨论子系统,有必要专著于某个特定的方面,因此,过载造成了抽取基本概念的难度,类似的,概念的组合部分,或者是某个概念特定实现的副作用,让概念的抽象更是充满技巧。例如,考虑一个变更请求,生命周期的角色(例如配置经理和测试经理)和阶段(开发和测试)是否对其至关重要,还是毫不相关?
在任何等级,概念的图谱提供了开发的开始点,或至少抽取一个CM模型--一组基础CM服务--从存在的CM系统。此外需要许多检验工作:图谱的用处,是否有其他概念,如何定义,命名和展示概念及其它语义,如何组合概念到一个有用的CM系统。