软件配置管理

恼人不休的问题:什么是软件配置管理

配置管理关注系统的集成、完整性、复用。
比喻:
保险柜:避免丢失,避免窃取或泄露;
岩钉:如果升级失败,可以回退到哪一个版本;
脚印:基线、里程碑,可以评审检查;


基本的版本控制:记录历史并防止混乱

“因为有无数潜在的可能,会让尚未保存的修改化为乌有。比如邻桌把电源线踢了,比如编辑器崩溃了,比如操作系统崩溃了,比如一只老鼠迅速跑过键盘,后面还跟着一只猫…”
即使只有一个开发人员,也需要软件配置管理。经常随手按ctrl+s,有经验的还会经常备份源代码。
建立公共存储区,星形结构。
防止版本覆盖:
串行的方法,给文件上锁,例如早期的vss;
并行的方法,将所有人的修改合并,例如svn、git;
行话:
公共存储区就是版本库。
每次只存储不同版本间有差异的部分(增量存储)。
每个人在自己电脑上的私有工作区。


当代版本控制方法

变更集:
从源代码实际变动来看,是一个或多个文件上的一处或多处具体的代码改动的集合。
这可能是修复一个bug,可能是小调整一个功能,也可能是一项大的工作的分解。
通过的变更集,我们能够明确知道,某个bug是怎么修复的,某个新增加的功能,是对应了哪些文件。
另一个重要的目标是,提供参考,便于回退。
每个变更集对应的工作量,不要太大,所对应的源代码改动,不要太多。
以变更集为单位修改代码并提交。
为了保证你的工作成果能融入到当前的整个软件产品里,你需要适时更新你的工作区。
什么时候更新:
在变更集开始之前,可能需要更新,保证你是基于版本库里比较新的版本开始工作,不要在开始的时候就落伍。过于频繁的更新也没有必要。最后在变更集完成,即将提交的时候,最好做一次更新,并且测一下。
源代码整体版本:
一个程序的所有源代码作为整体,也要记录和保存版本,交给用户的是哪个版本,这个版本测试没测试过,用户报告了一个bug,是指的哪个版本上的bug。
每个变更集提交到版本库后,自然而然地形成了产品源代码的新的整体版本。一个又一个变更集提交上来,产品向前不断演进。


集成:关注整体质量

注意,即便是每个改动都是正确的,也不能保证捏到一起仍然是正确的。
集成有广义和狭义之分:
广义:当开发人员在提交之前更新工作区,并作自测试的时候,他是在看他的改动是否能跟别人新近的改动一起工作,这是在做集成,当他做完他所在的模块的单元测试,又测了一下应用程序外在的行为的时候,他是在看他的模块是否能跟别人的模块一起工作,这也是在做集成,随后,系统测试团队对应用程序的一些版本做更加全面的测试,并把发现的bug反馈给开发人员,以便修复,这个过程当然也是在做集成。
狭义:人们常谈论的是狭义集成,也就是集成工程师的工作,集成工程师获取源代码的最新版本,编译构建,并作粗略测试,如果此过程中遇到了问题,就解决问题,都没问题了,宣布系统新的版本,供系统测试团队深入测试,也供开发人员使用。
广义的集成很有必要,狭义的在小规模团队不是必须的。
提交前应该做充分的自测试,首先是单元测试,进而对系统整体进行测试。
敏捷时代,谈到单元测试,就提到测试驱动开发:先写好自动测试脚本,再开发,直到测试通过,这样做的好处是,用简单的脚本而不是繁复的文档,在开发前明确开发的目标,而在开发后又能自动地检验该目标完成的情况。
同行评审:又称代码走查。相关的有结对编程。
注意:测试驱动开发和结对编程还都是存在争议的新技术。
除了人来完成的,机器也可以在一定程度上代替人,这称作静态程序分析(Findbugs)。
提交前,必须做了比较全面的测试,如果已经有一段时间没更新工作区了,就做一次更新,然后在工作区里编译构建,并作粗略的测试,证明程序可以运行,这种粗略的测试被称作冒烟测试。
狭义集成的步骤:
确保开发人员都提交了相关的源代码。
冻结或者标示将要集成的源代码(临时禁止开发人员继续提交)。
取出要集成的源代码。编译、链接和打安装包(如果构建过程中,遇到了问题,如果是构建环境、构建过程相关的问题,由集成工程师自己来解决,如果是源代码的问题,就由开发人员来解决。如果整个问题比较复杂,就把有问题的提交,从本次集成中剔出去)。
安装并粗略测试。
标示和存储集成成果。
通知相关人员,本次集成完成。
狭义的集成目的:生成一个基线。
即便开发人员总是去拿公共版本里最新的内容,从统计上说,即便他们不直接使用基线,也会从狭义集成中受益。(因为狭义集成能够发现问题,不再是等到某个开发人员不幸的撞见了)
测试人员也需要基线,对基线做全面而深入的测试,发现bug,在缺陷跟踪系统里记录下来这些bug,通知开发人员整改,开发人员修复后,集成工程师集成,产生新的基线,再次送交测试人员测试。
广义集成三阶段:
开发人员更新工作区、代码评审、编译链接、做一系列自测试。(因为是围绕着发生的代码改动及其周围进行,所以可以有效的发现问题)
集成工程师狭义的集成。(在有限的时间里,保证程序在整体上没有什么大问题)
质量保证,消灭集成过程中的问题,直到达到质量标准,集成完成。(没在第一阶段就这样全面、广泛、细致的检查,是因为没有效率)


从源代码到运行中的程序

构建:保证可重复性,过程尽量快,应该得到相同的结果。
部署:当测试时,部署到测试环境,开发人员自测试也同样需要测试环境,用户会在一定的环境中安装并运行他。
为了保证构建的结果一样,需要:
原材料是固定和明确的。
工具是固定和明确的。
生成方法是固定和明确的。
需要尽可能的文档化构建过程。更好的办法是自动化。
全量构建:从头来过;增量构建:利用上次构建的成果。(增量的优势是快,劣势是不那么可靠)
强调速度用增量构建,比如开发人员给自己构建的时候,而强调正确性的时候用全量构建,比如构建发给用户的版本的时候。
让用户明确的知道所需运行环境,前提是,在产品研发过程中,明确的定义所需运行环境。


迈向持续集成

瀑布模型被证明是低效的。
及早和经常的集成,这是被广泛认同的最佳实践。
及早和经常的提交,三方面含义:
开发人员要经常提交。(不是说没等一个变更集完成就去提交)
如果开发需要一段时间才能提交,那么在开发过程中,要及时更新,不要留到提交前,或者干脆不更新直接就提交。
在集成工程师这一端,要经常(狭义的)集成开发人员提交的内容。
典型的有每日构建,在持续集成看来,可能还不够频繁。
测试环境必须是标准的。
不论是源代码版本控制,还是编译构建管理,还是测试运行时的管理,尽可能用简洁的方法,不要引入不必要的复杂性,因为复杂往往意味着容易出错、意味着不稳定、意味着难以重复、意味着高昂的人力成本。如果复杂性不能避免,那就尽可能的封装,这样我们才愿意有更频繁的集成,而不要在频繁的集成,在烦琐、枯燥、易错的重复性工作中耗费太多的心力。
“集成工程师敲一行编译命令,然后喝茶 ;等编译结束,再敲一行链接命令,然后挖地雷;在集成工作结束前,他还吃了些小点心,网聊了一会儿,然后散了散步,发现相邻部门新来的女同事很迷人。但是,另一方面,他不得不工作到晚上12点,因为大部分时间,都在等待中度过了。”
各个集成的步骤之间,最好也能够自动化。
想要频繁而又快速的完成集成,要确定待完成的质量保证工作的内容都是必要的,测试团队也并非需要对所有的基线都做测试。
多层集成:比如,一层是三个子任务集成为一个大任务,即增加一个新功能,而另一层是,这个大任务,与其他任务再集成。
如何分层,以及子集成之间如何划分,基本原则:内部高聚合,外部松耦合。
注意多层集成是有副作用:它走向了持续集成的相反方向。


