首页 > 软件工程 > 构建失败

构建失败

2011年11月16日 发表评论 阅读评论

Joel著名的12条测试里有两条与构建相关:

  • Can you make a build in one step?
  • Do you make daily builds?

这两条相信大部分有些规模的公司都能够做到。不过,有每日构建,就必然伴随着构建失败,特别是在多人协作的环境,由于代码依赖、开发人员失误(比如只签入了一部分代码)、代码合并等等原因,连续好几天构建都失败的情况也偶会发生。

失败的代码构建让人万分沮丧,首先打击了士气。没有人打算让伟大的项目在第一步就失败,就像70圈的F1在热身圈就冲出赛道退出比赛一样。另外还造成了大量的浪费,由于构建失败,同一天签入的代码就没法在第一时间得到测试,加大了项目后期测试的压力。而当你下载了最新代码,却发现连编译链接都无法通过,那估计你也没兴趣写代码了。

正如bug不可避免一样,构建失败也是不可避免的(特别是对于像C/C++这种有大量预编译的语言),即使构建成功与否是非常容易验证的,非黑即白。所以构建失败往往也被认为是最愚蠢的错误。不过再愚蠢的错误,也必须正面对待,而不是对犯错的哥们嘲笑或者怒吼了事。

对付一件坏事,基本上两种办法:要么预防发生,要么减小影响。

预防:

1. 降低构建的复杂度:太大的构建模块和构建链/工具链、太长的构建时间、过多的代码依赖、紧缺的构建服务器资源都会让开发人员倾向于减少构建的次数。我也不止一次看到,由于最后只改动了几个字符,开发人员懒得重新构建造成的构建失败。每个人都会偷懒(不是有句话说“偷懒就是美德”?),但如果降低偷懒的动机,偷懒自然会减少。合理的模块划分、分布式版本系统的使用(大大加快checkout时间)、更强的构建机器(CPU、内存,特别是SSD)、高效的构建方法(怎么着也得并行构建)。如果一次构建只需要15分钟而不是3个小时,没有人愿意冒风险悍然签入代码。经常是还有2个小时就下班但构建需要3个小时的情况下。

2. 惩罚:虽然嘲笑或者怒吼解决不了问题,不过一些善意的小惩罚还是可以接受的。微软90年代初的标准是5美元一次,按照收入比换算的话在国内大概20RMB应该还是合理的范围。不过国人似乎不喜欢现金,那么改成请大家吃零食也是个不错的主意。另外一个方法就是把某个恶搞标志放到TA桌子上,直到下一个人破坏了构建才能送出去。

减小影响:

3. 提高构建频率:把每日一次构建改成每日两次构建可以提早一半的时间发现问题。如果把构建频率提高到每天4-6次,并禁止在测试发布版构建和其上一次构建之间的签入任何代码(除非是修复破坏构建的代码),这样就保证至少有4-6小时的时间修复失败构建。(这个时间应该足够修复所有构建相关问题)。当然如果需要构建的版本特别多(特别是多平台发布和多分支维护的情况下),在可利用的资源条件下无法做到这个标准,可以采取差异化方案。主要工作版本和发布平台(即签入最频繁的构建)增加构建频率,几天才有一次代码签入的分支可以只做每日构建。这样就可以确保最值得关注的地方得到最多的资源。

4. 签入队列:签入的代码不马上进入开发的主分支,而是进入一个签入队列。每天签入队列里的改动要通过构建后才能进入主分支,如果当中有破坏构建的签入,则当天的所有签入都会被hold住直到问题解决。这样的代价是复杂性增加了,另外每日测试和最新的代码会有一天的延迟,不利于问题的及早发现(不过问题仍然可以追溯到某天签入代码的范围里)。

