UML软件工程组织

如何规划一个UCM工程
孙志强 , IBM中国软件开发中心软件工程师

  本文根据UCM的主要特点,结合具体的应用场景,从涉及到UCM工程建立的几个重要方面着手,阐述了如何按照实际需求设计规划一个具体的UCM工程,以保证其适用性。

 在软件开发过程中,配置管理贯穿于整个开发过程的始末以及后期的维护阶段,它为成功构建软件工程提供有效的支持手段。从工程开始的一刻,配置管理就应被纳入软件工程构建的初始计划与后续规划中。IBM Rational提出了软件配置管理策略的最佳实践统一变更管理(UCM),同时以强大的配置管理工具ClearCase及变更追踪工具ClearQuest作为平台支撑,有力促进了配置管理的实施。在具体的应用中,各个工程的需求和特点各不相同,如何应用UCM策略及ClearCase和ClearQuest的灵活性,定制一个最佳的配置管理工程实施方案,就成了配置管理人员所面临的首要问题。

对于工程经理和配置管理人员来说,UCM工程(Project)提供了一个配置管理的基本框架,涵盖了对配置项存储结构的管理,开发过程中流(Stream)和基线(Baseline)的管理,并且可以通过UCM工程来处理同变更追踪工具ClearQuest的集成。通过对UCM工程的定制和规划,可以有效处理配置管理中遇到的主要问题。

一 配置管理的需求与起点

在实施配置管理之前,很有必要清楚地了解配置管理的需求,并根据工程的实际需要,确定配置管理开始的起点。

所谓配置管理的需求,就是将什么软件开发中所产成的工件置于版本控制中,使用什么样的手段对其进行管理,如何在软件开发过程中方便有效地对其进行存取。首先,我们需要确认或者预测在软件开发过程中,软件开发团队会产出什么工件,团队中的担任各种角色的成员如何对其进行使用。一般情况下,大都将频繁修改的软件源代码以及对应的目录结构至于版本控制之下,但这并不是配置管理的全部,配置管理的优势所在是能够记录整个软件开发的历史,并能够在时间点重现此时软件开发工件的状态。为了达到这个目的,除了软件的源代码和相应的目录结构需要处于版本控制之下以外,还可能需要将以下在软件开发过程中产生的工件纳入配置管理的范畴:

软件系统的需求文档,包括需求说明书,用例模型等等;
 软件系统的设计文档,包括体系结构设计文档,详细设计文档以及相关的模型文件,如Rational Rose模型文件等等;
 工程计划书,包括度计划、开发计划及测试计划等等;
 用户手册或者使用指南;
 库文件,包括静态库以及动态链接库
 可执行文件
 软件的界面定义文件
 开发工具及支持平台
 测试脚本;

 将上述工件定义为配置项的目的就是能够重现在软件开发过程中任何时间点重现的当时状态,从而保证软件系统版本的可再现性。但是在配置管理的实施过程中,也可根据实际需要,对具有隔离性的配置项分开进行独立管理,例如可以将与软件系统版本关联性较强的各类文档、库文件、可执行性文件定义在一个UCM工程管理框架内,而将相对保持稳定的开发工具与支持平台、测试脚本、计划书等等至于基本的版本控制之下。这样可以减少配置管理的复杂度,提高具体实现的效率。

UCM将个体文件和目录抽象为更高层次的对象,即UCM组件(component)来表示软件架构,通过变更活动(activity)来控制对配置项的更改,将工程活动同具有不可预测的变化可能性的软件工件集成起来,提供了在较高层次管理软件工件开发的能力。在实际应用中,通常使用UCM工程来管理一个产品或者是一组产品的开发及后续变更。那么何时开始建立一个UCM工程开始软件开发的配置管理呢?