分支:减少等待,分头工作

分支合并的目的是,把分支上的改动,合并到主干上来。主干又被称做主线、主分支、主控分支。
当我们看整个产品的版本演进而非单个文件的版本演进时,看到的是产品所有源代码的一个断面,加上一个变更集,形成产品的下一个断面,有些断面被明确的标示,有个有意义的名字,常被称作基线,但多数断面默默无闻。
这里的合并,是某种复制行为,分支合并并不会影响到原分支,变更集的复制也不会影响到原变更集。原分支上的变更集,以及原分支上的一个又一个整体版本,并不会随着合并而改变或消失。这里说的复制,不是指复制分支上的某个整体版本,而是复制整体版本之间的差异。
Svn直接支持产品级分支。
模式:通过一个位于中心的点来交换不同的开发人员或不同的开发子团队之间的代码改动,这个位于中心的点,可以是主干,也可以是分支,而位于四周的点,可以是工作区,也可是是分支。
位于中心的点,不论是主干,还是分支,都是在服务器端的存储库里,这意味着安全,不必担心丢失,意味着每个版本都被记录下来,可以回溯,意味着在版本控制工具的支持下,不会发生版本覆盖的情况,不会混乱。
位于四周的点,不论是用工作区,还是用分支,本质上都是达到了这样的效果:当使用它的开发人员不想受到来自外界的干扰时,他不会受到意外的打扰,也不会打扰别人。工作区或分支由开发人员完全掌控的,与外界隔离的。
分支和工作区一样,既支持隔离,也支持共享。
工作区与分支相比,有明显的功能上的不足,首先,记录的容量小,只能容纳一个未完成的变更集,没法记录历史,其次,安全性低。最后,狭义分支上有版本控制,能防止版本覆盖,因此可有有多人同时在上面工作,而工作区只适合单人工作。
分支的典型应用:
多层集成:从产品的某个整体版本开始,分支被创建出来,从这里开始生长,完成一个新功能,分支创建好了后,大家把自己的工作区定位到这条分支上,而不再从主干取最新版本。新功能开发完毕,测试没有问题后,把分支的改动合并到主干上。
管理交迭:1.0版发布以后,在继续研发2.0版,打算基于1.0版推出1.1版。从1.0版到2.0版的开发是在主干上,而从1.0版到1.1版的开发是在一条分支上的。
支持变体:比如推出windows版和linux版。
隔离试探性工作:事后证明你的实现方法可行,就把这条分支合并回到主干。
管理来自第三方的源代码:直接管理有时比较困难,可以用分支来体现。
分支需要有意义的、符合规范的名字。在你分支命名规范中,通常会体现出对分支的分类和分组。比如,所有的用于总体集成的分支,都使用int作为前缀(或后缀)。某个叫aaa的子团队用于子集成等工作的各条分支,都已sub_aaa作为前缀(或后缀)。这样做即便猜不出具体分支的名字,但可以缩小查找范围。
分支和分组的另一个好处是,便于划分和体现职责和权限。


管理文档

源代码是给机器看的,而文档是人写出来给人看的。源代码里的注释信息,本质上就是文档。如果注释比较多,就可能剥离出来,作为单独的文本文件。
文档通常“文责自负”,通常有明确的所有者。只有他可以改动该文件,其他人如果想改动也要告诉所有者一声。通常使用工具提供的锁机制,保证不同的人串行修改同一个文档,而非鼓励大家并行修改后合并。
文档通常“独立成篇”,文档之间相对独立。
文档与文档之间,文档与源代码之间,经常是不一致的、不同步的。需求文档里写的需求,可能还没有转化成设计,设计文档里提到的结构,可能还没有转化成实际代码、实际功能。机械的要求他们始终一致,只会降低工作效率。
文档被单独管理,而不是与源代码放在一起。
可以用管理安装包一样,使用可以共享访问的文件系统来存储文档。要考虑文档目录结构的合理规划,比如用什么样的结构,叫什么名字;要考虑文档文件的合理规划,比如要有哪些文档,存放在哪个目录下,文档叫什么名字。这些规划,不仅是每个项目、每个产品的规划要合理,还应该考虑,在一个项目中积累的经验,拿到下一个项目中使用。这通常体现为目录结构的模板,其中含有各个文档的模板,以此作为下一个项目的起点。
除了存储结构,还应该加以一定的权限管理。
每个文档文件的命名,除了文档名称本身外,一般应加版本号,共同组成文档文件的名称。
SharePoint
文档本身的一些信息,比如版本信息等,要由它自身携带。
文件名包括文档名称和版本号两部分,但这常常不够,文档中起始的一两页,常常用来更全面的记录和展现相关信息:
关于文档的名称,在文件名中,可能是缩写,在文档黄总,就应给出名称的全名。
应该以某种方式指出文档的“出处”,因为有时看到一份文档,会关心它有没有更新的版本,就要到文档的“官方”存储位置去找。
文档的状态:草稿(Draft)、评审中(In Review)和已发布(Released)。
用共享目录下的众多文件来组织和保存文档,有一些不便之处,比如对文档的并行修改,比如查看文档的修改历史记录,比如查找特定的内容就得依次打开各个文档。
Wiki:MediaWiki
Wiki页面中可以嵌入附件,提供搜索功能(是对内容的搜索,即全文检索)。
通常企业内部信息比较适合用wiki来承载。
有的文档用章节的形式组织,用文件来承载,不一定总是最方便的。比如一些需求管理工具、系统建模工具等。


跟踪缺陷,直到消灭

