每日编译(Daily Build)是你的好朋友

作者:周思博(Joel Spolsky)
译:Paul May 梅普华
Saturday, January 27, 2001
属于Joel on Software, http://www.joelonsoftware.com

1982年我家人带了一台很早期的IBM-PC到以色列,当时我们还是跑去仓库等PC由港口进来。我不知道用了什么方法,说服老爸买齐完整配备,有_两_ 台软碟、128 K记忆体、再加上一台点阵式印表机(印草稿用)和一台兄弟牌印刷品质的菊轮式印表机(列印时的声音和机关枪一样,不过更吵)。

IBM_PC.jpg

我想我们把能买的配备几乎都买齐了:PC-DOS 1.0、75美元的技术参考手册和完整的BIOS原始码列表、Macro Assembler、还有能显示完整80行和小写字母(!)的高级IBM单色萤幕。全部加起来大概是10,000美元(含荒谬的以色列进口税)。真是奢侈啊!

「每个人」都知道BASIC是种小孩用的电脑语言,要让你写出面条般纠缠不清的程式,还会让你的脑袋变成和乳酪一样都是空洞。所以我们花了600大元去买总共有三片磁片的IBM Pascal。这个编译器的第一轮编译要用第一片磁片,第二轮要用第二片,连结器则是在第三片。我写了一个简单的"hello, world"程式拿来编译,用的时间总共是8分钟。

嗯,这时间蛮长的。我写了一个批次档把整个过程自动化,把时间压到7分半。有快一点,不过当我想写长一点的程式(比如我的名作: 一定会赢我 的黑白棋)时,还是得花很长的时间等编译完成。「没错,」有位专业程式师告诉我:「我们通常会在办公室放块板子,等待编译完成时就去做仰卧起坐。写了几个月程式之后我就有腹肌了。」

有一天从丹麦传来了一个叫Compas Pascal的绝妙程式,Philippe Kahn把这只程式买下来并且改名为Borland Turbo Pascal。Turbo Pascal有点夸张,因为他和IBM Pascal的功能基本上相同,可是_连文字编辑器一起_ 只要33K记忆体就可以执行,这实在只能说佩服。更惊人的是一只小程式只需不到一秒就可编译完成。这就像一家默默无名的公司推出别克LeSabre的同型车款,可是时速有一百万英哩而且极为省油,环游世界一圈用的油还淹不死一只蚂蚁。

突然间我的生产力就提升了_许多_ 。

我就是在这时候学到_REP循环_ 的概念。REP代表「Read, Eval, Print」,是叙述lisp直译器一直在做的事:它会读取你的输入,把它求出来,然后印出结果。下面显示一个REP循环的范例:我键入某些东西,lisp直译把东西读进去,求解,然后印出结果。

REP_Loop.jpg

以稍大一点的尺度来看,你写程式的动作其实是一种放大版的REP循环,是一种名为编辑-编译-测试的循环。你编辑你的程式,进行编译,测试,然后看看能不能正常运作。

这里有个重要的观察结果,就是写程式时会一再重复这个循环,所以编辑-编译-测试的循环进行得愈快,你就愈有生产力,最快时就是能瞬间完成编译。电脑程式师想拥有 真正飞快的硬体 ,而编译器开发者会无所不用其极地做出超级快的编辑-编译-测试循环,这正是电脑科学上正式的原因。Visual Basic会在输入每行程式时进行字汇和文法分析,所以最后的编辑超级快速。而Visual C++的方法则是提供渐进编译、预先编译的档头和渐进连结。

不过当你进入拥有多个开发人员和测试人员的大团队时,又会遇到相同的循环,不过更大更复杂。测试人员找到程式的问题并回报问题。程式师会去修正问题。测试人员要等多久才会拿到修正的程式呢?在某些开发组织中,这种开发- 修正-重测的循环要花好几个星期。表示整个组织的运作完全没有生产力。要让整个开发组织运作的更平顺,就得专注让开发-修正-重测的循环更紧凑。

要达到这个目的有个好方法,就是_每日编译_ 。每日编译是一个_自动、每天、完整_ 的编译动作,把全部原始程式重新编译一遍。

自动- 因为你会用cron(在UNIX上)或是Tash Scheduler服务(在Windows上)安排每天在固定的时间编译程式。

每天- 更密集也可以。连续编译更吸引人,不过由于版本管理的问题(待会就会提到)可能做不到。

完整- 你的程式可能有很多版本。针对不同的语言的版本,不同的作业系统,可能还有分豪华版和入门版。每日编译必须建立_所有_ 的版本。而且必须从头建立每个档案,不可以依靠编译器有潜在问题的渐进重新编译功能。

下面列出每日编译众多好处中的几项:

