软件项目管理(七):软件项目配置管理
一、软件配置管理的作用
(一)星形网拓扑结构
- 不同程序员对程序的更改会产生冲突
(二)软件项目中可能遇到如下的问题:
- 找不到某个文件的历史版本;
- 开发人员使用错误的程序版本;
- 开发人员未经授权修改代码或文档;
- 人员流动,交接工作不彻底;
- 无法重新编译软件的某个历史版本;
- 因协同开发,或者异地开发,版本变更混乱导致整个项目失败;
- ……
软件项目进行中面临着持续不断的变化,变化可能导致混乱,而软件配置管理就是用于控制变化。
软件配置管理(Software Configuration Management, SCM)是指一套管理软件开发和维护过程中所产生的各种中间软件产品的方法和规则。它是控制软件系统演变的学科。
(三)软件配置管理的目标
- 标志变更
- 控制变更
- 确保变更正确实现
- 向受变更影响的组织和个人报告变更
(四)软件配置管理的效果
- 记录软件产品的演化过程。
- 确保软件开发者在软件生命周期中的各个阶段都能得到精确的产品配置。
- 最终保证软件产品的完整性、一致性、可追溯性。
(五)软件配置管理的主要功能
- 版本控制:采用相应的流程和工具,对软件开发过程中产生的各种文件的版本进行管理。是软件配置管理的核心内容。
- 变更管理:为防止开发人员对软件的随意变更而进行的管理上的审核过程,包括变更请求、变更评估、变更批准/拒绝、变更实现。
- 其它:配置审计、配置状态统计等。
二、 软件配置管理的相关概念
(一)软件配置项(Software Configuration Item, SCI)
- 软件配置管理的对象,一个软件配置项是项目中一个特定的、可文档化的工作产品集。
- 常见的软件配置项:需求规格说明书、设计规格说明书、源代码、测试计划、测试用例、用户手册。
- 构造软件的工具和软件赖以运行的环境也常常列入配置管理的范畴。
(二)基线(Baseline)
- 已经正式通过复审和批准的某规约和产品,它因此可作为进一步开发的基础,并且只能通过正式的变化控制过程来改变。
- 各开发阶段结束时形成里程碑基线。
在软件配置管理中,基线的含义在不同的应用场合会有所不同。
- 软件配置控制委员会(Software Configuration Control Board, SCCB)
负责管理软件配置项变更的组织。
- 评估变更
- 批准/拒绝变更申请
- 在项目生存期内规范变更申请流程
- 对变更所产生的后续影响进行监督和控制。
- 与项目管理层沟通
三、建立软件配置管理环境
(一)企业级的工作
(1)建立工具集
- 一个企业的配置管理工具应该统一购买、安装、设置和维护。以节约资源,提高工作效率。不要每个项目都搞一套工具。
- 情况差别很大的项目可以考虑使用不同的工具,但要尽量减少工具的种类。
(2)建立软件配置管理规范
- 在企业级建立标准的软件配置管理规范,如变更控制流程、版本编号规则、缺陷跟踪流程、分支策略等。
- 一个软件项目可使用标准的软件配置管理规范,如果有特殊需要,可对其进行剪裁,或重新制定规范。重新制定的项目规范,如果今后有很多类似的项目,可把其上升为企业级标准规范。
(二)项目级的工作
(1)识别和标志配置项
- 将软件项目中需要进行控制的工作产品定义为软件配置项(SCI)。
- 配置项分为两类:
- 基本配置项:软件开发者在项目开发过程中所创建的基本工作单元。
- 集成配置项:一个集成配置项是基本配置项或其它集成配置项的集合。
(2)建立配置库
- 配置管理库,简称配置库,是配置管理环境的核心,使用配置管理工具建立。
配置库存储配置项(SCI)、修改请求、变化记录等,并提供对库中所存储文件的版本控制。
- 为不同的人员(如开发人员、测试人员、集成人员、项目管理者)分配不同的访问配置库的权限。
- 配置库中的配置项每经历一次改变将形成一个新的版本并被分配相应的版本标志。配置库中通常以增量方式存储配置项的各个版本,以减少空间消耗并增强版本处理的灵活性。
- 例如:一个配置项最初从开发者的工作空间提交到配置库,形成最初版本,如1.0,此后每修改和提交一次版本就会变化,如1.1,1.2,……,配置库采用增量方式存储每个版本,以节省空间。可以在任何时候得到配置项的任何版本。
四、版本控制
(一) 配置库的检入检出机制
- 配置库的检入检出和版本控制机制解决了团队软件开发中的两个重要问题:
- 访问控制:保证具有相应权限的人员才能修改配置项。
- 并行控制:保证不同人员同时对某配置项进行的修改不会互相覆盖。
(二)防止版本覆盖的两种方法
- 第一种方法:串行(加锁-解锁)。
程序员在修改文件之前,版本控制工具将文件加锁,其他人不能对它进行修改。该程序员修改完毕,将文件再检入到配置库中时,版本控制工具再将其解锁,其他人才能进行修改。
特点:效率较低,应尽量减小加锁范围。
Visual SourceSafe (VSS),微软出品的版本控制工具,默认支持第一种方法。通过设置,也可支持第二种方法。
- 第二种方法:并行(修改-合并)。不同的程序员可同时修改某一文件,修改完成后,在某一合适的时刻进行合并(由版本控制工具辅助完成)。
特点:效率较高
Subversion(SVN)、ClearCase(CC)都同时支持以上两种方法,但以第二种方法为主。
- 市面上还有几十种版本控制工具,它们都至少支持以上两种方法中的一种
配置项的演化图(Evolution Graph)
(三)适时更新工作空间
- 开发人员在自己的工作空间中工作的时候,配置库中可能已有了很大的变化,其他开发人员已向配置库提交了很多代码。这样,自己的工作空间中的代码就有过时的风险,使得自己开发的代码不能与其他人最新的代码共同工作。
- 因此开发人员需要适时地更新(update)自己的工作空间。
- Subversion中的更新就叫“update”。其它一些工具还有另外的称呼,如变基(Rebase),重新配置(Reconfig)等。
- 什么时候更新?
- 在开始一个新任务的时候,如开发一个新功能模块,修改一处代码等。这时的更新建立了关于这个任务的初始工作环境。不要在一开始的时候就落伍
- 在完成任务的过程中,可能需要更新。特别是在任务持续时间较长的情况下。要跟上时代的步伐
- 在任务完成后,即将提交的时候,最好做一次更新,并测试一下,以保证自己新写的代码,可以与别人的代码一起工作。保证提交有基本的质量。做事要善始善终
- 注意:更新工作空间也不必要太频繁
(四)记录源代码整体版本
- 在软件项目周期的不同时期会产生不同的版本,且在同一时期也会有不同的版本。
- 因此需要记录软件的整体版本,明确软件的每个版本都包含哪些特定版本的源程序文件。
- 记录源代码整体版本的方法:
- 方法一:在软件开发过程中,当某一版本形成时,复制其所有源代码。一些版本控制工具提供的复制(Copy)命令即可完成这一任务。
- 方法二:记录某个整体版本,只需要记录这个版本是由哪些文件的具体哪个版本组成的。因此可以在相关文件的特定版本上打个标签(Label/Tag),标签的名字,就是整体版本的名字。
- Subversion支持以上第一种方法。此外,Subversion总是自动地产生新的整体版本。程序员的每一次提交,都会产生一个新的源代码整体版本号,将这一整体版本号分配给所有源程序文件。因此Subversion实际上也支持以上第二种方法。
- ClearCase采用的是第二种方法。
(五)基线及其质量状态
- 在谈论源代码版本管理的时候,基线(Baseline)的含义是,被明显地标志和记录下来的源代码整体版本。
- 基线具有质量状态:
- 刚刚标记出来的时候,其质量未知(Initial);
- 编译链接和打包通过后,其质量是通过构建的(Built);
- 如果通过了一定程度的测试,其质量是通过测试的(Tested);
- 如果通过了详尽测试,可以发布,其质量是可发布的(Released)。
- 当基线由一个较低的质量状态达到了一个更高的质量状态时,就产生了一个基线提升(Baseline Promotion)。
- Subversion可以用版本属性来表示基线的质量状态。
- ClearCase UCM明确地支持基线提升。不仅有相应的命令,也可以在图形界面中操作和查看。
(六)保存安装包
- 在发布软件之前,或在对软件进行系统测试或验收测试之前,需要生成安装包。安装包同样需要保存,并标上相应的版本号,原因如下:
- 将来在需要该安装包时,可以迅速准确地得到它,不必从源代码开始重新编译、打包,这样可以节省时间。
- 用户或系统测试人员发现的软件Bug,有可能是由安装包的生成过程造成的,保存了安装包,可以快速地定位Bug的原因。
- ClearCase不仅存储和管理源代码,也存储和管理由源代码生成的内容,这些内容被称为“导出对象”(Derived Object),包括可执行文件、库文件、数据文件等。安装包也是导出对象的一种。
(七) 软件版本编号方法
- 源代码文件、文档文件和产品整体(源代码整体和安装包)都有版本号(Version Number)。
- 版本号的命名,目前业界尚无统一做法。
产品整体版本编号
数字顺序型版本编号
普通版本编号
α和β版本编号
属性版本编号
配置管理工具的自动版本编号
(1)数字顺序型版本编号
- 普通版本编号
产品的版本号由若干数字组成,数字之间用“.”分隔。一种典型的编号策略如下:
x.y.z,x为主版本号,y为特征版本号,z为缺陷修复版本号。
主版本号的增加表示提供给客户的主要产品功能的增强。
特征版本号的增加表示产品新增了一些特征或做了一些重要修改。
缺陷修复版本号的增加表示在软件产品上做了一些缺陷修复工作。
- 当某一级版本号增加时,其下级版本号要清零。
-
α和β版本编号
- 在普通版本编号后面增加一个大写字符A或者B来分别表示α版本或β版本。例如1.2.4A或1.2.4B。
- 如果存在多次的α发布和β发布,可在A或B后面添加一个数字来说明发布的次数,例如:1.2.5A1,1.3.0B2。
(2)属性版本编号
- 开发团队内部对版本号也有要求。
- 把版本的重要属性反映在版本标识中。可以包括的属性有:客户名、开发语言、开发状态、硬件平台、生成日期、技术特征、质量状态等。例如:
J2SDK.v.l.2.2:10/31/2000-18:00,native threads, jit-122
(3)配置管理工具的自动版本编号
- 为了唯一识别配置库中某个配置项的某个版本,配置管理工具会自动为配置项进行版本编号,其编号规则固化在配置管理工具中。
- 例如常用的两级制版本编号规则:前一级标志分支,后一级标志同一分支中的特定版本,多个前后级标志串联起来可以表示任何复杂的版本。两级标志之间用“.”或“/”连接,分支的标志可能使用字母,也可能使用数字。
(八)项目外资源的版本控制
- 除项目中所产生的源代码、文档、数据等配置项外,项目所使用的一些外部资源也应纳入版本控制。
- 把外部资源纳入版本控制并不意味着一定要把它们放入配置库。
- 以二进制形式存在的软件包一般不适合放进配置库,特别是当它很大的时候。可以保存在共享目录里,加上适当的描述说明和适当的存取权限。
- 在项目中,要记录清楚使用了哪些外部资源,什么版本。可以用文本文件或表格的形式记录,并放入配置库中。
五、系统集成
(一)集成有什么作用?
- 系统集成(System Integration),简称集成,就是把软件产品的各个组成部分组合在一起,使产品作为一个整体是可以运行的。
- 集成要对软件进行编译、链接和打包,并要对软件产品进行粗略测试(Rough test),也称冒烟测试(Smoke test),证明其基本可运行,值得送交测试人员进行详细测试。
(1)软件开发过程分析
- 软件开发一般按如下过程:
- 开发人员在开始一个开发任务前,用配置库的最新代码更新自己的工作空间,编译链接。
- 开发人员分别在自己的工作空间中完成开发任务。
- 开发人员在提交前,用配置库中的最新代码更新自己的工作空间,编译、链接和测试(主要测本次任务所做的修改),通过后提交到配置库中。
- 为了保证软件质量,测试人员要定期或不定期地从配置库中取出所有最新代码,编译、链接和打包后,进行系统地、全面地测试。测试过程中如果发现bug,提交到缺陷跟踪系统中,进行修复。
- 以上开发过程在规模较大,开发人员较多的项目中,很可能出现以下问题。
- 测试人员从配置库中取出最新代码后,编译链接不通过,通过后,又几乎不能运行,阻塞测试进程。
- 开发人员在用配置库中的最新代码更新自己工作空间后,经常编译链接不通过,阻塞开发进程。
(2)为什么会出现问题?
- 开发人员由于疏忽大意等原因,提交的代码有质量问题,或忘记提交一些文件。
- 即使开发人员的工作完全正确(提交前已更新了工作空间,并通过了测试),仍有可能出现以上问题,因为不同开发人员所做的程序改动,可能是不相容的。
(3)怎样解决问题?
- 加入集成工作:定期或不定期地把配置库中的最新代码取出,进行编译、链接、打包和粗略测试,及时发现和解决问题,使配置库中的代码具有一定的质量,并形成基线,供测试和开发人员使用。
- 开发和测试人员即使不使用基线,也同样能从集成得到好处。
(4)由谁来集成?
- 开发人员要适时更新自己的工作空间,使自己开发的模块能够与产品整体协调工作,这实际上也是集成工作。只是其关注点是局部性的。
- 集成工程师(Integrater/Integration Engineer)也称构建工程师(Buider/Build Engineer)负责全局性的集成,他把各开发人员提交的代码修改汇集在一起,确保产品整体是集成的,并且具有一定的质量。这种集成工作称为狭义集成(Narrow Integration),而更一般意义上的集成称为广义集成(General Integration)。
(二)集成的一般步骤
- Step 1:确保开发人员都提交了相关的源代码。为了更严格地进行控制,可以预先制定一个列表,规定本次要集成哪些工作,在集成开始前检查一遍是不是所有规定的模块都已提交,列表之外的改动有没有被提交。在必要的时候(比如产品即将发布前),每次提交都必须得到授权。
- Step 2:冻结或者标识将要集成的源代码。必须明确集成了哪些内容,即集成了哪些文件,以及文件的哪些版本。为此需要冻结源代码,在集成前禁止开发人员向版本库提交,或者用打标签的方式把当前的整体版本标志出来。
- Step 3:取出要集成的源代码。最好存放在一个全新的工作空间,不包含一些杂项,如一些编译的中间文件和结果文件,尚未提交的本地修改等。
- Step 4:编译、链接和打安装包。这一过程通常称为构建(Build)。如果遇到了问题,需要修改源代码,回到第一步。
- Step 5:安装并粗略测试。如果发现问题,修改了源代码后,回到第一步。
- Step 6:标志和储存集成成果。集成成果有两个:一个是源代码的整体版本(基线),一个是生成的安装包。通常还要生成一个“发布说明”,说明本次集成了哪些功能和修改。
- Step 7:通知相关人员本次集成完成。即发布集成成果。
(三)集成中的测试和纠错
- 集成过程中,编译链接通过后,要做粗略测试,或称冒烟测试。
- 测试不宜太多太细,否则会降低集成的频率,延缓基线的产生,阻塞后续的开发和测试工作。
- 粗略测试的目的是排除那些严重的、对后续工作有严重影响的错误。
- 把所有可能出现的严重问题按照严重程度排序,选择前面的若干问题,作为检测对象。
- 针对这些问题编写测试用例。
- 如果能自动执行这些测试用例,则可以显著提高集成的效率,提高集成的测试强度,有利于频繁地集成。
- 如果在测试中发现了问题,通常采取以下两种方式处理:
- 对于容易解决的问题,立即着手解决;
- 如果问题比较棘手,需要开发人员仔细研究,那么通常应把引起问题的提交从配置库中剔除,也就是回退合并,使本次集成不再包含该提交。
- 开发人员在修复问题后,再次提交到配置库,与此同时,配置库中还可能出现了其他开发人员正常的提交,两者混杂在一起,如何处理?
- 方法一:在集成工程师开始集成之时,先把配置库锁上,除非允许,禁止提交。如果集成过程中发现了问题,由相关人员修复,在取得权限后,把修复提交到配置库。直到集成完成产生基线后,再解锁配置库。该方法较保守,可能会阻碍开发过程。
- 方法二:在集成工程师开始集成之时,把配置库中要集成的分支(称为“集成分支”)锁上。如果在集成过程中有开发人员要提交,就开辟临时分支,让程序员提交到临时分支上。集成完成后,再把该分支上的内容合并回集成分支。
- 方法三:集成工程师始终不锁集成分支。当集成遇到问题时,如果集成分支上已经有新的正常提交,就为本次集成开辟出一个临时分支,把为本次集成所做的修复提交到临时分支上,并在临时分支上产生基线,再把基线合并回集成分支。
- 方法四:集成工程师始终不锁集成分支。当集成遇到问题时,即使集成分支上已经有新的正常提交,也把为本次集成所做的修复提交到集成分支上。当集成工程师再次编译构建时,不仅包括了为本次集成所做的修复,也包括了新的正常提交。本方法最为简便,但有一定的风险。
- 究竟采用哪种方法,视具体项目情况而定。
(四)使用集成成果
1、测试人员会使用集成生成的安装包进行详尽的测试。 2、集成所产生的软件源代码整体的一个基线对开发人员是有用的。 3、开发人员在更新自己的工作空间时,如果每次都是更新到软件最新的代码,则有可能出现编译链接不通过的情况,阻碍自己的开发工作。 4、解决方法:更新工作空间时,不更新到配置库中的最新内容,而是更新到最近一次集成产生的基线。这种方法称为间接工作流(Non-immediate Workflow)。 5、而更新到最新内容的方法称为直接工作流(Immediate Workflow)。 6、Subversion默认使用直接工作流,也可以实现间接工作流。ClearCase默认使用间接工作流,也可以设置为直接工作流。
(1)间接工作流和直接工作流
(2)间接工作流的缺点
- 如果一个程序员需要拿到其他程序员最新的代码修改才能继续工作,而其他程序员的最新代码修改还没有被集成到基线中,那么只有等待,直到下一次集成完毕后产生新的基线。
- 程序员在提交程序修改时,只能保证自己的修改在上一个基线里没有问题,而不能保证在版本库中最新的软件版本里没有问题。
(3)解决方法
- 方法1:做出折衷,如果需要的最新代码不在基线中,就使用直接工作流;在提交修改之前,也使用直接工作流。
- 方法2:加快集成的频率,快到配置库里的最新代码一旦有问题,几乎可以立即被发现,并被立即解决。从而保证即使是用直接工作流,每次更新得到的也是被集成后有一定质量的基线。
(五)持续集成和持续交付
1、为了尽可能快地发现和纠正配置库里源代码的问题,保证在绝大部分时间里配置库里的源代码是没有问题的,不对开发人员产生负面影响,需要提高集成的频率,
例如每天、每半天、每两小时甚至更短的时间间隔,执行一遍集成,这种方法称为持续集成。
2、提高集成频率也要有个度,因为每次集成要付出一定代价(编译、链接、打包和粗略测试)。当提高集成频率的好处被所付出的代价抵消时,就要考虑是否应该这样做。
(1)持续集成的自动化
- 由于集成的频率很高,持续集成通常需要自动化工具的支持,将编译、链接、打包、部署和测试(通过自动化测试脚本)连贯地自动执行下来,并自动报告集成成功或所发现的问题。
- 自动化的集成不仅可以提高集成的速度,还可以提高集成的准确性和可重复性。
- CruiseControl是开源的持续集成工具。
- Build Forge是IBM Rational出品的构建和发布管理系统,能够很好地支持持续集成。
- 持续集成工具可以在适当时机启动集成过程,例如周期性地(如每两分钟)探测集成分支上有没有新的提交,一旦有新的提交就启动新一轮的集成。
- 持续集成工具可自动把配置库中的最新(集成分支末端的)代码下载到本地。这通常调用版本控制工具的一行命令就能完成。
- 自动执行编译、链接、打包操作。这通常调用开发工具的一行或几行命令就能完成。
- 自动执行粗略测试。这要求预先设置好测试环境,准备好测试数据,并编写自动测试脚本。
- 最后自动创建基线,收集相关信息,例如本次集成包含了哪些修改等,生成“发布说明”。
- 以上过程的任意一步如果出现了问题,持续集成工具会立即报告给相关人员(通过邮件、短信等方式)。
- 自动化的持续集成
(2)频繁更新和提交
- 开发人员频繁地更新工作空间和提交自己的改动,也能尽早发现源代码集成问题。
- 开发人员使用配置库中的基线或最新代码更新自己的工作空间后,进行编译、链接和检测(属于广义集成),可发现一部分问题。
- 开发人员频繁地提交改动,也有利于集成工程师尽早发现和排除代码集成问题。
- 频繁地提交少量改动还有利于减少不同开发人员执行的任务之间的等待。
- 提高更新和提交的频率也要有个度,因为这些操作需要时间。
- 要特别注意,不要因为提交逻辑上不完整的改动而对其他开发人员、测试人员和集成工程师造成困扰。
- 不要对提交做一些僵化的硬性规定。例如:在提交前必须执行完一个较大的、不能自动执行的测试用例集;每天下班前必须提交当天的修改。
(3)持续交付
- 当完成了软件的某一版本后,可将软件交付给用户使用,这种交付(delivery)活动往往不是一次性的,而是多次的,甚至是频繁的,即持续交付(continuous delivery)。
- 持续交付的目的有以下两个:
- 尽快发现和解决系统在用户使用环境中出现的问题。
- 尽快向用户提供新功能,为用户创造价值,并尽快对市场新动向做出反应。
(六)多层集成
1、典型情景:几个人共同完成一个大的任务,需要紧密配合,频繁交流。此时他们每个人所完成的任务不宜频繁提交到开发团队所有人使用的公共环境里。
因此他们有必要组成一个“小圈子”,每个人完成了自己的程序模块后,先提交到小圈子里,在小圈子里集成无误后,再提交到公共环境中,与其它程序再进行集成。
2、两层或两层以上的集成称为多层集成(Multilevel Integration).
3、使用多层集成的情况:
* 多个人合作完成一个任务,需要互相高度配合,而该任务作为一个整体,与其它任务关联不大,此时应考虑使用多层集成。
* 大型项目开发人员众多,源代码也庞大复杂。研发团队分成了若干研发小组,每个小组负责完成一个组件(或一个子系统),
此时可以考虑在每个小组内做第一层集成,然后再做小组间的总的集成
(1)复合基线
- 一个系统是由不同的组件组成的,各组件的集成工程师都会通过集成形成本组件的一系列基线。
- 系统的总体集成工程师取得各个组件的特定基线,通过集成,形成系统整体的一个基线,即复合基线(Composite Baseline)。
- 复合基线在基于组件的软件开发中有重要作用。
- ClearCase UCM提供了复合基线功能。Subversion需要手工记录复合基线,或通过编写脚本来实现复合基线功能。
(2)组件集成的工作方式
- 方式1:通常情况下,组件的集成是在最近一次系统总体集成创建的复合基线上工作。组件集成工程师取得复合基线中其它组件的基线,与本组件一起集成。
- 方式2:也有可能,组件集成工程师需要取得其它组件的最新基线,与本组件一起集成。
- 方式3:在少数情况下,组件集成工程师需要取得其它组件中最新的代码修改,然后与本组件一起集成。
- 具体使用哪种方式,视具体情况而定。
(3)组件开发人员的工作方式
- 方式1:使用配置库中最新的代码更新自己的工作空间,即直接工作流。
- 方式2:使用配置库中本组件和其它组件的最新基线更新自己的工作空间,属间接工作流。
- 方式3:使用配置库中的复合基线更新自己的工作空间,也属间接工作流。
- 使用哪种方式也取决于具体情况。
- 大型项目中,组件的开发人员通常只修改与自己相关的一个或几个组件,而其它组件对他来说应该是只读的,以防止随意修改。
(4)工具支持
- 以上不同工作方式的工具支持:
- Subversion可让程序员人工进行配置和设置,也可以借助一些脚本来完成。
- ClearCase引入了UCM项目的概念。一个UCM项目包括了一个或多个组件的开发。一个软件项目可以包括多个UCM项目。通过合理地设置UCM项目,进而适时创建基线和复合基线,能够对基于组件的开发起到不错的支持作用。有时也需要写一些脚本来完成特定功能。
(七)集成中的构建
1、构建(Build)就是从源代码生产出安装包的过程。包括:
编译
链接:生成可执行程序
打包:把所有对用户有用的东西打成一个安装包
2、构建有时可能不包括打包,比如程序员编译和链接程序后进行测试,此时构建过程就只包括编译和链接。
(1)保证构建的可重复性
- 构建可能会遇到的问题:
- 产品的某个版本,在源代码没有改变的情况下,这次构建后产品没问题,下次构建出现了Bug。
- 产品的某个版本,一个人构建后产品没有问题,另一个人构建后却出现了问题。
- 产品的某个版本,现在构建没有问题,一段时间(也许是几年或者更长)后再构建却出现了问题。
- 构建结果的不可预测会给软件开发和维护带来困扰!
- 保证构建的可重复性就是指保证每次构建一个具体的产品版本,得到的结果是相同的。
(2)为了达到这一要求,需要保证:
- 构建的输入(所有源代码、文档、数据等)是固定和明确的。
- 构建的工具和环境是固定和明确的。包括特定品牌和版本的编译器、打包工具、操作系统,以及硬件配置。
- 参数设置是固定和明确的。包括编译、链接和打包的命令参数,工具和环境的配置参数(例如操作系统的环境变量)。
- 构建过程是固定和明确的。比如Ant文件、相关的脚本;操作的执行顺序等。
(3)为了做到以上几点,通常有以下策略:
- 自动化:尽可能将构建过程自动化,减小出差错的可能性。例如使用构建工具来执行脚本。
- 文档化:详细记录构建过程、构建环境等信息,使任何人都可根据这个记录文档来正确执行构建过程,得到正确结果。
- 与源代码的版本绑定:将构建工具、配置参数、执行脚本、说明文档等与源代码一起放到配置库中。一旦导出了特定版本的源代码,也就同时导出了对应该版本的所有这些内容。
(4)加快构建速度
- 全量构建:完全重新编译源代码,继而链接、打包,不利用上次构建所生成的中间结果。
- 增量构建:尽可能地利用上次构建的成果,只重新编译那些发生了改变(和受改变影响)的源代码。特点:速度更快,但不如全量构建可靠。
- 原则:
- 在追求构建速度的时候,倾向于使用增量构建,例如程序员自己构建的时候。
- 在强调构建的可靠性的时候,倾向于使用全量构建,例如集成工程师进行构建的时候。
- 其它措施
- 使构建自动化:使用Ant、Makefile等构建工具,将整个构建过程自动化。
- 分布式构建:把构建任务分解,分布到多个计算机(或多个CPU)上并行构建。
- ClearCase自带的构建工具Clearmake支持Unix平台上的并行分布构建。
六、分支管理
分支(Branch)是软件版本演化图中的一条路径,是软件的一个独立演化的版本序列。
在配置库中,各分支是独立存储的。
在软件版本演化图的众多分支中,有一条是主线(mainline),也称主干(trunk)。所有其它分支都从主线分出,并有可能会合并回主线。
(一)为什么要使用分支?
- 原因一:需要创建一个不同的版本。
- 原因二:一组人员需要在一个相对独立的环境中互相配合共同完成一个大的任务。
- 深层次原因:软件开发进程面临着两个基本问题(一对矛盾),即适当隔离和适当共享。
- 适当隔离:在工作过程中,各人或各组需独立地工作,不希望被别人意外地干扰,也不希望干扰别人。
- 适当共享:各人或各组的工作,应该在适当的时候,以适当的方式,共享和集成。
- 分支同时对隔离和共享提供了支持。
- 一条分支被创建后,它的生长是独立的,工作在一条分支上,不会与主线或其它分支相互影响。
- 分支的起点是分支的基础,是分支继承的内容;不同分支上的工作成果,可在适当的时候合并。
(二)分支的合并
(1)分支的合并是指把一条分支上的版本的内容,带到另一条分支(例如主线)上。分为两种情况。
- 整个分支上的工作成果均合并过去。
- 只将分支上的一部分工作成果合并过去
(2)分支的合并是一种复制行为,合并后被合并分支上的各版本不会受任何影响。
(三)分支典型应用一:多层集成
- 整个项目团队使用主线,“小圈子”是一个分支。在分支上的工作不影响主线。在分支末端进行一次集成,然后合并到主线上。
(四)分支典型应用二:管理交迭
- 交迭(Overlap)就是指软件不同版本的开发在时间上重叠。
- 典型情景一:某软件的1.0版本基本成型,等待发布。此时软件的大部分功能都已完成,但还有少量辅助功能没有完成,并可能存在很多缺陷,等待测试和修复。在1.0版的完善和测试期间,大部分程序员处在空闲状态,等待测试人员通知修复缺陷。直到1.0版软件达到质量要求,发布出去,然后再开始2.0版的开发。
解决方法:为了使1.0版的完善工作和2.0版的升级开发工作并行,可利用分支。
- 典型情景二:在做系统集成工作之前,需要冻结代码,防止开发人员在集成工作期间,随意提交新的修改,影响集成工作。如果集成的时间比较长的话,必然会影响软件开发工作的效率。
解决方法:为了使集成工作不阻滞开发工作,可使用分支。
(五)分支典型应用三:管理变体
- 变体(Variant)是同一类软件产品,它们有很多相同之处,却又有所区别。
- 变体之间虽然相似,但不可能进行合并。
- 产生变体的最常见原因包括:
1. 因支持不同的操作系统而产生变体
例如同一个软件产品在Windows系统上和Unix系统上的不同版本。两种版本所调用的操作系统接口以及开发环境都有很大差别。
2. 因客户定制而产生变体
对于同一种软件产品,不同的客户提出的要求有区别,例如财务管理系统,不同客户的财务管理制度、管理流程是有区别的,因此需要特殊定制,从而产生变体。
3. 因不同的功能集产生变体
软件不同的变体是针对不同的消费群体的需要而制作的。例如Windows Vista有七个版本:家庭类的初学者版、家庭基础版、家庭标准版和家庭终极版;商务类的小企业版、
专业版和企业版。
- 用分支支持变体的第一种方法:为每一个变体创建一个分支。
- 第二种方法:为变体不同的版本创建不同的分支。
(六)关注主线的演进
- 不管版本树的分支有多少,都应该有一条主线,作为开发工作的主流,集中精力于主线的演进,其它分支以主线为基础进行开发。
- 例如,当软件存在多个变体时,不能不分主次地为每一个变体创建一个分支,各自独立开发。
1、错误的版本树形状
2、正确的版本树形状
3、有问题的版本演化策略
- 该策略存在的问题:
- 分支层数太深,可能会超出版本控制工具的分支层数范围。
- 文件的版本演化历史信息复杂,分布在不同的分支中。
- 开发人员需要经常更换分支,容易出错。
(七)分支管理要点
- 分支不能随意创建,必须有所规划,适当管理。
- 分支管理要注意以下几点:
- 分支要有明确的目的。分支应有一个名字,简略说明分支的目的。
- 分支要规划好何时创建,从何处创建。
- 分支要规划好是否合并?合并到哪里?分支上所有的工作成果都要合并,还是有选择地合并?
- 分支要规划相关角色和权限:谁有权读取分支上的内容或向分支提交?分支的合并及分支上的集成工作由谁负责?谁负责创建、删除和重新命名分支?
- 分支的规划要全盘考虑,看版本树的整体图景,而不要只关注手边的工作。
七、变更管理
(一)影响变更控制方法的因素
对软件原有配置项的改变叫做变更(change)。对变更必须进行有效的管理,避免其产生负面影响。
变更管理(控制)方法主要受以下因素影响:变更的规模、变更的影响面、变更发生的时间、开发过程模型、研发团队的规模。
(1)变更规模对变更控制的影响
- 有些变更可以较快完成,且规模较小,比如缺陷的修复,对功能进行的少量增强。对于这类比较小的,数量又比较多的变更,可采用缺陷跟踪的方式来跟踪和管理。
- 有些变更需要不少的人力和时间,对项目的进度和预算都有影响,对这样的大型变更,就需要更严格的控制和企业高层的介入。
(2)变更影响面对变更控制的影响
- 有些变更只会影响到产品的局部,而有些变更则可能会产生广泛的影响,例如公用函数库的变化。
- 对于有广泛影响的变更,必须有更为严格的控制,变更前要广泛征求意见,认真评估,变更后要通知大家,发生了什么改变。
(3)变更发生时间对变更控制的影响
- 越到项目后期,变更的代价就越大,因此对变更的控制就越严格,也越不容易接受变更。
- 在项目末期,通常只会接受缺陷修复和小的功能增强。
(4)过程模型对变更控制的影响
- 在瀑布模型中,项目各阶段的工作是顺序执行下来的,前一阶段的工作成果是后一阶段工作的输入,它要求前一阶段的工作成果一旦确定下来后,尽量不发生变化,否则对后续工作的影响太大。
- 在瀑布模型中,要更严格地控制变更。而在迭代型/适应型过程模型中,可以有更多的变更。
- 迭代过程模型的核心思想是“尽早反馈”。
- 迭代过程模型把一个大项目在时间轴上划分为若干个小周期,每个小周期称为一个迭代(Iteration)。几乎每次迭代结束时,都会产生一个可见的成果(可运行的软件包)。用户可对该成果进行评估,提出修改意见。研发团队也可以在短短的一个迭代周期内就发现需求、设计等方面的问题,从而可在下一个迭代中进行变更。
- 迭代过程模型对待变更的态度更为现实、更为积极,在采用迭代式开发的项目中,变更更为频繁。
- 通常在一次迭代开始之初,研发团队讨论确定本次迭代要进行哪些变更。但在每次迭代进行过程中,一般不会接受大的变更,因为每次迭代应该有相对确定的任务。
(5)研发团队规模对变更控制的影响
- 在小型团队里,当变更发生时,人员之间可以采用随意的沟通方式。但在规模较大的团队中,可能需要采取一些正规的方式解决沟通和协作问题,使变更得到控制,例如建立变更控制委员会,将变更请求条目的状态变化自动发送邮件通知相关人员。
(二)严格的变更控制过程
(1)变更请求
(2)变更评估
(3)变更审批
- 根据评估结果对变更作出决策:
- 直接实现变更
- 挂起或延迟变更
- 拒绝变更
(4)变更实现
(三)任务管理
1、任务(Task)是由软件项目团队人员所执行的一个活动,它生成或改变配置项。
2、变更是通过执行任务完成的。
(1)任务流程的设置
- 为了控制变更,保证任务结果的质量,任务需要按照一定的流程执行。
- 优秀的配置管理工具可以对任务流程进行定制,如ClearQuest、JIRA。
- 任务流程可使用状态模型图或状态转移矩阵表示。
1、典型的缺陷任务(缺陷跟踪)流程的状态模型图
2、典型的缺陷任务(缺陷跟踪)流程的状态转移矩阵
3、典型的新任务流程的状态模型图
(2) 任务流程中的权限设置
- 在任务流程中,不同的人员角色具有不同的职责和权限。
- 配置管理工具应能够设置在任务的每个状态下可由那些角色执行哪些动作。
- 任务流程涉及的常见的人员角色包括项目管理人员、开发人员、开发小组长、测试人员、测试小组长、集成人员。
- 项目管理者包括项目经理及其他变更控制委员会成员,其权限包括创建、取消、分配任务,使任务处于新建、已取消、已分配等状态。
- 开发小组负责人的权限是在任务处于已分配状态时根据需要对任务进行重分配或取消不必要的任务;在任务处于评审状态时批准或驳回任务已完成的修改;对处于已推迟和正在工作状态中的任务,可根据小组人员安排情况,在组内重新分配。
- 开发人员的权限是:在任务处于已分配状态时,接受任务,使之处于工作状态;如果认为任务无效(例如缺陷不能重现或与其它缺陷报告重复),可以把任务退回;在任务完成后可提出评审申请。
- 测试负责人的权限包括:当认为缺陷确实是无效时,可把缺陷取消;对测试人员已验证的缺陷进行审查,如果没有问题可最终关闭缺陷任务,否则可打回测试结果,要求测试人员重新验证。
- 测试人员的权限包括:对于被退回的缺陷任务,可对缺陷报告进行补充和澄清,再重新分配给开发人员;对开发人员已解决的缺陷进行测试验证,如果通过将缺陷置于已验证状态,如果不通过则驳回该缺陷的修改结果。
- 集成人员的权限是:如果由开发人员提交的任务结果导致集成失败,可驳回任务结果,由开发人员继续完善;如果集成成功,可将任务标记为“已集成”状态。
(3)建立任务间的关系
- 父子关系。将一个复杂的任务分解为多个子任务,由相同或不同的人员去完成。
- 配置管理工具应该建立父任务和子任务之间的关联性,并可自动在它们之间同步,例如只有当所有子任务都已完成并通过验证,父任务才能通过验证。
- 依赖关系。任务之间必须按照一定的顺序去执行,一个任务开始或完成后,另一个任务才能开始或完成。
- 重复关系。重复关系一般出现在缺陷修复任务之间。由不同的人员报告的缺陷实际上是一个问题,为了避免后续开发人员重复分析处理同一个问题,应在这些缺陷任务之间建立重复关系。开发人员只要处理其中一个任务,其它任务就会自动同步地发生状态变化。
(4)自动邮件通知
当任务的状态发生改变后(例如一个任务被分配给了一个开发人员),相关人员应及时得到通知。自动邮件通知是最常用的一种方式。
在配置管理工具中实现自动邮件通知一般需要以下步骤:
- 设置邮件服务器。
- 一般应使用局域网中的邮件服务器。
- 需设置邮件服务器的名称、SMTP端口等信息。
- 设置邮件通知方案。
- 邮件通知方案规定了当任务流程中一个动作发生时,应向哪些用户发送邮件。
- 在配置管理工具中,应该可以新建或修改邮件通知方案。
- 把邮件通知方案赋给项目。一个邮件通知方案可用于多个项目。
- JIRA的邮件通知方案编辑界面
-
(5)任务信息设置
- 正确地设置任务信息不仅有利于变更控制,而且可以为项目管理和过程改进提供丰富的数据。
- 优秀的配置管理工具(如ClearQuest、JIRA)可以对任务信息进行定制。
- 任务信息通常包括描述信息、范围信息、人员信息、附加信息等。
- 任务描述信息
- 任务标志:任务的唯一标识符;
- 任务标题:简单描述任务的单行文本;
- 任务详细描述:详细地描述任务的细节,是任务执行者主要的依据;
- 优先级:确定任务执行的优先顺序;
- 严重程度:通常用于缺陷任务,表示缺陷对系统的影响程度,例如可分四级:1-Fatal, 2-Critical, 3-Major, 4-Minor;
- 影响:任务影响的一些活动;
- 状态:任务当前在处理流程中所处的状态;
- 范围信息
- 产品:标明任务属于哪个产品。
- 版本:标明任务属于产品的哪个发行版本;
- 模块:标明任务属于产品中的哪个模块;
- 功能:主要用于缺陷任务,说明缺陷是由哪个功能引起的。
- 人员信息
- 执行者:任务在当前状态下的执行者;
- 报告者:任务的提出者。
- 附加信息
- 估计花费时间:估计完成该任务所花费的时间,单位为小时;
- 实际花费时间:完成该任务所实际花费的时间,单位为小时;
- 缺陷发现方式:如测试、评审、用户使用发现等。
- 缺陷引入阶段;
- 缺陷原因分析;
- 附件:有利于任务执行的一些资料,如错误发生时的屏幕截图、日志文件等。
(6)任务数据对项目管理的支持
- 项目是通过执行所有的任务完成的,所以从配置管理系统所记录下的任务信息中,可以提取出丰富的支持项目管理的数据度量,例如:
- 有关项目进度的度量:
- 项目当前完成的功能数和总功能数的比例;
- 当前已解决缺陷数和未解决缺陷数的比例;
- 每周新发现的缺陷数趋势图;
- 未完成的任务趋势图,按周统计。
- 有关产品质量的度量:
- 缺陷模块分布,反映各模块的质量;
- 缺陷严重级别分布,反映产品的总体质量;
- 有关工作效率的度量:
- 缺陷发现方法分布,反映测试、评审工作的效率;
- 任务在特定状态下停留(老化)的时间分布,反映开发人员的响应速度;
- 每周返工的缺陷数,反映缺陷修复的有效性。
(7)如何获取和展示数据
- 软件配置工具应该提供便利的机制,为项目人员查找所需的数据,并以表格或图形的方式显示出来。
- 例如,ClearQuest提供了许多固定的数据查找、统计模板,用户只需要双击相应的模板就能得到所需的数据;用户可以在已有模板的基础上做调整,定义出新的模板;用户还可以从头设计自己的数据查找模板,以实现更复杂的查询、统计和报表功能。
- JIRA、Bugzilla也有数据统计和报表功能。
八、配置审计和配置状态报告
- 配置审计的目的是验证配置项的特性是否满足特定标准和规范。属于“过程检查活动”。
- 通常在软件开发每个阶段结束后,或产品发行之前,都要进行配置审计,它是正式技术复审的一种补充。
- 配置库中是否已纳入了所有已标志的配置项?
- 配置项的名称和版本标志是否符合规范?
- 配置库中的配置项存储位置是否符合规定?
- 是否在配置项中显著标明了每次所作的修改?
- 配置项的变更是否符合变更控制流程?
- 是否定期备份了配置库?
- ……
- 不要把配置审计误解为“对配置库中的每个配置项都检查一遍”。不要在配置审计上花太多的时间。
- 配置审计的对象是项目的主要配置项,如果主要配置项符合规范,就可以认为配置管理符合既定的规范。反之,如果质量人员在审计的时候发现主要配置项比较混乱,那么应当告知当事人及时更正。
- 配置状态报告
1、记录和报告配置项变更处理过程的相关信息。这些信息包括一个已批准的配置识别清单,变更请求当前的
处理状态,以及批准的变更的实现情况。
2、对于大型项目的开发,配置状态报告非常重要,它促进了人员之间的通信,有利于人员之间协调一致地工
作。
- 配置状态报告所记录的数据,有时需要经过统计分析而得到综合数据,例如每月或每周产生的变更请求数、处理的缺陷数,当前未处理的缺陷数,当前处在某一状态的变更数,等等。统计分析结果可以用分布图、趋势图等形式直观地显示出来。这些综合数据对软件项目管理有着重要意义。
九、配置管理过程
(一)制订计划
- 制订计划,需要考虑到产品开发过程中,软件配置管理的方方面面:
- 配置项的识别和标记:源代码、安装包、文档。
- 配置管理工具。
- 变更管理规则:变更请求、并行修改、版本间差异等等。
- 配置管理的角色和职责如何划分?人员是否需要培训?
- 配置审计计划和配置库备份计划。
- 作为计划的成果,常常是一份软件配置管理计划(SCM Plan)文档。
- 制订软件配置管理计划,一般由软件配置管理工程师主导,由项目经理审批。
- 软件配置管理计划模版
(二)做好准备
- 需要在工具、过程、人员三个方面做好准备。
- 工具:如果在组织级已经提供了适用的软件配置管理工具,则只需简单地为这个项目做初始化工作,比如创建项目、创建目录、往版本控制工具中导入初始版本、设置合适的参数,等等。如果组织级并未提供合适的工具,则需要考虑工具的选择、购买、安装、设置等。
- 过程:如果在组织级已经确立了通用的软件配置管理过程,则应该考虑拿来使用,也可能根据项目的实际情况,进行适当的裁剪和定制。如果组织没有确立或完全确立通用的软件配置管理过程,则可能需要为项目特别制定软件配置管理过程。
- 人员:首先要保证各个软件配置管理相关岗位,已经有合适的人选,特别是软件配置管理工程师和集成工程师。其次要保证各个角色已经有足够的能力,来完成软件配置管理方面的工作,如果欠缺经验和能力,应该考虑进行相关培训。
(三)日常工作
- 项目组的所有人员在产品开发过程中都会参与配置管理的日常工作,如源代码和文档的版本控制、系统集成、变更管理等。
- 软件配置管理工程师主要负责保证软件配置管理系统的正常运行。例如配置管理工具的维护工作和手动备份工作,人员权限的管理,帮助使用者解决工具和流程方面的疑难问题等。
(四)监控、调整与改进
- 监控的目的在于及时发现软件配置管理中的问题并纠正。
- 随着项目的进展,项目的软件配置管理策略、方法可能需要调整;随着对软件配置管理认识的不断提高和经验的积累,会对软件配置管理的流程和工具进行调整和改进。
- 软件配置管理的监控、调整与改进工作可能由软件配置管理工程师主导,也可能由质量保证人员主导,另外过程改进人员也常常参与。
(五)收尾
- 在产品发布,项目收尾阶段,软件配置管理同样需要进行收尾。主要包括两个方面:软件资产的整理和归档、软件配置管理本身的总结和共享工作。
- 在项目收尾时,软件资产的整理归档进入关键时刻,这个时候保存的软件资产是业已成型的软件资产,是最有价值的资产。
- 软件资产的整理和归档,包括对源代码、安装包、文档的妥善保存;包括对各个历史版本,特别是发布产品对应的历史版本的妥善保存。同样重要的还有对开发环境的整理和归档,对变更请求等相关数据,也应该进行整理和归档,保证将来仍可查询。
- 软件配置管理本身,也是一种资产,称作过程资产。在项目即将结束时,应对整个项目过程中的软件配置管理工作进行总结,得到的经验教训,供以后其它项目参考。
- 在整个项目过程中,可能对软件配置管理流程或工具进行了调整和改进,要考虑是否有可能将这些调整与改进加入到组织一级的软件配置管理中,供以后其它项目使用。
十、软件配置管理工具
(一)软件配置管理工具
- 软件配置管理工具的主要功能
- 版本控制
- 变更管理
- 配置审核
- 状态统计(查询和报告)
- 问题跟踪(跟踪缺陷和变更)
- 访问控制和安全控制
- 常用的配置管理工具
- ClearCase & ClearQuest
- CVS
- Subversion(SVN)
- PVCS
- Harvest
- Visual SourceSafe(VSS)
(二)CVS概述
1、CVS (Concurrent Versions System, 并发版本系统)是一个被广泛应用的配置管理工具。
UNIX和Linux的发行版一般都带有CVS服务器,Eclipse内建有CVS客户端。
CVS是自由软件,可免费获取其安装包和源代码。
2、CVS提供了多种途径帮助开发团队成员之间的版本同步和开发通信,辅助解决版本冲突,提高协同开发的效率。
(1)CVS的几个特性
- C/S模式
- 基于“修改—合并”的并发控制
- 客户端check out后,有文件的一份独立拷贝。
- 开发者在自己的工作目录中修改文件。
- 若有版本冲突,则与其它开发者的修改合并,然后提交(check in)。
- 记录不同版本之间的差别
(2)CVS安装包的获取
- CVS支持Unix、Linux、Windows、Mac平台。
可从http://www.march-hare.com下载其安装包和源代码。
- CVS在Windows上的版本称为CVSNT。
- tortoiseCVS —Windows上的一个常用的CVS客户端。自由软件,官方网站:http://www.tortoisecvs.org/。
(三)CVS常用操作
- 创建仓库(repository)
- 导入项目/模块
- 检出项目/模块
- 修改并提交(检入)文件
- 更新文件
- 取回文件的某个历史版本
- 文件比较
十一、本章小结
- 理解软件配置管理的作用和有关软件配置管理的相关概念(配置项、基线、SCCB)。
- 了解建立软件配置管理环境的方法。
- 理解配置库的检入检出机制和防止版本覆盖的方法。
- 理解适时更新工作空间、记录源代码整体版本、保存安装包的必要性和方法。
- 掌握软件版本编号的常用方法。
- 理解系统集成的含义,了解其一般步骤。
- 理解持续集成、分层集成的含义。
- 理解构建的含义和保证构建可重复性的方法。了解加快构建速度的方法。
- 理解分支管理的相关概念、作用、方法和典型应用。
- 了解影响变更管理的因素。
- 理解严格的变更控制过程。
- 了解配置审计和配置状态报告的作用。
- 了解配置管理过程
- 了解软件版本控制工具的常用操作功能。
十二、参考文献
- 董越. 未雨绸缪—理解软件配置管理. 电子工业出版社,2008.5
该书以通俗易懂的语言讲述了软件配置管理的基本原理,内容较为实用。
- 董越. 软件集成策略—如何有效率地提升质量.电子工业出版社,2013.7
该书系统地讲述了软件系统集成的原理。
原文链接:https://blog.csdn.net/yongchaocsdn/article/details/80883326