Bug的跟踪系统,学名叫缺陷跟踪系统,bug的学名叫缺陷(Defect)。
有些团队使用excel表格来处理缺陷跟踪。
BugFree
缺陷的状态:
已报告(Reported),又称创建、打开、初始,一般谁发现谁来填。
已分配(Assigned),分配给开发人员,条目里填上开发人员的名字。
已解决(Resolved),开发人员解决了这个缺陷。
已关闭(Closed),由测试人员完成,确定这个缺陷真的被修复了。
已报告的缺陷也会被认为不是真正的缺陷,会被直接关闭(加上些注释最好)。
重复的缺陷条目,也把它关闭(注释它跟某个缺陷是重复的)。
已解决的缺陷,测试人员发现它并未真正的解决,通常会重现打开,分配给上次修复它的开发人员(变回成已分配)。
本质上,我们是在讲述有限状态机在缺陷管理中的应用。
每条缺陷记录有一行标题(Title)或者叫总结(Summary),用来简述缺陷的内容。
一些字段起到类似作用,比如关键字(Key Words)。
详细描述(Description)一定要做到令开发人员和测试人员可以复现这个缺陷,要详细记录当时的操作环境、当时的操作步骤,以及当时的缺陷现象,这是处理缺陷和检验处理结果的依据。
严重程度(Severity),轻微、一般、严重、致命。
优先级(Priority),低度、中度、高度、最高。
规模小的团队,通常不必要优先级。
要遵循一个原则:避免带着许多缺陷前进,要尽快消灭。
对缺陷的统计:
回答缺陷是怎么分布的、数量是多少。柱状图、饼图等。
回答随着时间的迁移,缺陷的总体趋势是什么样的。趋势图。
关于缺陷的年龄的统计,时长图。
这些数据的采集和展现,应该尽可能得到缺陷跟踪工具的支持,人工来做,耗时费力。
通常可以把一条缺陷记录和一个变更集关联起来。便于查看这个缺陷的修复究竟改动了哪些源文件。简单的方法是,在变更集的标题或描述中,记录相应缺陷条目的编号。注意,缺陷记录和变更集之间的关系,并不一定总是一对一的关系。


管理变更

请求修复缺陷只是变更请求中的一种。
增强:指一些小的请求,把程序已有功能稍稍增强一点。注意,增强所导致的修改,常常不仅是源代码的修改,可能需求文档因此修改,用户手册也要修改,测试用例也可能要修改。
特性:典型的Scrum(一种以迭代、增量为主要特点的软件开发过程,是敏捷开发的一种),所有待完成的特性都列在产品订单里,每次迭代前,从这里挑出来本次迭代要实现的条目,把这些条目列在冲刺订单里,每次迭代通常是15到30天。在迭代过程中,一般不会改变冲刺订单,再一次迭代完成后,回顾工作成果和经验,再计划下一次迭代。类似的另一个典型是特性驱动开发(FDD)。
缺陷、增强、特性,从配置管理的视角来看,它们都是变更请求。
瀑布模型中,变更管理很中哟啊,一旦定下来的事,就要执行,不能乱改。但也不能禁止变更的发生。核心是严格控制变更。常见做法是设立变革控制委员会(CCB)。
因为变更控制的流程本身也耗费很大,所以使得团队越来越倾向于迭代的、增量的开发方式。让每次迭代需要开发的内容较少、容易确定;在设计和实现时,及早发现问题,在功能实现后,及早获得用户的反馈。项目早期的迭代,会把比较多的注意力,放在典型的、最重要的需求上,会把注意力放在产品的整体架构上,然后,通过编写代码以验证关键设计,通过向用户展示可运行的程序以验证关键需求,尽早的到这些关键问题的反馈。这样,以后的风险和难度就小多了。
缺陷一般来说都会被修复,而功能增强、新功能增加这类的变更则不同,即便是正确有效的,也很可能因时间、成本等因素不去实施,需要评估:
变更的大小、变更的影响面、变更的风险、变更发生时间、研发规模。
在版本控制工具里,可以考虑加一些控制,以保证开发人员做且只做该做的事,一种方法是,让变更集不由开发人员创建,而是由管理人员创建,然后指定给相应的开发人员完成。另一种方法是修改代码之后提交时控制。大多数情况下不需要这样的控制,除非是临近项目结束等,以保证集中精力在最重要的事情上。
需要以一定的方式表达产品版本间的差异:
查看版本控制工具。
查看问题跟踪工具中的变更请求。
查看项目计划或迭代计划。
查看需求数据库或需求文档。
集成工程师可以考虑使用脚本,在每次集成后产生完成条目的列表。


玄妙的学院派

当你打算开始软件配置管理工作时,先弄清楚要管哪些东西,包括:源代码、文档、安装包、环境和工具、编译工具等,这并不意味着一定得一个文件一个文件的标,源代码通常作为整体标出来就可以了,怎么划分全看如何让工作方便,在术语上,我们管这样标示出来的每一项的特定版本叫配置项(CI)。
配置控制(Configuration Control),特别是对变更请求的管理。
对于变更,协调工作:
考虑不同的变更请求之间的关联性,有些变更可能是说的一回事儿,或是相关的事,需要统筹考虑它们对设计的影响,它们的实现成本,是考虑让他们一起实现,还是拒绝或拒绝一部分。
一个变更请求可能会影响到不同的产品,可能对他的改动是在一个公共组件上的。
协调先后顺序,有的比较急,有的比较大,有限安排人力资源去完成,有的则可以拖一拖。
配置状态报告(Configuration Status Report),做配置管理,需要数据和信息的支持,包括三类典型的信息:(以车辆设计为例):
车辆由哪些零件,什么型号的零件组成的。应该是一个列表。
车辆设计在正式批量生产前,可能有改动的请求。变更请求的状态应该被记录。
变更实现的情况。
这些信息和数据,表现形式有三种:查询结果、报告和图表。
配置审计(Configuration Audit),是指对象本身是否符合需求或相关的标准,而不是制作对象的过程。
首先,要确保需求文档反映了客户的需求,设计文档反映了需求文档的要求,源代码实现了设计文档的目标,这样一层层递进,以确保跑起来的程序,就是客户想要的,这些主要是通过评审来实现的,特别是在瀑布模型中。在确定需求的时候,要与客户一起讨论、评审,直到需求文档被一致认可。在确定设计的时候,要与相关人员一起讨论、评审,直到确定设计文档的内容能够实现需求文档的要求,并且能够编程序实现它。在源代码编写完毕,要做同行评审,看是否符合设计,是否实现了需求,是否正确无误。
上述审计,大都需要评审者具有软件所在具体领域的知识,对软件的具体功能进行检查,这叫做功能审计。
在发布给客户的内容,是一个安装程序、一个发布说明文件和一个使用说明文档,那么在打包发布前进行检查,看这三项是不是都有,就属于物理审计。
能力成熟度集中模型(CMMI)中,对配置管理工作,从如下角度进行了划分:
建立基线,首先识别配置项,接着建立配置管理系统,用来存放配置项,最后通过评审或测试后,由配置项组成基线,作为未来开发的基础。
建立并控制变更,要追踪变更请求,要评估他们,分配给合适的人去处理它们,还要检查以确保它们确实被处理了,要控制对配置项的变更,如果要改它,需要合适的人同意,改好后,要适当检查,才能入库。
建立完整性,首先要对配置管理活动做足够的记录。其次要进行配置审计,确定配置项的内容是否合适,并出现在合适的地方,确定基线的内容正确。
制度化已管理过程,在一个软件研发项目中做配置管理,首先要建立配置管理计划,然后确保有足够的资源,包括工具、环境、也包括人员,在配置管理系统运转过程中要适当监控。
制度化已定义过程,要形成可以指导现在和未来多个软件研发项目的配置管理过程规范,这样的规范不是一成不变的,要收集相关信息、数据和反馈,并基于此进行软件配置管理的持续改进。
软件能力成熟度模型(SW-CMM)已被CMMI取代。
这些软件研发模型和标准都有光辉的思想在里面,都是有价值的东西,然而,是充分发挥出价值,还是没有产生价值,甚至产生负面影响,要看怎么去用它们,基本的原则是,深刻领会标准的内在思想,结合企业的实际情况应用这些思想,而应用标准需要有所选择和裁剪,对于特定研发背景,要弱化甚至舍弃不适用的部分,要以合适的方式具体化和实现需要的部分,应用标准来不得教条,不要为标准而标准,更来不得表面文章。