通常情况下,一个UCM工程的启动应该以软件系统体系结构设计的完成为前提。体系结构是一个软件系统在其运行环境下的高层抽象,它体现了软件系统的高层次结构的设计和实施,定义了软件的组织元素、对外接口及其之间行为元素。通过软件体系结构的实现视图(Implementation View),我们可以获得在开发环境中软件的静态组织结构,以此为起点,在UCM工程中将软件工件的架构映射为UCM组件的组织结构,从而建立起配置管理系统的最初框架。

回页首

二 将软件工件映射为配置项

在配置管理系统内,所有受版本控制的文件或者目录都作为配置项或者配置元素(element)进行管理,而UCM通过将相应的配置项聚集到一个UCM组件内,以便于对大量的软件工件进行管理。因此,首先应该将配置项组织为结构合理的UCM组件,然后使用UCM工程对组件进行统一管理。

在描述软件体系结构的4+1视图中,实现视图由于指定了用于实现软件系统逻辑包、对象或者模块的文件和相关目录,这对于配置管理系统的设计来说非常重要。依据实现视图,可以为即将开发的软件系统定义UCM配置管理组件,使用这些UCM组件将相关的目录和文件组织起来,便于以后的开发、集成与发布。举例来说,在一个软件系统中可能包含有用户权限控制模块,那么在实现视图中就会指定由哪些文件和目录来构成这个用户权限控制模块,那么我们就可以将这个相对独立的模块映射为一个UCM组件,将该模块对应的文件和目录聚集到该组件下进行管理。在实际应用中,既可以将一个独立模块或者组件映射为一个UCM组件,也可以将一个子系统或整个软件系统映射为UCM组件,我们可以根据具体情况来确定UCM组件的粒度。 如果使用IBM统一开发流程(RUP)来指导软件的开发,由于RUP推荐使用组件来组合成一个系统,而组件具有内聚性及相对独立性,就使得将软件系统映射为UCM的组件结构更为清晰。

图1所示的是一个软件系统体系结构实现视图的包图,整个系统被划分为五个相对独立的模块,使用包(package)来表示,限于篇幅,我们不再详细展示包内部的文件及目录组织结构。由于包内部的内聚性以及包与包之间的相对独立性,在一般情况下,可以直接将一个包映射为一个UCM组件,因此可以将其置入五个对应的UCM组件中,并按照实现视图来组织UCM组件内文件和目录的组织结构。

 

     图1 一个软件系统的实现视图 ― 包图

 除了要将实现视图中对应的源文件和目录识别并聚集到UCM组件,还需要一些额外的UCM组件对软件开发过程中的其他工件进行管理。通常,一个典型的软件应用中还可以引入以下的UCM组件:

系统组件:系统组件内部存放重要的系统级的文件,包括工程计划、需求文档、设计文档以及其他系统架构文档等等;
 测试组件:该组件内部存放系统测试的相关文件,包括测试脚本、测试结果与日志以及其他相关的测试文档等等;
 部署组件:在系统开发周期结束时,我们需要一个单独的组件来存储部署软件系统的文件,包括可执行程序、链接库以及用户文档等等;
 工具组件:为了保证开发平台的一致性,可以将开发工具放在单独的组件内进行统一版本控制。

 在使用ClearCase来创建UCM组件时,可以将整个版本对象库(VOB)作为一个UCM组件,也可以将VOB内的某一个一级目录定义为UCM组件。如果工程规模较小,可以只使用一个VOB,将VOB下的若干个一级目录定义为相应的UCM组件,这样可以减小系统负荷,提高运行效率。对于较大规模的应用来说,将大量的配置项集中到一个VOB会为管理和维护带来许多不便,例如难以备份和恢复,难以对VOB进行清理,另外,一个超大的VOB也会在一定程度上降低VOB服务器的性能。针对这种情况,可以使用分布在一个服务器或一个命名域(Region)的不同服务器上的多个VOB进行管理,将关联性较强的UCM组件聚集到一个VOB中,将其他相对独立的组件分散到其他VOB中进行管理,这样便于管理维护,有利于具有多台服务器的配置系统的负载均衡。另外,在软件开发过程中,某些文件和目录在某一版本开发过程中处于只读状态,例如工具组件、一些共享的链接库、公共接口或者系统文档,因此有必要将需要读写权限控制的配置项聚集在单独的UCM组件中。

