05 2010存档
最近参与一个大项目,几十个开发人员,代码都放在一个trunk下,也就是说,这几十个人的代码都在一起编译,一起跑单元测试,一起在半夜跑自动化测试用例。反正我以前是从未加入过这么大的trunk(之前我参加的项目最多就四五个人在一起写代码而已),现在发现巨大的trunk造成了一些很郁闷的问题。
首先,编译越来越慢。项目用scons来编译(我暂时还没发现scons比Makefile好在哪里),一编译就耗干系统的内存(我们的系统是8G内存),整个trunk重编译一次是两个多小时,好在我负责的只是其中一部分,但是即使是这一部分,也要花十多分钟编译(我目前还不能说这是scons慢造成的,但是python占内存偏多,嫌疑很大),这在我调试阶段很费时间。
其次,互相干扰很严重。几十个程序员,就算一个人每一个月才出现一次代码错误,那加起来就是:每天都有人至少犯一次代码错误。虽然使用了ReviewBoard,但是review不可能洞察一切,还是会有单元测试频繁的不过。后来加了一个提交代码的工具,为每个提交代码的人单独编译并跑单元测试,通过了才真正交给subversion,但这样还是有问题:每次提交,我都发现有很多人排着队的等前面的人编译完,我有几次好不容易排上了,跟别人的提交一起编译,结果由于别人的提交编译不过,我还得重新排队......问题的根源在于:这个trunk上的提交太过频繁了。毕竟几十个人呢,几乎每十分钟就有新的code需要提交。
可能长期在互联网公司干,我对那种动辄几百万行code,几十兆可执行文件的大软件越来越反感。我觉得好的软件,一定是满足且刚好满足了某一类用户的某一个需要,而不是妄图去满足所有用户的很多需要。说白了:尽量做小巧的东西。如果项目真的是个大项目,那最好是能拆成多个小软件,好歹代码能分到不同的trunk下去,trunk小了,挤在一个trunk下的开发人员就会少很多,就不会有漫长的编译和频繁的提交了,然后,这些小软件一起运行,完成某个大工作。
说得有点理想化了,把大项目拆成小部分,这个道理谁都懂,但难度在于怎么拆?这种问题我回答不了,也许《unix编程艺术》能够回答:不要写一个巨大的进程,应该写多个,然后一起工作。进程都可以拆开,代码有什么不能拆开的?有人可能担心效率,但是相比于混乱的管理,这点效率损失我觉得还算值得。
以上是我的看法。实际中,反例也是有的,比如windows NT就是一堆人挤在一个代码trunk下做出来的,而且产品还很成功。但是从《观止》里可以看出,NT的开发人员也一样被频繁的build break和单元测试fail折磨得人不人鬼不鬼,也许这就是为什么他们要辛苦上6年才能开发完成,以及为什么操作系统的未来是属于微内核的(微内核巧妙的把OS拆开了)。
====== 2010.5.10 ======
补充一下,每次编译,除了内存,CPU也被占满,登录同一台服务器的其他人连vi都用不了,到了后来,我在哪台机上编译,哪台机上的开发人员就埋怨,真成“嫌人”了;编译完后,20G的硬盘空间就没了,想只编译一部分是不行的,因为没拆开,整个trunk必须一起编译。
更可怕的是,这么大的trunk,还要打分支,一个160G的硬盘,才能下载编译几个分支呢?