目录
软件配置管理(SCM)是“系统化地定义软件项目工作和处理变化,以使项目保持其完整性”的实践活动。SCM关注于程序的需求、源码、文档和测试数据等所有项目相关的产物。配置管理策略将决定如何管理项目中发生的一切变化。因此,它记录了你的系统以及应用程序的演进过程。另外,它也是对团队成员协作方式的管理。
SCM的主要任务有两个:第一,变更控制;第二,版本控制。以上两点只是对SCM的基本概括,想要做好SCM不仅需要完善的流程也需要强大的软件工具支持。
唯一不变的就是变化本身,接受变更是不争的实事。软件产品易于掌握的特性和不可见性,往往导致它的构建人员面临着永恒的变更。因此必须制定相应的变更管理计划,防止变更失控。
执导原则:
一般程序:
必须清醒的认识到——没有不变的需求。变更控制只是被动地应对到来的变更,此外,我们还可以主动迎击变更。做法就是将不稳定的区域隔离出来,从而把变化带来的影响限制在一个层、类或者组件的内部。下面给出相应措施:
1 找出看起来容易变化的范围。需求中应该包含这份潜在变化的清单,下面是一些容易变化的区域:
2 把容易变化的项目分离出来。
3 把看起来容易变化的项目隔离起来。
(这绝不是超前设计,而是利用分层、设计模式来达到牺牲少许性能来降低耦合度,提高灵活性的方法。)
版本控制系统是保存文件多个版本的一种机制。版本控制软件可以帮助你得到以下益处:
(一) 版本控制的内容
版本控制的目标是能够随时获取软件在整个生命周期中任意时间点的文件状态。因此,任何与项目相关的文件都应该进行版本控制。以下内容应该进行版本控制:
以上内容都应该纳入到版本控制行列,但根据项目规模可以有所裁剪,但以上加粗的内容必须进行版本控制。而有些内容不纳入版本控制,这些内容是:
(二) 版本控制策略
1 推迟了新功能的整合,对分支进行合并存在发生集成问题的风险。
2 多个分支难以管理,并会增长集成的风险。
3 很难避免重名问题。
4 代码整合将会随着分支数量的上升,变得越来越困难。
备份计划指的是定期备份工作的成果。你的备份计划应该包括定期进行备份,并且定期地将备份介质转移到脱机存储介质中。
在制定备份计划的时候,人们常常忽略的一点是:要测试你的备份过程。应该对数据恢复进行演练,以确认备份数据中包含了所需要的全部数据,并且可以成功恢复。
必须由专人负责,做到责任到人并且明确定义需要备份的内容以及备份的周期。负责人往往具有版本控制软件最高的权限,可以查阅所有文档,而且其维护的是企业的重要组织过程资产,责任重大,应该谨慎选择。
(一) 介绍
SVN是一款非常知名的中央版本控制系统。(与中央版本控制系统对应的是分布式版本控制系统,如DVCS。分布式版本控制系统支持大型开源团队的需要,一般项目使用中央版本控制系统足以。)版本控制系统用于维护应用程序每次修改的完整历史,包括源代码、文档、数据、脚本等等。它的另一个重要用途,让团队一起工作在应用程序的不同部分,同时维护系统记录,即应用程序的权威代码基。SVN由商业组织Collabnet维护,它提供收费支持。
SVN中,版本控制的单元是修订(revision),它由多个目录内文件的一组变更构成。可以把每个修订看成当时版本库中所有文件的一个快照。在SVN中每次提交都会应用所有更改,这一过程是原子性的,并且创建一个新的修订版本。SVN版本号是针对整个代码库的,而不是每个文件对应一个版本号。SVN用对待文件的方式对待目录、文件属性和元数据。
每个SVN版本库在创建时,可以选择生成3个默认目录:trunk(主干)、tags(标签)和branches(分支)。当创建分支(标签)时,只是在branches(tags)目录下创建一个新目录,并将trunk上你想创建分支(标签)的那个修订版本的内容复制到该目录中。刚刚创建的分支(标签)和trunk指向同一组对象级,直到它与主干开始不一致为止。SVN不区分标签与分支,它们只是用途不同而已。
SVN的一些限制或者说是需要注意的地方:
(二) VisualSVN-Server(服务端)
1 安装
第一步:
第二步:
2 使用
主界面如下:
第一步:创建版本库
第二步:创建用户
第三步:创建分组
第四步:配置权限
(三) SVN(客户端)
1 安装SVN
安装过程唯一需要注意的是,在安装完成中文语言包后,要在SVN中设置使用语言,否则还是会按英文显示。
第一步:点击“Settings”。
第二步:设置使用语言。
2 SVN的使用
SVN的定义的图标及其含义如下:
无版本控制。
正常状态。
表示本地文件与版本库不同步。
本地文件与版本库存在冲突。
表示只读文件(被他人加锁的文件)。
表示该文件已加锁。
表示当前文件夹下有文件或文件夹从版本库中删除或者丢失了。
表示有文件或目录被添加到了版本库中。
第一步:新建一个存放版本库的目录。
第二步:点击目录,右键弹出菜单选择“SVN检出”。
第三步:输入URL。
第四步:输入用户名及密码。
获取最新版本 在右键菜单中点击“SVN更新”。
获取特定版本 在右键菜单中点击“更新至版本”。
第一步:新增文件。新增文档会显示图标,表示无版本控制。在该文件上右键选择菜单选择“增加”,以声明对该文件进行版本控制。
第二步:声明对其应用版本控制。添加之后,图标会变为,此时文件只是存在于本地,只有“签入”后才会上传到版本库中。
第三步:“签入”修改。
处在版本控制下的文件,不能在本地删除,需要从版本库中删除才能彻底删除文件。
第一步:选中目录或文件,在右键菜单中选择“删除”:
第二步:“签入”修改。
选中目录或文件,在右键菜单中选择“”,会出现提交对话框,按需填写相应信息,并选择需要签入的文件:
点击“确定”开始签入文件,签入成功后会返回本次操作的结果:
第一步:右键菜单选择“改名”。
第二步:输入新名称。
第三步:“签入”修改。
第一步:选中目录,点击右键菜单中的“分支/标记”。
第二步:输入分支保存路径以及日志信息。
第三步:获取最新版本。如果不获取最新版本,在目标位置是找不到分支目录的。
第一步:在相关目录下的空白处(即合并起始位置的URL,可以从分支合并到主干,也可以从主干合并到分支),点击右键菜单中的“合并”。
第二步:选择合并类型。
第三步:合并。
第四步:如果存在冲突请解决冲突。(这里不做详细解释,下文会详细解释冲突产生过程及如果解决。)
输入正确的服务地址,用户名密码即可。
3 版本冲突
以下流程模拟了一个版本冲突的产生。
用户B在签入时会失败。
前两种做法比较极端,且在回避问题,以下说明第三种做法的步骤。
第一步:用户B获取最新版本。获取后,会发现冲突文件被会显示。
第二步:选中冲突文件,点击右键菜单中的“编辑冲突”。
第三步:将修改后的文件标记为已解决。
第四步:用户B“签入”文件。
我在“三 版本控制”中阐述版本控制的基础知识,其中主要包括的版本控制的内容与策略。为了能将理论联系实际,以下给出了一些比较好的实践,以供参考。
(一) 工作之前先更新
应该频繁地更新工作有关的文件,频繁获取最新版本,这对一个团队活动来说十分有益。因为当你在发现返回结果莫名其妙的时候,可能你的队友已经提交了对某个缺陷的修改。很多开发人员都知道新的版本一般会包含更少的缺陷,但仍有两方面,在困扰这开发人员去频繁获取最新版本:
第一,队友在肆意破坏构建。可能你更新一次,就会因为别人引人的某个缺陷而无法继续工作。
第二,不稳定的网络。更新时间很长,长到难以忍受。
可能最多的情况还是因为第一点。对于这种情况,如果这种肆意破坏构建的现象已经普遍了,那认命吧,脱机使用可能更好一些。
(二) 构建失败了不要提交新代码
正确的步骤是在提交修改之前,应该先获取相关文件的最新版本,然后重新编译工程。待本地测试并通过代码审查(如果有)后,再提交新代码。如果构建失败了,你应该修复代码,而不是把问题扩散到版本库中。我曾目睹过可笑的事情:一位开发人员,把编译不通过的代码签入服务器的原因竟然是想让别人帮他看看是哪里写错了。不要让这种闹剧在你的团队中上演,如果你的某位成员经常性地破坏构建,那么你应该果断地收回权限,以维持版本库正常的构建,减少不必要的修复时间。
(三) 提交有受测的或已审查的代码
版本控制要求成员提交可靠代码。测试和代码审查均是代码质量保障的有效手段。代码审查的软件质量控制最有力的手段,其缺陷检出率也是最高的,但也将消耗掉相当大的成本。并不是所有团队都能做好代码审查,代码审查需要技术硬手,要有一定的重构经验。事实是,很多小项目没有配置相应代码审查人员,或因团队能力有限而放弃代码审查步骤。导致缺陷在项目中蔓延,代码的味道越来越坏。代码审查与测试的重要性,并不是本文讨论的重点。我要说明的是,我们进行配置管理的对象是可靠的代码,可靠的代码不等于编译通过即可,它至少意味着更少量的缺陷。所以,即使你的项目团队没有配置代码审查,没有人写单元测试,最起码地请保证在警告数量为0后签入代码,因为IDE的作者们比你更了解语言。
(四) 提交后测试主版本是否可以工作,成功后再干别的
这是很多团队都在采用的方法。道理很简单,你的代码没问题了你才可以下班。很多团队都是在快下班时,要求成员提交代码。实践证明并不理想,因为经常会发生一件最最痛苦的事情——下班了,活儿来了。我更倾向于在下午3:00发布系统。第一,每位成员都清楚程序发布的时间,在早晨他们就会处理手上的代码(为了按时回家),一般在上午就能完成调试和测试工作,很多事情没有必要非拖到下班来干。第二,因为下午2:00~3:00,人会犯困,在开发人员等待测试人员的反馈时,他们可以休息一下,毕竟发布前的准备可能已导致了数日的赶工。第三,也是最重要的一点,一旦构建出现问题,我有足够的时间处理缺陷,并能确保当天测试团队能拿到一个可测试的版本。
(五) 签入代码时最好进行一次代码走查并确保签入了所有相关代码
在签入代码时进行一次差异比较是一种好的实践,成员可以最后一次查看自己的代码,进一步降低缺陷别引入的几率。切忌不要仅仅签入部分代码,这样做很可破坏构建。你自己可能没有察觉,因为本地构建是正常的,可是,其他人却因为缺少某个文件而无法通过编译。
(六) 时刻准备着回滚到候选版本
应该维护好我们的版本信息,清楚当前回滚的最佳选择。
(七) 在回滚之前规定一个修复时间
建立一个团队规则:如果因某次提交而导致构建失败,必须在某个时间之内修复它,如果无法修复,则回滚到之前的最好版本。
(八) 责任到人
将其与绩效考核紧密联系,让守规矩的成员得到褒奖,并让肆意破坏构建,违反团队规则的人,为他的行为负责。
(九) 乐观锁往往更高效
SVN默认使用乐观锁(不会以独占方式打开文件,他人也可以修改该文件),但同时支持悲观锁(独占文件方式)。两者的选取主要由成员的分工,系统架构的耦合程度来决定。如果,某些文件很少被公用,对于这些文件则使用悲观锁比较有利于解决合并冲突。相对的,如果团队成员可能会同时工作在同一个文件上,例如:所有成员均需要编辑DAL层某个类的代码,那么这个文件就需要使用乐观锁。事实上,越是大项目,人员越多,系统解耦越不彻底,越适合使用乐观锁。对于某个文档的修改时,可能是你使用悲观锁的少有的情况。
我在上文提到过,应该尽量避免创建分支,而是使用增量式的开发。每次创建分支,都要认识带它带来的成本。这种成本在于“增加了风险”,而唯一最小化风险的方法就是无论由于什么样的理由创建了分支,都要努力保证任何活跃分支合并到主干。
在开发过程中,通过频繁向主干提交的方式做增量式修改几乎总是最正确的做法,主干开发也是集成成本最低的模式。在主干开发中,开发人员几乎总是签入代码到主干,而使用分支的情况很少。主干开发有以下优点:
主干开发并不排除分支。它意味着——所有的开发活动在某一时间点上都会以单一代码基线而告终。主干开发的一个可预测结果是:每次向主干签入并不都是可发布状态。任何人对主干的修改都可能破坏构建。因此,在使用主干开发的团队中,应该进行持续的过程改进以缩短修复构建的时间,保证主干在大多数时间处于可工作的状态。
推荐使用分支的情况包括:
下面介绍常见的分支模式。
(一) 为发布创建分支
在某个版本即将发布之前,为该版本创建分支,该版本的测试和验证全部在该分支上进行,而最新的开发工作仍旧在主干上进行。在这种模式中,要遵循如下规则:
(二) 按功能模块分支
使明确分工的团队,在各自负责的模块上工作,在并行开发的同时,保持主干的可发布状态。使用该模式要做到以下环节:
使用这种模式太容易“将确保应用程序处于可发布状态所需要解决的痛苦”推迟到后期。应该做成分的估计,确保采用这种模式所取得的收益远比其开销更重要,而且要确保在按进度发布系统。
该模式分支形如:
(三) 按团队分支
该模式分支形如:
按团队分支的流程如下:
非常重要的是,每个分支都要有一个责任人,一般是TeamLeader,由他负责定义和维护该分支的规则,包括管理谁可以向分支提交代码。
这种分支模式与按功能模块相比,优点是分支较少,而缺点是各分支很快会变得差异很大。主要风险是,在进度压力下,团队不能充分遵守关于合并回主干以及从主干更新代码的规则。团队分支很快会和主干变得不一样,彼此之间的差异也会很大,所以,合并会很耗时。
现实的项目中,需求变更以及在配置管理中使用分支几乎无法避免。好的SCM可以有效地使变更处于受控状态,降低合并冲突,保证主干代码尽可能处于可发布状态。但是,项目规模做大,管理力度失衡,就会发生种种失控的状态。变更控制会失效,成员深陷于痛苦的“变更>修改>发布>变更>修改>发布”的死循环中。分支之间相互嵌套,团队规范形如废纸。版本库形成非常复杂的网络已经无法维护。伴随着分支的积增,资源的分配也更加细碎,成员之间会彼此抱怨别人的代码破坏了构建。需求无法冻结,导致长期的赶工,资源开始流失。这种情况,很可能在我们的身边上演。不要寄希望于SCM能完全防御掉这些风险。SCM只是我们促成项目成功的方式之一。
我的建议是,在合理范围下,使用再多的有利于促成项目成功的措施也不为过。对于配置管理,应该以主干开发为首选,如果没有必要绝不要使用分支。此外,程序架构应该尽力解耦,松耦合的开发可以将影响和变化源缩减到很少。松散的耦合,更利于应对突如其来的变更。此外,越少的修改,合并冲突的几率就越低。因此,降低集成成本,不仅需要合理的SCM策略,也需要在程序架构方面动一番脑筋(例如面向组件开发,面向服务开发)。
主要参考书籍:
W3c0.com 提供的内容仅用于培训。我们不保证内容的正确性。通过使用本站内容随之而来的风险与本站无关。W3c0 简体中文版的所有内容仅供测试,对任何法律问题及风险不承担任何责任。 当使用本站时,代表您已接受了本站的使用条款和隐私条款。版权所有,保留一切权利。 鲁ICP备15022115号