在识别出配置管理系统中所有的UCM组件之后,接下来创建UCM工程对其进行管理,这时需要决定使用单个UCM工程还是多UCM工程。UCM工程最大的意义就是为一个群组提供一个开发、集成、测试以及部署的环境,达到共同构建一个软件系统的目的。如果一个软件系统各个模块的关联度较高,开发成员需要紧密地进行工作,并且当前只进行一个版本的开发,不考虑同一个工程的多版本并行开发,那么该工程的配置管理只需要使用一个UCM工程即可完成所有的工作。然后对于有些规模较大的系统来说,如果各个子系统或者模块耦合度较低,在开发过程中互相影响不大,为了便于管理,往往使用多个UCM工程对其进行管理,将某一个或者若干个模块或子系统使用一个单独的UCM工程进行管理,在软件系统开发后期再对整个系统进行集成。另外,如果一个软件系统需要多个版本的并行开发,例如,同时需要新版本的开发和旧版本的升级,这时,也需要使用不同的UCM工程分别来对其进行管理。

如果多个UCM工程建立在一个工程对象库(PVOB)中,那么这些不同的UCM工程则可以共用一个PVOB内的UCM组件,在建立UCM工程时指定包含哪些UCM组件,选择需要使用的UCM组件基线,确定是否具有对UCM组件进行修改的权限。在软件开发过程中,还可以根据需要添加和去除相应的UCM组件,并可更改此UCM工程使用的各个UCM组件的配置基线,以便于能够使用合适的版本来进行集成开发。为了避免冲突,并且能够保证软件工件的一致性,当多个UCM工程共用一个组件时,除了针对该UCM组件的工程,其它使用该组件的工程只具有读取权限。如果实在需要多个工程对某一个UCM组件具有改写权限,则要定期将更改该组件所关联的活动交付(deliver)到统一的流上,并进行相应的归并(merge)和基线更新。下图所示配置管理系统使用了两个UCM工程。

 
          图2 一个配置管理系统的工程组织结构

 该软件系统分为两个子系统进行并行开发,一个开发团队负责系统主要功能和图形界面(GUI),另一团队负责系统Web应用界面的开发。使用一个UCM工程MainProj来管理系统主要的功能、对外接口以及图形界面的开发,所有UCM组件在该工程中均为可写状态。 Web应用开发团队只需要使用由主系统开发团队定义的系统接口,而专注于Web应用层的开发,与系统其它模块的耦合度极小。因此可以将管理Web应用的UCM组件和管理系统接口的UCM组件置于UCM工程WebInterfaceProj中,并将Web应用UCM组件属性设为可写,系统接口UCM组件属性为只读。当系统的对外接口改变并建立新的Adapter组件基线时,Web应用工程只需要更新该工程中Adapter的配置基线,即可获取最新的接口信息。

回页首

三 流(Stream)的使用策略

ClearCase UCM使用流(stream)为外界提供一个可以相对独立访问VOB的手段,一个流以一组基线作为基础,通过建立在流上的UCM视图对选取配置项进行访问。一个流与建立在流上的UCM视图就形成了一个相对隔离的工作空间(workplace)。流及工作空间的使用者并不局限在软件开发人员,一个工程中的其他人员例如测试人员、系统分析人员等等也可以使用UCM来访问和管理他们的工作成果。

在一个UCM工程中,一般将流分为两类:集成流(Integration stream)和开发流(Development stream)。在一个工程组内,一般使用共享集成流来表示工程成员的最终变更结果,将其他成员在开发流上的成果提交(deliver)到集成流上,汇聚完所有开发流上的变更后,通过创建基线在指定合适的里程碑,然后在开发流上通过复原操作(rebase)将开发流上的基线与集成流上的推荐基线保持同步。