用分支实现迭代

先考查一下如下的情形:主干上比较古老的部分,是目标为1.0版的研发,主干上某一点,是1.0版本发布了,随后,主干上开始目标为2.0版的研发,现在正在向前演进,为支持1.1版,我们从主干上1.0版本发布对应的那一点起,做一个分支,岔出来,这条分支的目标是1.1版,也可能将来1.2版也在这上面。
把1.1版称作补丁版本(Patch Release)。
没有采用完全独立的两个目录或两个版本来实现,是因为,分支除了有隔离的功能外,还对共享有比较好的支持,使用分支,便于彼此同步和复用。
理想情况是,在1.x分支上,从1.0版起到1.1版之间所有的代码改动都应该拿到主干上,贡献给2.0版。
比较保险的做法是,对1.x分支上的每一个变更集,均由开发人员做出判断,是否适合合并到主干。
一般来说,新的分支在刚创建的时候问题不多,因为两个分支上的内容差不多,随着时间流逝,两个分支上的内容相差越来越多,这时候把一个变更集从一个分支复制到另一个分支,就会越困难,出现各种问题的可能性就越大,可能需要因此而调整合并的策略,引入更多的检查。
关于不同分支间合并,还要注意合并的频率,定期合并也不错,只要两次合并的间隔不要太久。
这里谈到的分支,可以是广义上的分支的不同具体形式,可以是狭义的分支,也可以是分布式版本控制工具中的不同的版本库,或者其他的方法。只要这些方法能够方便的做到不同(广义)分支之间的隔离和共享就可以。
甚至早在1.0版发布之前,就启动2.0版的开发,可以借助分支。
从老板开始决定开始,创建一个新分支1.x,在这条分支上开发,直到没有问题了,1.0版在这个分支上发布。
而在主干上,从那个位置开始研发2.0版对应的新功能了,这跟分支上1.0版的开发相互隔离,不会彼此干扰,另一方面,分支上的工作,包括少量新功能和大量的缺陷修复工作,对于2.0版的开发同样有用,所以,分支上提交的绝大部分的变更集,应该被复制到主干,这跟补丁版本的开发是差不多的道理。
应该在什么时候创建1.x分支呢?当开发人员要提交第一个仅针对2.0版而不适用于1.0版的变更集的时候,这时主干的断面可以作为1.x分支的起始版本。
在产生了1.0版本之后再创建1.x分支,被称作并行发布(Parallel Releases)。
当项目的里程碑有0.5版、0.8版,这两个重要的内部版本,为了能通过里程碑而进行的缺陷修复工作能并行起来,可以借助分支。
当集成时,预计需要比较长的时间时,可以考虑让集成一问题解决工作于开发人员的继续开发和提交并行起来,也可以借助分支。
如果每当集成遇到问题的时候,我们就开出分支,这样分支就会有点多,有改善的办法:用一条长期生长的分支而非很多个短分支来支持集成过程中的修改。并且,总是在该分支上发布新的基线,由于这个原因,该分支常被称作发布分支。
具体来说,开发人员提交代码改动到主干,每次集成时,集成工程师把主干上的最新内容合并或干脆复制到发布分支,在发布分支上制作正式的基线,供开发人员和测试人员在必要时使用,甚至发布给外部用户。
可以看出,在集成的过程中,主干一直是开放给开发人员的,随时提交任何修改,与本次集成互不干扰,这和使用多条短分支来支持集成的效果是一样的,却能避免频繁的开分支。
使用一个长分支代替多个短分支,可以多次集成不会打架。
这种一个分支和主干上期并行并且上面的内容彼此很接近的分支结构,称作双分支结构。
适用于以下的场景为例:
当软件研发团队,研发的某款软件,部署到服务器上,专供A公司使用,在某一时间只会使用软件的一个发布版本,而非多个,并且,软件发布通常是循序渐进的,每次增加一点新功能。这时可以使用双分支,当服务器上的程序暴露出比较严重的缺陷时,或因为A公司的业务调整需要紧急调整某个功能的算法时,需要紧急开发和发布一个补丁版本,这时,补丁版本的开发可以在发布分支上直接完成,并在发布分支上产生基线,向A公司内部发布,并部署到服务器,此后,把发布分支上为此次补丁版本所作的修改合并回主分支。
交迭(Overlap),本质上,前面说的都是分支,用分支来支持交迭,一条分支上,重点是质量,重点是稳定性,另一条分支上,是要增加新功能,是要全力发展,两条分支,既防止了后者干扰前者,也防止了前者阻滞后者。


用分支实现变体

变体(Variant),又译为变种,指一些软件产品,它们彼此有一些相同之处,但又彼此有所区别,就像一群兄弟姐妹,弟弟将来无论怎么长,也不会长成和哥哥现在的样子一模一样,比如一个软件的windows版和Linux版。
产生变体的原因:
因支持不同操作系统而产生变体。
因不同的功能集而产生变体。
因客户定制而产生变体。
可以用分支来支持变体,主干上的改动不断的同步到1.0-A分支上。当推出2.0版时,为了开发2.0-A版,有两种方法:把主干1.0版到2.0版的所有修改都复制到分支上,这时的分支应该叫A,以后的1.0-A版,2.0-A版等等;还一方法是,在2.0版或者2.0版之前的某个位置,创建一个新分支2.0-A,把分支1.0-A上为变体特殊需求所作的修改所对应的变更集都复制到2.0-A上。方法二优点是对分支合并引入的代码修改进行浏览和审查比较容易,缺点是如果会频繁的推出发布版本,分支就会创建很多。
使用分支来支持交迭,代码改动在分支间的主要流动方向是,从两边向中间流动,从分支流向主干。而当用分支支持变体时,代码改动在分支间的主要流动方向是,从中间向两边流动,从主干流向分支。这是分支支持交迭和变体时的重要区别。


用设置实现变体

在版本控制工具看起来是相同的源代码,构建工具却可以选取其中不同的部分来构建,于是就会产生不同的程序,互为变体。
很多应用程序在运行时从配置文件中读取设置信息,在windows操作系统中,可以把设置信息放到注册表里,这些信息也可能是加密的。
运行时的程序还可以通过探测运行环境,而改变自己的外在行为,比如一款手机,但它运行在某个运营商的网络中的时候,它显示出该运营商所要求的一些功能。
在安装和运行时读取设置信息,与构建时读取设置信息相比,最大的好处是减少了构建的数量。
在运行时读取设置信息,可能会影响到程序运行的性能。
构建时、安装时或运行时读取设置信息,实现变体。这类方法与用分支的方法相比,其好处主要是,不需要做代码合并工作。对于公共代码,在工作区中一次性的完成工作,即对所有变体都产生了效果。
从程序的外观和行为,从程序使用者的角度,讨论是不是变体,就好像是讨论究竟有多少头发算秃顶,多少根头发不算秃顶。
而从软件开发的角度,问题的关键不是什么才算变体,而是具体通过什么手段,来实现程序外观和功能的不同。
一般原则:尽可能晚的实现变体,这样做,开发成本比较小。


用组件的组合实现变体