5. 专人负责:代码能否构建是软件的第一要素,这么重要的东西当然值得指派专人(或者是一个委员会)来负责。国际化团队需要在每个点(或者相近的时区)配备负责人,确保破坏构建的签入能够早几个小时被定位,甚至代替责任者修复一些愚蠢的问题。每当构建失败发生,委员会成员都会收到通知邮件,这时候他(们)应该停止手上的所有工作来解决这个问题,并在第一时间找到责任人通知其修复。如果暂时没法找到,也可以通知其peer或者在找到一两个相关reviewer的情况下自行修复。(建议与第6、8条配合使用就不会找不到责任者)

6. 自动构建:如果每次代码的签入都能够伴随一次完整的自动化构建,构建期间锁住代码库,并在确认构建结果后才允许正式签入,这样我们基本就不会碰到构建失败。这种方法其实是提高构建频度的极致。当然对于大型开发团队来说这并不现实,也可以做一些妥协,比如自动构建期间放弃代码库的锁定。毕竟由于多人同时签入代码导致的失败构建,所有人都可以理解的,而这种情况也相对较少。

7. 停止生产线:这条是丰田的做法。出现构建失败后停止所有的代码签入(当然修复构建的除外),直到下一次成功构建。期间构建负责人介入并定位问题(或者责任人自己认领)。这样有利于隔离问题,避免连续的构建失败。而夜间测试至少也有一个新的版本可以利用。

8.  签入时间限制:这条是从《微软的秘密》中看到的,所有人在下午2点之后不能签入代码。每天2点开始每日构建,一旦出现什么问题可以有人当场fix而不是将问题拖到第二天而浪费一整晚测试的宝贵时间。但对于国际化开发的团队显然不合适,实际一点的做法是要求所有人必须在下班前3小时之前做好当天的代码签入。另外,国际化开发的团队也总是有每日构建及测试的固定时间,一般会是在岸团队的夜里(想不到onshore的翻译了),可以规定在每日测试使用的版本构建前3小时内不允许的签入,而在这个构建前安排一个小的构建进行验证。总的原则是保证构建能够成功。

9. 签入前的公示:也是从《微软的秘密》里偷来的,特别是对于大规模的签入。公示可以是发邮件,也可以是在某个系统里登记一下。而每个人在签入之前也检查一下邮件或者系统。

小结一下减小影响的办法:及早发现、及早修复、隔离错误、拉长签入流水线。

最后是书托时间。关于软件开发的优秀实践,《微软的秘密》有很多很好的例子,虽然里面的有些相对现在流行的“敏捷开发”有些老土(书里写的基本上是92-95年的微软),但由于这么多年来软件开发的效率没什么本质上的提高,所以这些实践到现在仍然适用。

分类: 软件工程 标签:
  1. JT
    2011年11月17日07:21 | #1

    我们公司买了个自动构建的软件叫Eletronic Commander,只有有签入就构建一次,这样的设定当然也是因为项目的构建不需要花太多时间,构建成功与否都会自动发邮件通知。然后老板就把他儿子玩的一只丑陋但又比较大只的恐龙带到公司,只要谁签入了促使构建失败的代码,就把那只恐龙放在对方的显示器上,一开始还比较好玩,也怕拿到恐龙,但后来丧失新鲜感后就不再这么弄了,恐龙也就被放一边了。我觉得惩罚措施一定要每隔一段时间更新一下,算作是工作中的小趣味。

    [回复]

    marshall 回复:

    @JT, 恐龙这个主意很像《微软的秘密》里的办法,不过道具换成了一顶帽子和5美元

    [回复]

  2. JT
    2011年11月17日07:21 | #2

    这么优秀的评论居然还要审核,一看就知道不是spam啦

    [回复]

  3. 2011年12月23日14:16 | #3

    我虽然学代码,不过学得太差啦

    [回复]

  1. 本文目前尚无任何 trackbacks 和 pingbacks.

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Click to hear an audio file of the anti-spam word


Warning: fsockopen() has been disabled for security reasons in /home/onlymars/public_html/wp/wp-includes/class-snoopy.php on line 1148