在实际应用中,一个UCM工程既可以只使用一个流,即单流UCM工程,也可以使用多个流,即多流UCM工程,用户可以在创建UCM工程时加以选择(如图3所示)。



               
             图3 选择单流还是多流UCM工程

在创建UCM工程时,首先就需要在单流和多流中选择使用哪种结构。下面我们讨论一下这两种结构的特点及使用场景。单流结构意味着所有成员使用一个共享的流进行工作,工程成员的工作空间建立在一个集中一致的数据之上,任何一个成员的变更如果提交到ClearCase的流上以后,能够在其他成员的工作空间内得到反映。因此,单流结构的UCM工程仅仅提供一种简单串行开发模型,不同的用户使用简单的检出/检入操作来更改和提交变更。一般来说,在下列情况下会使用单流结构的UCM工程:

1. 工程的开发采用敏捷开发过程(Agile development),开发人员需要尽快看到别人所做的变更。

2. 在工程开发初期阶段,若干个开发人员需要即时共享代码。

3. 由少数开发成员(1-3)组成的小组集中起来进行的小规模开发,成员间需要紧密开发,成员之间的变更需要即时可见。

4. 使用UCM工程来管理ClearCase无法提供图形化合并(Merge)的资产,例如图形文件、二进制文件等等。

下图所示的是采用单流UCM工程的工作流程:



               图4 单流UCM工程的工作流程

 图5所表示的是个典型的单流UCM工程的版本树


         图5 单流UCM工程中元素的版本树

从上图中可以看出,该UCM工程的集成流为"UCM单流工程_集成流",开发团队包括王刚与李亮两位开发人员。在开发活动中,开发人员通过关联分配给自己的活动直接从集成流中检出所需的文件版本进行变更,当完成变更并将其检入到源控制之后,其他开发人员就能看到对其所作出的变更,由于整个变更流程为串行开发,开发人员始终访问的是集成流中的数据,因此在开发过程中使用的数据都是最新的。鉴于此,当开发人员完成变更并要将变更结果检入到源控制时,需要完成完整的测试,保证变更的有效性,以免影响到其他人员的工作。作为集成人员来,需要适时监控开发人员对项目作出的变更,并根据变更所关联的活动创建项目基线,并在根据项目进展的程度决定推荐基线。

相对于单流结构而言,多流结构的UCM工程意味着不同的开发人员使用一个单独的私有工作流,开发人员之间的工作空间保持一定的隔离性,同时,不同的开发人员又使用一个共享的集成流,当开发人员个体完成对应的变更并将工作成果提交到集成流之后,所有的成员才可以看到最新的变化。集成人员在集成流上适时地创建基线,并根据项目的进展状况设置推荐基线,各个私有开发流通过复原(Rebase)操作,使得各个开发流的基线同集成流推荐基线保持一致,从而使各个开发成员在同一基础上进行变更活动。

在UCM工程中,集成流与其衍生的多个相对隔离的开发流使得并行开发可以顺利得以实现,但是多流结构又使得配置管理系统的复杂性大大增加,不会像单流UCM工程那么易于管理和维护。通常,在下列情况下适于使用多流的UCM工程:

1. 开发人员需要一个相对隔离的私有工作空间,在将其成果共享给其他成员之前,需要在其私有工作空间内对其更改的源文件进行调适,确保其变更不会破坏系统的稳定性。

2. 需要对发布的版本或者项目的基线进行精确的控制。

3. 在项目进行过程中,集成流中常常会出现编译错误的情况下,需要使用多流UCM工程保证在私有空间内使用一个可以正常编译的基础版本。

4. 使用UCM工程来管理ClearCase能够提供图形化合并(Merge)的资产,例如文本文件、Rational Rose模型文件以及Word文档等等。