在平台加应用的模式里,程序是若干模块的组合,其中有一个特别大,被称作平台,其他的模块,被称作应用。同样的,一个软件的变体,可以由不同的组件组成。
系统由组件组装而成,组装可以发生在软件从源代码到运行中的程序这一生成转化过程中的不同阶段。
我们从源代码的组装谈起。源文件在一起构成目录,目录在一起构成更大的目录,以此类推,直到系统整体。或者从软件结构上说,文件构成模块,模块构成组件,组件构成子系统,子系统构成整个系统。
对于大型系统,其所对应的源代码量很大,开发人员又很多,如果用一个版本库,一些版本控制工具的性能会成问题。如果出现了这样的趋势,解决方法之一,把源代码分成不同组件,放到多个版本库中。
即便是系统的不同的变体都使用了某个源代码组件,使用的内容也可以是不同的。也就是说,该源代码组件的不同版本,参与了系统的不同的变体的构成。
需要强调,这里所谈论的源代码组件,是从软件配置管理角度所划分的组件,划分关键是,一个组件是考虑软件复用时方便软件配置管理特别是版本控制的最小单位,如果从软件架构角度所说的若干个模块来看,它们永远是在一起,并且把它们作为整体来开分支、做基线就可以管理得很好,那就把它们当做一个源代码组件,而不是硬要分成多个组件。典型的例子是,在平台加应用这个模式中,平台尽管很大,但经常可以当作一个组件。
基线,狭义的说是集成的成果,具备一定质量的整体版本。当系统由组件组成的时候,系统的基线由各个组件的版本,常常是各个组件的基线组成的。因此我们把系统整体的基线称作复合基线(Composite Baseline)。
系统整体版本特别是复合基线的概念,并不总是那么重要,当系统的各个组成部分比较独立,当用户自己能够选择和更新各个组件时,整体版本的概念就不那么重要了。比如Android或者iPhone手机,用户关心的是手机操作系统的版本和各个应用程序的版本,而非它们的整体版本。
实现软件复用的需要:
一个适合复用的软件系统架构,组件内部,高度聚合,组件向外提供明确清晰的接口,组件之间,通过接口,相互配合。这里所说的组件,可不是一个类或者一个函数级别上的,一个系统,可能有成千上万个函数和类,这里说的组件,是粒度比较大的组件,可能是若干基础函数和类的集合、一个工具箱,供应给程序使用。使用面向对象语言编程,有利于实现组件化及组件复用,但这既不充分也不必要,面向对象设计和面向对象分析更为重要。
一个适合复用的研发过程,以产品为中心的软件研发过程,是不适合复用的,这样的软件研发过程,会集中精力于一个又一个产品本身,很难顾及到公共的部分,顾及到资产的复用。在研发过程中,要保持公共组件的常用版本的公共性。
一个适合复用的人员组织结构,在研发过程中,考虑对系统标准版本,以及对公共组件的常用版本的研发、单独立项,保证其具有一定的独立性,保证有足够的资源供应,这里的资源供应,主要指的是人力资源,应该有单独的项目组,来开发公共组件的常用版本。对于每个具体的应用软件系统,也应该单独立项,而在两者之间,应该有人进行总体规划工作和随后的协调工作。


支持多地点开发

对于跨过企业,可以利用时差,由不同国家的员工轮班倒着干。
不同地点开发,形成了某种隔阂,比如沟通问题,会倾向于自成体系,可能使得不同地点开发的内容接口不一致,无法集成在一起,也可能使得不同地点开发的内容,外观风格不一致,看起来像两个产品拼凑而成。除此之外,还有时差,不同文化。
如果一定要采取多地点开发,可以让每一个地点的团队或个人,负责相对独立的一块源代码或完成相对独立的工作任务。比如,以组件为单位,把不同的组件,分配给地理上不同地点的团队开发,而组件间的接口要清晰简单,并且应该尽早讨论、确定并记录,这样,有助于减少对不同地点间人员沟通的需求,也减少对环境和工具的要求与依赖。再次,要加强协调和配合,要有适当的人员进行总体的管理,进行各站点之间的沟通和协调,要有合适的流程保证各站点之间的同步。


从开源到外包

从获取资产的来源上分,除了开放源代码和免费产品这类外,还有其他厂商大量出售的标准软件,比如操作系统,一种是其他厂商专门生产的软件,常被称作外包。这些资产,称作第三方资产。
对第三方资产的管理,首先要适当的标示和记录他们。其次要存放好这些资产,并能方便的访问和使用。最后要管理外来资产的版本变更。
最好在本地存一份源代码,具体的说,就是导入到本公司的版本库里。
Svn自带一个脚本,可以方便的不断导入第三方源代码的新的版本。


管理软件部署

不论是对内还是对外,各类安装包应该有相对统一的存放地点。简单方法是使用一个共享目录,并设置了合适的读写权限。不仅要存储安装包的最新版本,还要适当存储历史上的版本。因为有时要退回到历史版本上,要把历史上的版本与最新版本进行比较。
安装也需要做计划,何时安装、安装哪些内容、怎么安装、有什么前提条件。应该考虑到如果安装出现问题,能否回退到安装前的状态,如何回退。应该考虑到先做一些实验性安装,没问题再正式安装。安装应该得到适当的批准,在具体安装前,应该仔细进行检查,检查版本、检查运行环境、检查相关关系的呢过。在安装时,要严格按照预定的步骤安装,并观察是否有异样。要记录整个安装的情况,以便将来回顾。在安装后,应该做一些粗略测试,以验证安装成功。
就像研发过程中的配置管理异样,对线上运行也需要把这些配置识别出来。除了当时的配置信息外,历史上的配置信息也同样需要考虑记录。
在系统运行过程中,可能会有来自各方面的变更请求,这些变更请求的一部分就是对软件研发的变更请求,但是,并非所有这些请求,都需要送到软件研发部门,有些变更请求,是对当前运行系统配置的变更请求,也就是说,是对运行哪些系统,包含哪些组件,使用哪些服务器等方面的变更请求,也包括对运行系统的一些设置、使用的一些数据的变更请求。这些请求,就像软件研发的变更请求一样,需要记录并跟踪,以防丢失。需要分析评估,考查它的成本,它的风险,它所带来的收益。在实施变更的前后,要通知相关受影响的人。
网站开发和管理的困难在于,有时候不好分辨,哪些算是软件研发的输出,哪些算是运行时的配置和设置,哪些算是系统运行行为本身。因为不好分辨,所以更要明确责任。要明确,哪些内容由谁来负责,如何修改。而它的前提是,网站有比较好的系统架构,并且有比较好的工具支持,能够把脚本程序的变化、页面编辑产生的变化和运行时的变化,三者分离开来。因此,网站要有比较好的系统架构,并且有比较好的工具支持,其中的工具主要是指网站内容管理系统(CMS)。


软件配置管理实施

