Xiao Peng

My personal blog moves to xiaopeng.me , blogs about design patterns will be synced to here.
肖鹏,ThoughtWorks资深咨询师,目前关注于架构模式、敏捷软件开发等领域,并致力于软件开发最佳实践的推广和应用。
多次为国内大型企业敏捷组织转型提供咨询和培训服务,在大型团队持续集成方面具有丰富的经验。
  博客园 :: 首页 :: 联系 :: 订阅 订阅 :: 管理

公告

代码库管理案例分析

Posted on 2011-04-16 16:54 勇敢的鸵鸟 阅读(...) 评论(...) 编辑 收藏

前些天参加了公司内一个项目的代码库管理策略的讨论。以前在客户那里做咨询的时候类似的讨论也有很多,但是相对来说客户的情况比较稳定,而且项目与项目之间相似度比较高,所以可选的方式并不多。这一次讨论,因为是发生在ThoughtWorks内部,大家处于完全平等的位置,敞开讨论,反而让原来死板的理论真的活了起来。

背景

CWP是ThoughtWorks内部比较大的一个项目有30多人,当然这跟我们咨询的项目没法比。不过ThoughtWorks比较崇尚小团队,我们认为超过10个人的团队就应该考虑拆分了,这对于项目管理、团队沟通、架构隔离都有好处。项目原来主要关注于一个产品MTX,最近准备加入MTL产品,我们认为这是一个好的时机。MTX和MTL共享一个账户管理的功能。我们想把这个功能抽出来单独成为一个产品——Account Setting,因为未来还有其他的产品也要依赖于这个功能。由于人力资源的限制,Account Setting实际上要放到MTL团队开发,MTX与Account Setting的集成也要放到MTL团队开发。Account Setting的部分功能在MTX中已经实现。

讨论

一个基本的问题是——码库分开还是合在一起。

首先不论是分开还是合在一起都是可以工作的。其次,不论是分开还是合在一起都有相对的劣处。看上去很简单的两点。不事先明确地承认这两点,往往会导致争论陷入僵局。而且,不仅是在开始的时候强调,整个过程中都得反复地说。那么这是不是和稀泥呢?可以是也可以不是。停留在这个层次上就是和稀泥,进一步分析哪种方式会带来什么好处和什么坏处,就不是和稀泥。

首先看合在一起的好处。这些产品之间依赖关系是比较明显的,特别是这几个产品又是同一个团队开发。我们把代码放到一起,能够取得的天然的好处是版本对齐。一个产品依赖于另一个产品有几种方式——API依赖、RPC依赖、REST依赖。我们使用的是REST依赖,但是背后还有一个私有协议的依赖。如果代码是合在一起的,因为我们采用了持续集成的实践,我们可以确保任何时候我发布的版本都是可以一起协作的——不论是交换的接口还是协议。

合在一起的坏处呢?坏处和好处其实非常接近,由于通过代码管理工具进行了强制版本对齐,那么不同产品之间的依赖关系实际上就被绑死了。Account Setting升级了自己的协议,MTX必须同时更新,否则持续集成就不能通过。

分开的好处和坏处基本上跟合在一起的好处和坏处是相反的。分开意味着灵活的版本协作方式,但同时也意味着需要有人专门负责不同产品版本对齐的协调。还有就是版本库的管理——开发人员可能要在不同的版本库之间切换。

纠结

除了上述好处坏处的分析之外。还有些操作可能产生相反的结果。比如,分开可能同时意味着沟通成本的提高和降低。合在一起更方便联调,因为两边的代码都在一起,我可以这边改改那边改改,最终使它们能够一起工作;合在一起也助长了忽视接口设计的风气,使得两边的耦合越倾向于紧密,从而需要沟通的机会增加。我们说真正好的沟通模式是不需要沟通,可以将二者分开,使得双方都更加关注于接口的稳定和降低依赖。

怎么办?

好处-坏处、坏处-好处、纠结-纠结,如果在问题的内部继续讨论,永远都不会有结论。所以,必须跳出来看看,问题的大背景。我们到底是希望一个严格的版本对齐,还是灵活的版本协作。

我们注意到,未来会有更多的产品加入进来依赖Account Setting。保持所有的产品版本对齐,尤其是在开发过程中成本是非常高的。所以就分开吧。

我不说分开是对的,我只能说分开是一个还不错的选择。或者用丘吉尔先生的话说,除了合在一起之外,分开是最差的选择。甚至是不是真的比合在一起好,我也不能保证。这个讨论的价值让我们看到,分开带来了哪些好处,避免了哪些问题。——足矣!

版本依赖管理

代码库分开了,接下来就是持续集成环境怎么搭建。考虑到Account Setting可能会发布多个版本,不同的产品可能依赖于不同的版本。一种方式是把环境搭到Account Setting团队,每个版本维护一个环境,其他产品连到这个环境上做自己的持续集成。另一种方式是环境搭到各个产品那里,你要依赖什么版本你自己决定。

这让我想到在某公司做咨询的时候发生的一件事情。I公司的A部门,分为平台和数个产品多个团队。平台发布的东西交给产品之后,要做一个版的集成少则一两周,多则一两个月。经常平台发布过来的版本,我们所在的产品部门发现根本不可用。我们在产品部门搭建了持续集成环境,但是见效甚微。那么环境应该搭到哪儿呢?我们认为应该搭到平台部门去。你要交付东西给我,这个质量责任应该在你那里。

类比到我们的问题上来,似乎要搭到Account Setting团队这边。但是且慢,这个类比有个问题。Account Setting要对外发布,自己保证质量,搭建与产品集成的环境,这一点没有问题。但是产品自己的持续集成环境要是放到Account Setting这边来问题就大了。——耦合!ABCD四个产品可能都要依赖Account Setting的1.0版本,是不是它们任何一个的持续集成失败了,都要Account Setting去定位呢?更复杂的情况,可能某个产品需要跟小版本联调,这些情况在Account Setting这边会出现爆炸式组合。

那么好,我把环境搭到产品去好了。且慢,现在A产品搭了一个1.0版本的环境,为了联合开发某个特性,需要升级到1.1版本,这个特性由A产品的Dev1开发,那么如果把A产品中的1.0环境升级,其他人的本地构建和提交构建必将失败;如果不升级,Dev1的本地构建和提交构建必将失败。

这是持续集成中典型的环境管理问题。在持续集成中尽量保证本地构建和提交构建的一致性。为了这种一致性,构建对软件和硬件的依赖应该有明确的定义,并且做统一的管理。

持续集成环境管理

典型的持续集成中软件依赖管理方式就是对软件依赖做配置管理。即把Account Setting的发布包放到A产品的代码库中,A产品依赖哪个版本的AS,就提交哪个版本的发布包。构建失败可以回滚到一起的发布包。这样本地构建和提交构建依赖的都是一个版本的发布包。

这个还不是我们最终选择的方案。我们最终选择的方案是AS将自己的发布包放到一个公共可访问的仓库里面,其他产品可以引用不同版本的发布包,类似于Maven的机制。其原理与前面说的类似,其实这也算是一种配置管理吧。

这样一个讨论涉及到了——配置管理、测试、环境管理、流程、组织结构,基本上除了报告之外,与持续集成相关的各个维度都有所涉及。

The End。