下面是使用多流结构UCM工程的工作流程:



            下图所示的是一个典型的多流UCM工程中一个元素的版本树:
            图 6. 多流结构UCM工程的工作流程


                        图7多流UCM工程中元素的版本树

 从上图中可以看出,该UCM工程的集成流为"UCM单流工程_集成流",在该集成流下衍生了两个开发流:"李亮_多流UCM工程_开发流"与"王刚_多流UCM工程_开发流",两个开发流基于统一的共享集成流,开发人员在各自私有的开发流上进行工作,相互之间保持一定的独立性,当个子的变更任务完成之后,将变更结果从开发流提交到共享的集成流。当变更之后的集成流逐渐稳定之后,集成人员在集成流上创建基线,并根据实际情况将最新的基线设置为推荐基线。之后,各个开发人员通过复原操作,将对应的开发流的基础同集成流的推荐基线保持一致,从而使各个开发成员在同一基础上进行变更。

回页首

四 基线(Baseline)的创建与维护

如图8所示,基线是一个UCM 组件在某一特定时刻一组元素的集合,它包含了在该时刻所选取所有元素版本的集合,用来记录在软件项目开发过程中完成的工作并标识具有指标意义的里程碑,并可根据需要,使用基线来重现某个特定时刻的配置。与动态的流(Stream)不同,基线的静态的,不变的。


                图8 基线

当完成UCM组件的组织与规划后,相应地,就要决定这些组件的基线创建与维护策略。具体可以包括:

如何根据UCM组件来指定一个UCM工程的基线。
 何时创建基线
 如何命名基线
 确定基线的级别
 如何对基线进行测试

 如果整个UCM工程仅仅使用一个UCM组件,那么该组件的基线即为该工程的基线。但一般来说,工程中可能会使用多个UCM组件,一个特定的工程基线就包含了该工程中每个组件的特定基线。当开发人员加入工程或者需要进行复原操作时,软件开发组织中的集成人员就需要告诉开发人员具体使用各个组件的哪个基线,因此有必要对每个组件的基线进行跟踪管理。如果工程中组件较多,手工维护势必过为复杂。ClearCase提供了一种有效便捷的方法,即复合基线进行管理,复合基线选取每个组件中的特定基线,可以用来表示整个工程的基线。限于篇幅,本文对其不再展开讨论,详细内容可参考http://www-128.ibm.com/developerworks/rational/library/5134.html

在一个项目的初始阶段,集成人员和项目经理需要确定使用哪些现有资源作为项目开始的起点,之后使用一个基线或者一组基线来对其进行表示。如果使用现有的UCM组件,那么使用组件内现有的基线作为新建工程的初始基线。如果使用现有的基本VOB(Base ClearCase VOB),那么需要将其已标识(labled)的版本转化为基线,而后将新建基线作为组件的初始基线。在软件开发过程中,也需要周期性(每天或者每周)地在集成流上创建基线,这样做可以达到以下目标:

1. 开发人员之间可以同步彼此的工作,通过周期性的交付,新建基线,从新推荐基线复原,开发人员可以共享彼此的成果。

2. 可以大大较少合并(merge)的时间与数量,当周期性的进行交付与复原时,需要解决私有工作空间与共享集成空间的版本冲突,从而在最终提交工作成果减少合并的工作量。

3. 可以及早发现软件的集成问题。当创建一个新的基线后,需要对软件进行编译、构建可执行程序。通过周期性的此类操作,可以及时发现在开发过程中对影响软件集成的问题。

4. 可以标识储存软件开发过程中重要的里程碑,例如每次迭代的最终版本,β测试版本,发布版本等等。

对于单流UCM工程来说,由于不存在开发人员私有空间数据同集成共享数据之间的问题,因此没有必要周期性地创建新的基线。而创建基线的目的则是为了标识存储软件开发过程中具有重要指标意义的里程碑。