不同阶段,不同挑战:
第一阶段,一个软件开发组织初创之时,这时候的当务之急是,建立起软件配置管理的基本解决方案,其中最重要的是,引入源代码版本控制工具,把源代码管理好,防止源代码丢失、版本覆盖、版本混乱等各种问题,有了源代码版本控制工具,开发就可以比较顺利的进行了,随后的要紧事,是建立起基本的缺陷跟踪系统,其主要目的是让测试团队和开发团队能够有效的合作。
第二阶段,软件开发团队的规模不断增长之时,这通常伴随着源代码量的迅速增加,编译构建所需时间的不断延长等,这一系列的变化给集成(广义和狭义)带来了越来越大的压力,在这个阶段,我们的关注重点是围绕着集成的优化,比如,如何在狭义集成前、集成中、集成后合理的分配质量保证工作?如果让构建更快?如何让测试更快?能不能让狭义集成过程完全自动化?如何实现持续集成?等等。
第三阶段,发布多个版本、多个项目、多个产品之时,此时的主要挑战是软件配置管理对软件复用的支持。实现软件复用有多种模式、多种方法。注意选取适当的模式,并注意不同模式同时使用时,如何相互配合。这些模式中,以组件的组合对软件配置管理的挑战最大。另一方面,当版本、项目、产品的数量很多时,数量本身也带来挑战。比如说,三五年前的某个项目,你知道它的源代码就在公司的某个版本库的某个目录下,但是到底是哪个版本库哪个目录呢?
以上三个阶段的划分,只是常见、典型的情况。并且阶段与阶段之间,也并没有非黑即白的明确的界限。请以此为参考,根据你所在的研发组织的实际情况,确定当前的工作重点。


如何完成一项改进

不论是引入一个版本控制工具,还是改变提交源代码修改的步骤,抑或是调整关于内部版本命名的规则,在本质上,都是对现有的软件配置管理解决方案进行一项改进。这一项改进可能是关于软件配置管理工具的,或软件配置管理相关流程的,或两者都有。不论完成一项什么样的改进,都有一些通用的步骤和要点。
在改进方案调研和选型时,要对所在研发组织的实际需求有真切的了解。比如,现在需待解决的问题是什么,对某项指标有多高的需求。举例来说,某个工具号称能支持2000人同时使用,而你所在的研发组织,现在只有20人,未来三年的目标是发展到100人,那么这个工具的这个高指标对你所在的研发组织并无意义。工具软件厂商和服务咨询的提供方可能会夸大你的需求,暗示你有某方面的需求,以此来引诱你花大价钱购买其实你并不真正需要的工具或服务。
用免费的工具还是收费的工具?传统上认为,收费工具通常质量更好,出了问题能得到及时的修复,关于工具如何使用,也有工具厂商能够提供专业的解答。然而,相应的开源免费工具,如果足够流行,被成千上万的软件研发组织使用,那么它的质量通常已经相当好。并且,有些新兴的开源工具与一些有年头的收费工具相比,明显具有更好的架构,因此有更好的性能,也更容易维护和使用。在今天,开源免费的工具,有可能是一个更适合你所在的研发组织的选择。
某个改进,特别是流程上的改进,在研发组织作为整体因此而受益的同时,可能也有一些部门、一些团队、一些个人没有因此得到好处,甚至受到损害,比如工作步骤变得比以前繁琐。他们可能会成为变革的阻力。如何解决?方法之一是,识别出这个改进的主要受益方,与相对应的管理者沟通,请求他的帮助。他经常有很大的热情,从管理者的角度去协调和推动这项变革发生。
从改进方案的讨论阶段开始,就要注意保持与利益相关方(Stakeholders)的沟通。确定改进方案确实是他们想要的,尽量满足不同方面的需求。在确定方案后,如果实施改进所需的时间较长,那么应该适时汇报阶段性的成果。
尽可能把你心中的宏图伟业,落实为一个个小的改进项目或阶段。每一个都有明确的产出,对研发组织有实质性的贡献。小的改进与大的改进相比,风险更小、实现较快、可根据反馈及时调整,比较容易得到批准、付诸实施。并且,通过一个个成功的改进,不断累积你的信用,日后打算进行一些革命性的改变时,会更容易获得支持。
一项改进本身的质量保证工作该怎么做?除了改进需求评审、方案设计评审、代码评审、在测试环境测试等方法外,试点(Pilot)也是一种=广泛使用的方法。试点是在真实的环境中小范围的试用新的方法。这样,出了问题负面影响也不至于很大。同时,由于是在真实的环境中试用,如果没什么问题,那么就可以比较放心的推广。
要成功实施一项改进,培训、支持、文档也很重要。通过培训等方法,让具体的使用者充分了解为什么要改变,改变到具体什么样的流程和操作方法。当使用者遇到问题时,要提供方便的途径,让他们的问题得到解答或解决。培训和支持都是向使用者提供的服务。如果能够让使用者在很多时候自己帮助自己,那就更好了。如何做到呢?如果有合适的相关文档,文档具有合适的结构和合适的内容,易于使用者阅读、便于使用者查找,那么就能够在相当程度上减少支持使用者所需的人力。


在一个项目的生命周期中

