如果我们有多个敏捷团队在同一个代码库上工作时,如何将彼此之间代码互相冲突的风险最小化?如何确保每个迭代结束时拥有一个干净的、可发布的软件版本?本文讲述了关于如何在敏捷的环境中与多个团队共同进行版本控制工作的实例——这正是我们在《Scrum and XP from the Trenches》中描述的公司所采纳的方式。
本文并非专为版本控制专家所写,实际上这样的专家在本文中找不到新东西。本文是为我们这些希望进行简单、有效的协作的人所准备的。任何直接参与敏捷软件开发的人,无论他承担何种角色,都有可能对其感兴趣——每个人都会用到分支和合并,而不只是配置经理。
介绍
本文讲述了关于如何在敏捷的环境中与多个团队共同进行版本控制工作的实例。我假定你已经熟悉了Scrum的基本元素、XP方法和任务板。这些方式不是我发明的,它们是基于“主线(mainline)模型”或“稳定主干(stable trunk)模式”。想阅读更多信息请查看引用部分。
撰写本文,是因为我一直在遇到需要类似内容的团队。许多团队在理解了模型之后,似乎非常喜欢这些模型。它也正是我们在《Scrum and XP from the Trenches》中描述的公司所采纳的方式。它真的可以帮助我们以更敏捷的方式来开发和发布软件。通过以易于阅读的方式来描述模型,也许我不再需要反复在白板前做解释了。)
注意这只是众多模式中的一种,不是“银弹“。如果你决定采用该模型,也许你需要做出一些变更来适应你自己的特定上下文。
目标
在多个团队构成的敏捷环境中,版本控制模型必须达成以下目标:
快速失败
代码冲突和集成问题应该可以被迅速发现。
经常修复小问题要胜过不常修复大问题。
一直可发布
即使经历了一个混乱的Sprint,也要保证至少有些可以发布的内容。
简单
所有的团队成员每天都会使用这些模式,所以相关规则和程序必须要简单明了。
单页总结(对于挂在墙上的内容)
如果该图让你觉得很迷惑,别着急,阅读本文即可。如果其中的理念对你来说很明显,读读本文也无妨。
版本控制模式
分支所有者&方针
下面是要遵循的一条简单规则。
规则:每个分支(即使是主干分支)都拥有一个所有者和一条方针。
不遵守上述规则,我们只能得到一片混乱。方针说明按照本规则,什么样的内容可以检入到当前分支中。所有者是负责定义和检查规则执行情况的人。
“完成”概念
一个用户故事怎么样才算“完成”?更明确地说,团队什么时候才可以把一个用户故事移入到任务版上的“完成”一栏之中?这又到底意味着什么?
我会给出下面的假定。
假定:“完成”的定义=“可发布”。
所以当一个团队成员说某个用户故事已经“完成”,并将故事卡移入到“完成”一栏中之后,客户就可以马上跑到房间中说:“太好了!我们现在就上线吧!“,而且团队中没有人会说:“别,先等等。”
你可以使用任何你喜欢的“完成”的定义。但是要记得——如果定义中没有完全包含“可发布”的含义,你就要好好想想了:在“完成”定义中没有包含哪些内容?谁会来补齐这些内容?什么时候?如果在“完成”之后出现问题,又会发生什么?
“完成”分支
当一个故事“完成”后,它需要有一个落脚之处。使用我的关于“完成”的定义(“可发布”),就意味着系统中的某个分支可以发布,这样该用户故事对应的功能就可以进入到生产系统之中了。这就是“完成”分支。
任何分支都可以是“完成”分支。我将会使用主干作为“完成”分支(这是一个不错的开始)。有时这被成为“主线”。
假定:主干作为“完成”分支。
主干方针:
任何时候都可以发布
希望尽早发布
“任何时候都可以发布”,这意味着:在任何时候,产品所有者都可以基于主干的最新版本,发布新版本的产品。
下面是一个示例。
蓝色的线表示主干。每个绿色的球形图案表示一次代码检入活动。可以看到在本次Sprint中共检入了5次内容。虽然通常我们是在每个Sprint结尾时才进行发布,不过还是可以在任何时候从主干中发布产品。如果在接近Sprint结束时,有一半的团队成员生病,因此导致没有时间完成故事#5,我们还是可以进行一次发布。当然,我们也可以选择先不发布,以等待团队在另一个Sprint中完成故事#5。
“希望尽早发布”意味着如果我们不想让某个故事相关功能上线(或者说不关心它是否上线),就不要检入该故事相关的代码。如果我不希望发布上图中的故事#3,这个分支就被我毁掉了。由于这个分支不再是可发布的,我就违反了分支的方针。
规则:不要在单一分支上合并不同的发布周期。
何时创建额外分支?
新分支的创建越少越好。下面是一条基于经验的原则。
推荐:只在下面这种状况下才创建新的分支:当需要检入新的内容,而且没有哪个现有的分支能够在不违反自身方针的状况下完成本次检入。
工作分支
好,假设我们已经有了一个很好、很干净的主干,并且在任何时刻都处于“可发布”状态。
等一下。“可发布”意味着已完成集成测试。这就意味着我们必须要 运行集成测试。也就是说我们要在向主干检入代码之前要运行集成测试。
那我应该向何处检入我认为已经完成、但是在检入主干前需要进行验证的代码呢?当然,我可以在本机上完成测试,并直接将通过测试的代码检入到主干之中。但这还是有点吓人,我相信大家都遇到过“嘿,但是它在我的机器上运行没有问题啊”这样的事情。
另外一个问题是“好吧,我完成了今天的编码任务,现在要回家了。我该把代码检入到哪里?还没有测试过呢,所以不能检入到主干中。我想把它检入到别的地方,这样其他的团队成员就可以在其基础之上继续工作了”(敏捷团队是采取代码集体所有制的,对吧?)。
你看,我们有希望检入的内容,但是不存在不违反分支方针就可以进行检入的地方。这就是建立新分支的一个合理原因了。
我们可将此称为工作分支,团队所有成员都可共享该分支。有人称其为开发分支。
团队A的工作分支方针:
- 代码完成编译和构建,并通过所有的单元测试。
很好,现在我们有两个分支了。一个稳定的分支(主干)和一个稍微不那么稳定的分支(团队分支)。团队分支是红色的,表示它不太稳定;例如:这个分支通过了单元测试,但是它可能还没有完成集成测试,所以还没有稳定到可以发布的状态。好,现在团队有地方可以检入正在进行中的工作了!
嗯,那要是需要同步不同的分支时应该怎么做呢?往下看。
从工作分支公开发布(publish)至主干
最终(我们希望)一个故事可以进入到“完成”状态。或者更明确地说,最终工作分支会达到可发布状态。此时我们可以(而且应该)将此分支公开发布到主干上,比如将工作分支上所有的新代码复制到主干上。完成后,主干与工作分支就完全相同了。
我们可以称此过程为“公开发布”,因为我们已经完成了一些工作,而且现在已经准备好将其“公开发布”回主干供发布用。这样说只是一个有用的隐喻。
下面是一个示例。假设我们已经实现了两个故事:“开户(Register)”和“存款(Deposit)”。它们都是“已完成”的,也就是说通过了单元测试、集成测试,并且处于“可发布”状态。我们已经开始处理“取款(Withdraw)”这个故事,但是它还没有“完成”。任务板看起来会像下面这张图示一样:
每个黄色的即时贴表示一项任务,也就是要完成故事需要做的一项工作。例如编辑类X,更新构建脚本,等等。每项任务通常包含一个人日的工作,每个故事通常包含3至8个人日的工作。
分支的过程会像下面这样:
我们的第一个团队实现了“开户”故事,并将代码检入到工作分支中,运行集成测试,修正一些问题,再次检入,再次运行测试,通过了!“开户”故事就“完成”了!然后将其公开发布到主干之中。
接下来实现“存款”。只需要执行一次检入就可以了。集成测试通过,我们再次把代码发布到主干之中。
现在团队正在实现“取款”故事。他们已经完成两次检入了,但是这个故事仍然没有完成。
注意“发布到主干”并不是说我们仅把某个故事的代码直接拷贝到主干中,而是意味着所有的工作拷贝到主干中,做一次完整的同步。
这样就带来了两个很有趣的问题:
- 如果团队同时在实现多个故事,该怎么办?
- 如果其他团队也正在向主干发布内容,又该怎么办?
我们还是一个接一个地来看这些问题。
如果团队同时在实现多个故事该怎么办?
如果团队每次实现一个故事,将代码发布到主干中并不算什么大不了的事情。只要这个故事相关的代码在工作分支上完成实现并通过测试,我们把所有的相关内容从工作分支上复制到主干上就可以了。搞定!
先等一下。如果团队中同时开发多个故事呢?如果“开户”故事完成了,而“存款”还在进行中呢?
如果我们在这个点上向主干进行同步,就会将尚未完成的“存款”故事同步进去,这时它还不能发布呢!而且违反了主干的版本控制方针!
当然,我们可以等到“存款”故事完成。
(等待……)
好了,现在“存款”故事完成了!太棒了!等一下……现在有人开始开发“取款”用户故事了!没错!同样的问题又发生了!
如果 “存款”故事的一个测试失败了,就很难知道是因为“存款”故事相关代码造成的,还是由于检入同一分支中并且部分完成的“取款”故事相关代码的原因。
等待无法起到任何帮助作用。这样实际上是在滚雪球,期望在未来某个假设的时间点上所有的故事都可以完成(如果这样的情况真的能够发生的话),而且可以进行一次大规模的发布。
上述是一个非常普遍的问题。我们该怎么做呢?
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/14780914/viewspace-410097/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/14780914/viewspace-410097/