每个基线都有一个相应的级别,所谓的级别就是标识一个基线质量和稳定性的属性,通过级别划分,可以大致了解一个基线的大体状况。缺省情况下,ClearCase使用以下级别:

Rejected:未通过测试,不建议使用
 Initial: 软件初始阶段的基线
 Built:可编译的基线
 Tested:完成测试的基线
 Released:通过测试验证,可以发布的基线

 一般情况下,在软件开发过程中需要执行不同等级的测试。在初始阶段,常执行确认性测试,验证是否可以正确地编译软件系统,这类的测试比较简单,也不会耗时太多。在随后阶段,还应执行更复杂的综合测试,例如功能测试、回归测试等等,这类的测试一般会花费质量保证人员相当的时间来完成。

当新建一个基线并需要对其进行测试时,首先需要锁定集成流,以防止开发人员继续提交变更而影响集成流数据的稳定性,由于项目初期的确认性测试不需要花费太多时间,因此也不会长时间锁定集成流,对于项目的正常进行不会造成大的影响。如果要进行长时间的复杂测试,则可以从集成流新建一个测试流,当在集成流新建基线后,首先锁定集成流,而后在测试流执行复原操作(指定新建基线为复原目标基线),而后对集成流进行解锁,在测试流进行具体的测试,这样就不会长时间锁定集成流,避免对正常的开发造成影响。

当通过一系列的测试之后,就可以提升对应基线的等级,并可根据具体情况,设定推荐基线,通过复原操作将最新的集成结果同步到各个开发流上。

回页首

五 考虑同ClearQuest的集成

在UCM环境中,软件系统的变更通过活动(Activity)来完成,从技术角度来看,我们可以把活动理解成软件变更活动的载体,而从软件项目开发这个人为活动的角度来看,我们也可以将UCM中的活动(Activity)同现实中的实际活动一一关联起来,这样就可以通过活动直观地明确变更的目的与起因。但是,ClearCase的活动仅仅能够记载活动的名称以及相关的注释,其间也没有任何的流程控制和历史记录,对于小型的UCM工程来说,管理起来并不复杂。但是对于需要通过大量变更活动来保证软件顺利演进的大型软件项目来说,不加控制和管理的变更活动会大大增加项目管理的难度,提高软件的风险。在这种情况下,就需要将UCM工程同变更管理系统ClearQuest相集成来解决这一问题。

集成后的UCM工程中的活动(Activity)同ClearQuest中的变更请求相关联(如图9所示),通过ClearQuest对变更请求整个生命周期的管理和跟踪,达到控制整个软件变更过程的目的。



             图9 UCM的活动同ClearQuest的变更请求相关联

  对于每一个变更请求,在不同阶段,ClearQuest根据不同的处理模式(Schema),项目中不同的角色在不同的阶段通过执行不同的Action来更改变更请求的状态,从而使得变更的处理按照预定义的模式统一进行。除了ClearQuest提供了几种缺省的变更处理模式之外,用户还根据需要,自定义缺陷处理模式,自定义变更管理字段格式,达到最佳应用效果。详细内容,可参考ClearCase与ClearQuest UCM红皮书。

回页首

总结

本文概括介绍了在新建一个UCM工程时需要考虑的几个问题,通过以上的讨论,希望能够使读者了解在创建UCM工程之前的准备工作,包括相应计划、策略等等。建立、运行并维护一个UCM工程是一项复杂的工作。除了上述讨论的问题以外,如何在UCM工程使用中根据需要进行相应的调整与维护,如何做好UCM配置系统的管理和控制,也是一项非常重要的工作。希望本文能给您的进一步学习奠定一块基石。

关于作者

孙志强,IBM中国软件开发中心软件工程师,目前从事IBM Rational ClearCase的测试工作。熟悉配置管理的理论与实践,以及软件产品的全球化测试。


版权所有:UML软件工程组织