制定计划:凡事预则立,不预则废。制定计划,意味着考虑在这个产品的开发过程中,软件配置管理要怎么做,这包括软件配置管理的方方面面。
通常上会遵循和使用该企业已有的软件配置管理解决方案,但需要仔细研究具体项目的特殊之处,比如多久一次导入、如何送回公共改动等一系列问题,还有团队是否分布在不同的地理位置,不同的产品之间是否存在复用,等等,这些是这个项目中的软件配置管理的特定场景(Scenario)。
对项目的软件配置管理进行计划,并不意味着一定要写一份名叫软件配置管理计划(SCM Plan)的厚厚的文档。作为计划的成果,有些内容可能写在了某个wiki页里,另一些内容填在某个表格里,甚至有些内容干脆就是写在一封电子邮件里告诉大家。
做好准备
要做哪些准备工作,深受组织级软件配置管理工作的影响。
如果公司已经提供了可用、适用的软件配置管理工具,如版本控制工具等,则只需简单的为这个产品进行初始化工作。比如,在其中创建项目、创建目录、导入初始版本、设置合适的参数,等等。如果组织级并未提供合适的工具,则需考虑工具的选择、购买、安装、设置等一系列事宜。
如果公司已经确立了通用的软件配置管理过程,则应该考虑拿来使用。这可能是全盘接受,也可能是在此基础上,根据项目的实际情况,如开发团队规模等因素,进行适当的裁剪和定制。而如果当前项目情况非常特殊,则可能需要部分或全部的为项目特别制定软件配置管理过程。当组织级没有确立或没有完全确立通用的软件配置管理过程时,也会有这样的情况。一般来说,在做软件配置管理计划时,应该同时完成过程方面的准备,或者已经完成对这方面的重要决定。
而在人这一方面,要保证各个软件配置管理相关岗位,已经有合适的人选,并具备了在该项目中完成配置管理方面的工作的能力。他们应该有足够多的经验和能力,如果欠缺,应该考虑进行相关培训。
日常工作
软件配置管理系统日常工作,牵扯到项目团队所有成员,因为所有成员都需要与软件资产打交道,也就需要与软件配置管理打交道。从这个角度讲,不同的角色,所有的团队成员,都是软件配置管理系统的一部分。
而软件配置管理工程司主要的职责是保证软件配置管理系统的正常运行。比如,当工具需要某些维护工作和手动备份工作时,需要做一些相应的工具方面的维护和备份工作:当人员有增减的时候,需要开通和管理相关权限;当使用者遇到的各种麻烦需要解决时,需要回答工具和流程方面的疑难问题,这被称为Trouble Shooting。另外,还需要为一些软件配置管理的具体事宜、具体案例给出意见或作出决定,比如,具体的某个开发任务,是开分支来支持比较好,还是只使用主干来接受相关变更集的提交好。
当然,在一些研发组织中,软件配置管理工程师同时兼任集成工程师,也承担集成工程师的职责。
监控、调整与改进
软件配置管理系统的运行,既需要参与者的深刻理解和自觉执行,也需要某种形式的监控。这首先是因为,每个团队成员都有其关注的焦点,比如开发人员集中精力与编写代码,测试人员集中精力于发现程序中的问题,项目经理集中精力于项目的按时完工,并让客户满意。而遵循软件配置管理规定,并不是他们关注的焦点。其次还因为,每个人都有失误的时候,都有犯错的时候,如果这些不被及时指出和纠正,就会被效仿。而监控的目的就在于,及时发现问题,及时发现没有遵守纪律的问题,并敦促改正。
但是,即使团队成员严格遵守项目中软件配置管理的各项规定,让软件配置管理系统严格按照规定运行,也仍然有可能出问题。因为,随着项目的演进,项目所在的环境,项目对软件配置管理的要求,都在不断变化。比如,变更请求管理越是到项目后期越是严格。因此,项目的软件配置管理策略、方法,需要随着项目的进展进行调整。这是第一类调整。
而有些调整是因为另外的原因,是因为在定制计划时,不能准确的估计到项目对软件配置管理的需求:不能准确的估计到在这个项目中,各项软件配置管理工作应该怎么做,应该做到什么程度。比如,在项目之初,可能认为在这个项目中为试探性的工作开分支没有必要的,因为预计没有比较大的试探性工作。但是项目实际运行中,确实遇到了比较大的试探性工作。这时候就需要进行调整。这是第二类调整。
随着对软件配置管理的认识不断提高,会对流程进行调整:随着新的软件配置管理工具的选型、购买、安装设置的完成,会对项目所用工具进行调整。这类以提升为主要特征的调整,通常被称为改进。改进往往具有组织级的意义,最终是在全公司实施。
收尾
在产品发布、项目收尾阶段,软件配置管理同样需要进行收尾工作。这主要包括两个方面,软件资产的整理和归档工作、软件配置管理本身的总结和共享工作。
软件资产的保护,在项目收尾时进入关键时刻。这个时候保存的软件资产,是已成型的软件资产,是最有价值的资产。同时,这个时候的软件资产,是上市软件产品对应的软件资产。这个断面,在将来很有可能被用来作为维护和继续开发的基础。而另一方面,这个时候的软件资产,如果不及时进行整理和归档工作,又容易被渐渐遗忘,最终丢失。随着硬件设施的迁移,随着其他的变迁,先是很难找到它到哪里去了,进而被从物理介质上清除,再也无从恢复。
软件资产的整理和归档,包括对源代码、对安装包、对文档的妥善保存;包括对各个历史版本,特别是发布产品对应的历史版本的妥善保存。这可能通过某种备份来完成;也可能是转移存储地点,从活跃的经常被存取的存储地点,转移到不活跃但更为安全的存储地点。
而对构建方法的整理和归档,对于环境的整理和归档,也同样重要。否则,在将来,有可能即使复现了当时的源代码,却不能生成对应的安装包;于是源代码资产也失去了价值。
对变更请求等相关数据也应该进行整理和归档,保证将来仍可查阅。
这些是对软件资产的整理和归档工作,而对软件配置管理本身,同样存在着整理总结的工作。因为,软件配置管理本身也是一种资产,被称作过程资产,这也是企业的重要资产。
在项目即将结束时,是一个很好的机会,对整个项目过程中的软件配置管理工作进行总结。其中的经验和教训,值得日后其他项目参考。在日后其他项目的起始阶段,制定软件配置管理工作计划时,就要考虑以往的经验和教训。
在整个项目过程中,可能对软件配置管理流程进行了调整和改进。对这些要进行分析,看是否有可能加入到组织一级的软件配置管理流程中,从而使日后其他项目受益。在工具方面,如果引入了新的软件配置管理工具,或对已有工具进行了定制或二次开发,也要考虑,这些成果能否上升为组织一级,供日后其他项目使用。


平衡集权与自治

集权与自治是个古老的话题。对集权的追捧大有人在,而对自治的支持,也毫不逊色。说点公道话,其实集权有集权的好,自治有自治的好,不可以一味强调其中一端,不可偏废。古希腊的城邦政体固然好,自由、民主、独立,然后缺乏城邦之间的统一领导,邦分崩离析而不能守,最终灭亡。而柏拉图的理想国,终归只是理想国。近现代,对高度集权的经济体制的尝试,也终归只是尝试。
对于企业运作,对于软件研发,也是同样的道理。企业,特别是高新科技企业,越来越意识到,完全的从上至下的科层体制和命令式管理是行不通的,因为基层才更了解实际情况,更知道具体问题该如何处理,更富于创造性。当然,一盘散沙式的管理也同样行不通,这会带来大量的重复劳动,恶性的内部竞争,甚至是工作目标本身的分散。
具体到软件配置管理,也是一样。让每个产品开发团队都独自搭建一套版本控制系统,独自购买、安装、设置和备份,听起来不合理。同样,如果让企业内所有的产品研发,不论是一个人两周完成的内部工具的研发,还是一千人两年完成的大型项目的研发,都遵循同样的软件配置管理过程,这听起来问题更大。
为什么要集权?对于软件配置管理来讲,最重要的原因有两点。首先,集权通过共享而节约了资源,节约了劳动,说白了就是省钱。就像刚才举的例子,版本控制系统的搭建和维护,是一件有一定工作量的事情,是一件有一定技术含量的事情。在公司一级统一做,只花了一分钱,只雇请了一个相应的人才。而如果几十个产品,各个都要自己搞,那就要花更多的钱,并且雇请更多的人。
其次,车同辙,书同文,有利于沟通和交流,也方便资源的重新配置。比如,如果因为公司业务需要,一个开发人员从一个产品开发团队调到另一个产品开发团队,结果他发现,本来比较相似的产品,比较相似的产品研发,却使用了截然不同的软件配置管理工具,使用了截然不同的软件配置管理流程。于是,他不得不花大量的精力,来学习和适应。相反,如果这两个产品的研发,使用了相同或相似的软件配置管理工具和流程,这个开发人员就能把更多的精力放在软件开发本身上了。
然后,集权和统一并不是绝对的。各个产品的研发,有它特定的背景,因为有队软件配置管理的不同程度的要求或不同方面的要求。就好像人人都要穿鞋,这是一致的,然而,各有各的尺码,不可强求,不可削足适履。至于具体如何组织和运作,要根据具体情况掌握。
以工具为例,一般来说,一个企业的软件配置管理工具,应该统一购买、统一安装、统一设置、统一备份、统一维护和升级。总之,统一管理。这样能够降低成本,也减少企业为管理所牵扯的精力。当使用的是开源的工具或免费的工具时,虽然没有购买的问题,但仍有统一取得、统一安装等问题,仍然应该统一管理。着同样是出于成本考虑。
有的时候,必须对取得的工具加以改造,以适应本企业的需要。这可能是通过在工具之上进行某种封装来完成,也可能在源代码级进行修改,甚至是完全自己写一个工具。这些也尽量在公司一级统一来完成,不要每个产品研发项目都尝试单搞一套。
另一方面,不同类型的、不同背景的研发项目,对工具可能会有不同的要求。为此,可以考虑通过对工具的设置来完成,通过对工具的不同使用方法来完成。比如,有的项目使用分支,以引入多层集成,有的项目则不需要。
如果需求差距比较远,也可以考虑使用不同的工具,比如,二三十人的小项目,而且所有人员都坐在一起开发,用svn就不错,但上千人的大项目,分布在多个研发站点的大项目,就应该考虑使用git这样的工具。即便如此,仍应该尽量减少工具的品种,比如,仅使用两种版本控制工具,一种用于内部工具开发项目,一种用于产品项目。
流程方面也是类似的道理。几乎可以肯定的是,各产品的研发,不应该采用完全不同的软件配置管理流程和规范。同样,几乎可以肯定的是,各产品的研发不应该采用完全相同的软件配置管理流程和规范。那么,中庸之道在哪里?
如果几个产品的研发,其背景基本相同,对软件配置管理的需求基本相同,那么它们应该遵循相似或相同的流程和规范。从这一点出发进行考虑,应该在企业级建立标准的软件配置管理流程和规范。
对于具体产品的研发,可能需要对标准流程和规范做一些更改:可能是更细化其中的一些内容,可能是加强其中的一些内容,也可能是有所删减。这些更改,统称为流程的剪裁(Tailor)。比如,如果只有一个产品,使用了开源项目的成果,作为一个静态链接库,那么,如何管理这个静态链接库的版本等相关的方法、规范和流程,就应该写在这个产品研发本身的软件配置管理计划文档或者这个产品研发本身的流程文档里。而如果有越来越多的产品,或者预计有越来越多的产品会使用这个第三方的静态链接库,那就应该把这个静态链接库的管理,放到标准流程的规范中。
如果某个产品的研发特点,与标准流程的适用范围非常不同,那么,裁剪可能就不再是一个有效的方法。与其把一件大人衣服改成一件洋娃娃穿的衣服,还不如为洋娃娃单做一件衣服。
对这种情况,适宜为这个产品本身做一套流程规范,并且考虑相关工具的配合。而如果在将来要研发若干相似的产品,这套流程规范适用于或基本适用于一系列产品的研发,那么,就把这套流程规范上升为企业的标准流程规范。也就是说,这时,企业里有不止一套标准流程规范。各产品,根据自己的情况,选择相应的流程规范,并考虑进行少量裁剪。