1. 当某个问题修好之后,测试人员可以很快就拿到新版本重测,看看问题是否真的修好了。
2. 开发人员可以比较放心自己的修改不会破坏到要出货的1024种版本,不必真的自己_准备_ 一套OS/2来测。
3. 在每日编译开始前把程式存入版本管理系统的开发人员会比较安心,因为知道自己不会因为放入某些会「破坏(break)」编译的东西而干扰到别人。所谓破坏编译就是让编译无法进行。这对整个程式团队来说就等于Windows的蓝色当机画面,当某个程式师忘记把新增的档案放入版本管理系统时常常出现。在_他们_ 的机器上都正常,不过等别人由版本管理系统拿程式出来编译时,就会遇到连结错误,然后什么事都不能继续做。
4. 行销部门及beta测试者之类的外部人员都必须用到尚未完成的产品,这时候就可以选一个已知相当稳定的版本暂时用一阵子。
5. 如果有维护一个存放所有每日编译结果的档案库,当你发现很奇怪的新问题又搞不懂原因时,可以利用二分法搜寻过去的档案,找出问题问题第一次出现的时间。再配合良好的版本管理,或许就能找出哪一些更动造成这个问题。
6. 当某个测试人员回报一个程式师认为已修正的问题时,测试人员可以说在哪一版看到这个问题。然后程式师可以回头查查自己什么时候把修正存入,就知道是否_真的_ 修好了。

接下来是实施的方法。你需要一台每日编译的伺服器,它可能会是你能拿到最快的电脑。然后写一个脚本命令,由版本管理系统取出所有最新的程式码(你_有在用_ 版本管理系统吧?),然后从头编译会出货的所有版本。如果有安装程式或设定程式,也要重新编译。所有会出给客户的东西都应该由每日编译程序产生。把每次编译的结果存在依日期编码的专属目录里。每天在固定时间执行你的脚本命令。

1. 建立最终编译结果的_所有动作_ 都必须由每日编译脚本完成,这一点非常重要。由取得原始码开始,一直到把结果放到网站上适当位置供人下载(在开发过程中当然会有一个测试伺服器),所有过程全部都包含在内。想要确保整个编译制作过程中_没有_ 任何步骤只有某个人知道,这也是唯一的方法。这样子就绝对不会发生由于某人被车撞,而且只有他会做安装程式,所以不能发行产品​​的鸟事。在Juno的团体中,只要知道编译伺服器在什么地方以及双击「每日编译」的图示,就能从头建立一套完整编译结果。
2. 以下是绝不能容许的行为:在准备发行程式时发现_一只小虫_ ,于是你就在每日编译伺服器上直接把它修好然后发行。每日编译有条黄金定律:只有从完整取出程式码开始,并经过完全重新的每日编译所制作的程式才可以发行。
3. 把你的编译器的警告等级开到最高(在微软的世界里就是-W4,用gcc的话就是-Wall),并且设定成即使遇到最小的警告都要停止编译。
4. 如果每日编译失败,就要冒险停止整个团体的作业。全部动作都停下来重新编译,直到问题修正为止。有时候一天之内会做很多次每日编译动作。
5. 你的每日编译脚本应该用电子邮件把失败状况回报给整个开发团队。用grep把"error"或"warning"记录抓出来再放入电邮里也不是难事。脚本也要能把状态报告附加到大家都能看到的HTML网页上,这样程式师和测试人员就能很快地知道哪个编译结果是成功的。
6. 在微软的Excel团队有一个很有效的规则:破坏编译的人必须开始负责照顾每日编译,直到有其他新的人破坏才换手。这样做能让大家有强烈动机维持编译正常运作,而且几乎每个人都会轮流照顾编译动作,所以大家都会知道编译结果是怎么产生的。
7. 如果你的团体成员都在同一个时区工作,午餐时间会是个进行编译的好时间。这样子大家都在午餐前把最新的程式放入版本管理,大家吃饭时就进行编译。等人吃完午餐回来,如果编译失败大家就来解决问题。只要编译正常完成,大家就可以取出最新的版本继续作业,不必担心会被编译错误卡住。
8. 如果你的团体分散在两个时间,每日编译的时间得适当安排,以确保第一个时区的人不会卡到另一个时区。在Juno的团体中,纽约的开发人员会在下午7点把程式放入版本管理然后回家。如果他们破坏了编译,在印度海得拉巴的团队正要工作(大约是纽约时间下午8点)却因此卡住一整天。于是我们开始实施两次每日编译,分别在两边下班前一小时进行,就完全解掉这个问题了。

进阶阅读:

1. 有些针对每日编译工具的[讨论](http://discuss.fogcreek.com/joelonsoftware/default.asp?cmd=show&ixPost=862)
2. 实施每日编译非常重要,所以列入[迈向高品质的12个步骤](http://www.joelonsoftware.com/articles/fog0000000043.html)。
3. 在G. Pascal Zachary的书[Showstopper](http://www.amazon.com/exec/obidos/ASIN/0029356717/ref=nosim/joelonsoftware)里有很多关于Windows NT团体编译制作(每周一次)的趣事。
4. Steve McConnell在[这里](http://www.construx.com/stevemcc/bp04.htm)谈每日编译。

这些网页的内容为表达个人意见。
All contents Copyright © 1999-2006 by Joel Spolsky. All Rights Reserved.