管理众多的项目

当公司的产品、组件比较多了以后,管理起来,会遇到一些新的挑战。比如,存储目录结构方面的挑战:公司可能拥有多台专用服务器,每台服务器上有多个版本库,而每一个版本库里,拥有多个产品或组件的源代码。因此需要为此进行规划:设置合理的层次,进行适当的分组,并以此确定各产品、组件的存储位置。记录并遵循这样的规划。如果这样的规划需要调整,就要重新评估,重新设计方案、讨论和批准。
不仅是源代码存储有存储结构规划的问题,对文档的存储、对安装包的存储、对静态链接库的存储,也有类似的问题。
不仅是存储和版本控制中存在着这样的问题,变更管理,特别是变更请求管理系统中,也有类似的问题。例如,如果一个缺陷跟踪系统里,拥有数十个甚至数百个产品或组件,那么每次填写缺陷记录或查找缺陷记录时,都需要先在系统中,从这数十个甚至数百个产品或组件中,引入某种层次关系,就会大大的提高效率。而对于某个特定的团队或特定的人,一般只关心其中少数几个产品或组件,如果为此设置这几个产品或组件的某种快捷方式,会进一步提高工作效率。
要注意,同一资产,其命名应该统一。一个源代码组件,有一个固定的名称。在版本库中,这个名称反映为存储目录名:在基线和分支中,如果需要组件的名称,那么也用这个名称;在变更请求管理工具里,也要用这个名称;生成的运行组件,还是要用这个名称。除了名称外,版本号也要对应和统一,这个我们以前也提过。


软件配置管理团队的组织结构

一般来说,研发软件的企业,只要企业不是太小,都会有软件配置管理团队,再不济,也会有一两名软件配置管理人员。他们的职责是什么?
他们要负责对软件配置管理工具和环境的设置和维护。这包括工具的选型、工具的购买或取得、工具的安装、工具的设置、工具的定制和二次开发、工具的升级、工具的数据备份、工具的权限管理、工具的性能调优等。总之,是围绕软件配置管理工具的管理工作。
除了操作和管理工具外,他们还要负责与工具相关的培训。教会每个工程师如何使用这些工具。而当大家在使用过程中遇到问题的时候,也会去请教他们,让他们帮忙解决。
在企业级,设定专人来负责这些事情,比每个项目自己管理要好。软件配置管理工具,特别是大型商用的软件配置管理工具,管理和维护起来,可不是那么容易的。术业有专攻,还是让专人来负责整个企业这方面的事情比较好。
除了工具需要管理,软件配置管理的流程、规范和方法也需要管理。这包括制定流程规范,也包括监督执行,还包括不断的调整和改进。请注意,这里所说的流程规范,包括标准的流程规范,也包括裁剪,还包括个别特定的规范。这些事情,谁来做呢?
通常,公司一级的软件配置管理人员,应该发挥重要作用,因为它更专业,更能照顾全局。而在具体项目中,项目中的配置管理人员也应该发挥作用,因为项目成员更了解本项目的实际情况。一般的标准流程规范,应该由公司一级的软件配置管理人员负责起草、发布并持续改进,并征询各方意见。而具体项目中对标准流程规范的裁剪,公司一级的软件配置管理人员可以只是参与。
企业的软件配置管理人员,应该对员工进行软件配置管理方面的流程培训,仅有工具培训是不够的。要教会每个工程师,如何在这些流程下规范的工作。而当大家在工作过程中遇到问题的时候,也要去请教软件配置管理人员。
对流程和规范的监督执行,也就是常说的流程审计,可以由软件配置管理人员进行,也可以由质量保证部门进行。而在各个项目研发团队内部,可能还有自查。
与公司级的软件配置管理人员相对应的,是项目或产品一级的软甲配置管理人员。他们负责项目或产品整个生命周期中的软件配置管理,从制定软件配置管理计划开始。他们还可能会负责产品之间的协调工作,当然这也可能是由企业级的软件配置管理人员完成的。
事实上,项目或产品一级的软件配置管人员,也有可能在行政上归属于企业级的软件配置管理团队。或者,项目及的软件配置管理人员与企业级的软件配置管理人员,仅仅是角色的划分,实际上是同一个人。
集成工程师,包括组建级的集成工程师和系统级的集成工程师,他们的主要职责是集成,以及与集成相关的一些操作。他们可能由软件配置管理人员兼任。
然后,配置管理人员绝不要把集成、发布等工作当作自己职责的全部。配置管理人员最基本的任务,是建立、维护、调整和改进配置管理解决方案,包括流程、工具、人,保证配置管理系统的运行和不断调优。其中非常重要的一点是,设置正确的、符合企业特定环境特定需求的配置管理策略。让我们为此共同努力!

  • 1
    点赞
  • 3
    收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值