首页 / 科幻灵异 / 超级系统 / 章节正文阅读

黑客圣经:大教堂和市集(2 / 5)

作品:《超级系统

unix传统另一有力之处是许多用户都是黑客,因为源优码是公开的,他们可以成为高效的黑客,这一点在linux世界中也被推向了令人高兴的极致,这对缩短调试时间是极端重要的,在一点鼓励之下,你的用户会诊断问题,提出修订建议,帮你以远比你期望快得多的速度的改进代码。

把用户当做协作开发者是快速改进代码和高效调试的无可争辩的方式。

这种效果的力量很容易被低估,实际上,几乎所有我们自由软件世界中的人都强烈低估了用户可以多么有效地对付系统复杂性,直到linus让我们看到了这一点。

实际上,我认为linus最聪明最了不起的工作不是创建了linux内核本身,而是发明了linux开发模式,当我有一次当着他的面表达这种观点时,他微笑了一下,重复了一句他经常说的话:“我基本上是一个懒惰的人,依靠他人的工作来获取成绩。”象狐狸一样懒惰,或者如robertheinlein所说,太懒了而不会失败。

回顾起来,在gnuemacslisp库和lisp代码集中可以看到linux方法的成功,与emacs的c内核和许多其他fsf的工具相比,lisp代码库的演化是流动性的和用户驱动的,思想和原型在达到最终的稳定形式之前往往要重写三或四次,而且经常利用internet的松散合作。

实际上,我自己在fetchmail之前最成功的作品要算emacsvc模式,它是三个其他的人通过电子邮件进行的类似linux的合作,至今我只见过其中一个人(richardstallman),它是sccs、rcs和后来的cvs的前端,为emacs提供“onetouch”版本控制操作,它是从一个微型的、粗糙的别人写好的模式开始演化的,vc开发的成功不像emacs本身,而是因为emacslisp代码可以很快的通过发布/测试/改进的过程。

(fsf的试图把代码放入gpl之下的策略有一个未曾预料到的副作用,它让fsf难以采取市集模式,因为他们认为每个想贡献二十行以上代码的人都必须得到一个授权,以使受到gpl的代码免受版权法的侵扰,具有bsd和mitx协会的授权的用户不会有这个问题,因为他们并不试图保留那些会使人可能受到质询的权力)。

四.早发布、常发布

尽量早尽量频繁的发布是linux开发模式的一个重要部分,多数开发人员(包括我)过去都相信这对大型工程来说是个不好的策略,因为早期版本都是些充满错误的版本,而你不想耗光用户的耐心。

这种信仰强化了建造大教堂开发方式的必要性,如果目标是让用户尽可能少的见到错误,那你怎能不会仅仅每六个月发布一次(或更不经常),而且在发布之间象一只狗一样辛勤“捉虫”呢?emacsc内核就是以这种方式开发的,lisp库,实际上却相反,因为有一些有fsf控制之外的lisp库,在那里你可以独立于emacs发布周期地找寻新的和开发代码版本。

这其中最重要的是ohio州的elisp库,预示了今天的巨大的linux库的许多特征的精神,但是我们很少真正仔细考虑我们在做什么,或者这个库的存在指出了fsf建造教堂式开发模式的什么问题,1992年我曾经做了一次严肃的尝试,想把ohio的大量代码正式合并到emacs的官方lisp库中,结果我陷入了政治斗争中,彻底失败了。

但是一年之后,在linux广泛应用之后,很清楚,一些不同的更加健康的东西诞生了,linus的开发模式正好与建造教堂方式相反,sunsite和tsx11的库开始成长,推动了许多发布。所有这些都是闻所未闻的频繁的内核系统的发布所推动的。

linus以所有实际可能的方式把它的用户作为协作开发人员。

早发布、常发布、听取客户的建议

linus的创新并不是这个(这在unix世界中是一个长期传统),而是把它扩展到和他所开发的东西的复杂程度相匹配的地步,在早期一天一次发布对他来说都不是罕见的!而且因为他培育了他的协作开发者基础,比其他任何人更努力地充分利用了internet进行合作,所以这确实能行。

但是它是怎样进行的呢?它是我能模仿的吗?还是这依赖于linus的独特天才?

我不这样想,我承认linus是一个极好的黑客(我们有多少人能够做出一个完整的高质量的操作系统内核?),但是linux并不是一个令人敬畏的概念上的飞跃,linus不是(至少还不曾是)象richardstallman或jamesgosling一样的创新天才,在我看来,linus更象一个工程天才,具有避免错误和开发失败的第六感觉,掌握了发现从a点到b点代价最小的路径的决窍,确实,linux的整个设计受益于这个特质,并反映出linus的本质上保守和简化设计的方法。

如果快速的发布和充分利用internet不是偶然而是linus的对代价最小的路径的洞察力的工程天才的内在部分,那么他极大增强了什么?他创建了什么样的方法?

问题回答了它自己,linus保持他的黑客用户经常受到激励和奖赏:被行动的自我满足的希望所激励,而奖赏则是经常(甚至每天)都看到工作在进步。

linus直接瞄准了争取最多的投入调试和开发的人时,甚至冒代码不稳定和一旦有非常棘手的错误而失去用户基础的险,linus似乎相信下面这个:

如果有一个足够大的beta测试人员和协作开发人员的基础,几乎所有的问题都可以被快速的找出并被一些人纠正。

或者更不正式的讲:“如果有足够多的眼睛,所有的错误都是浅显的”(群众的眼睛是雪亮的),我把这称为“linus定律”。

我最初的表述是每个问题“对某些人是透明的”,linus反对说,理解和修订问题的那个人不一定非是甚至往往不是首先发现它的人,“某个人发现了问题”,他说,“另一个理解它,我认为发现它是个更大的挑战”,但是要点是所有事都趋向于迅速发生。

我认为这是建造教堂和集市模式的核心区别,在建造教堂模式的编程模式看来,错误和编程问题是狡猾的、阴险的、隐藏很深的现象,花费几个月的仔细检查,也不能给你多大确保把它们都挑出来的信心,因此很长的发布周期,和在长期等待之后并没有得到完美的版本发布所引起的失望都是不可避免的。

以市集模式观点来看,在另一方面,我们认为错误是浅显的现象,或者至少当暴露给上千个热切的协作开发人员,让他们来对每个新发布进行测试的时候,它们很快变得浅显了,所以我们经常发布来获得更多的更正,作为一个有益的副作用,如果你偶尔做了一个笨拙的修改,也不会损失太多。也许我们本不应该这样的惊奇,社会学家在几年前已经发现一群相同专业的(或相同无知的)观察者的平均观点比在其中随机挑选一个来得更加可靠,他们称此为“delhpi效应”,linus所显示的证明在调试一个操作系统时它也适用——delphi效应甚至可以战胜操作系统内核一级的复杂度。

我受jeffdutky(ahref="mailto:dutky@@/a)的启发指出linus定律可以重新表述为“调试可以并行”,jeff观察到虽然调试工作需要调试人员和对应的开发人员相交流,但它不需要在调试人员之间进行大量的协调,于是它就没有陷入开发时遇到的平方复杂度和管理开销。

在实际中,由于重复劳动而导致的理论上的丧失效率的现象在linux世界中并不是一个大问题,“早发布、常发布策略”的一个效果就是利用快速的传播反馈修订来使重复劳动达到最小。

brooks甚至做了一个与jeff相关的更精确的观察:“维护一个广泛使用的程序的成本一般是其开发成本的40%,奇怪的是这个成本受到用户个数的强烈影响,更多的用户发现更多的错误”(我的强调)。

更多的用户发现更多的错误是因为更多的用户提供了更多测试程序的方法,当用户是协作开发人员时这个效果被放大了,每个找寻错误的人都有自己稍微不同的感觉和分析工具,从不同角度来看待问题。“delphi效应”似乎因为这个变体工作变得更加精确,在调试的情况下,这个变体同时减小了重复劳动。

所以加入更多的beta测试人员虽不能从开发人员的中减小“最深”的错误的复杂度,但是它增加了这样一种可能性,即某个人的工具和问题正好匹配,而这个错误对这个人来说是浅显的。

linus也做了一些改进,如果有一些严重的错误,linux内核的版本在编号上做了些处理,让用户可以自己选择是运行上一个“稳定”的版本,还是冒遇到错误的险而得到新特征,这个战略还没被大多数linux黑客所仿效,但它应该被仿效,存在两个选择的事实让二者都很吸引人。

五.什么时候玫瑰不是玫瑰?

在研究了linus的行为和形成了为什么它成功的理论之后,我决定在我的工程(显然没有那么复杂和雄心勃勃)里有意识的测试这个理论。

但我首先做的事是熟悉和简化popclient。carlharris的实现非常好,但是有一种对许多c程序来说没有必要的复杂性。他把代码当作核心而把数据结构当作对代码的支持,结果是代码非常漂亮但是数据结构设计得很特别,相当丑陋(至少对以这个老lisp黑客的标准来看),然而除了提高代码和数据结构设计之外,重写它还有一个目的,就是要把它演化为我彻底理解的东西,对修改你不理解的程序中的错误负责可不是一件有趣的事。

第一个月我只是在领会carl‘s的基本设计的含义,我所做的第一个重大修改是加入了imap支持,我把协议机重新组织为一个通用驱动程序和三个方法表(对应pop2、pop3和imap),这个前面的修改指出一个需要程序员(特别是象c这种没有自然的动态类型支持的语言)记在脑中的一般原理:

聪明的数据结构和笨拙的代码要比相反的搭配工作的更好

fredbrooks也在他第11章中讲道:“让我看你的[代码],把你的[数据结构]隐藏起来,我还是会迷惑;让我看看你的[数据结构],那我就不需要你的[代码]了,它是显而易见的”。

实际上,他说的是“流程图”和“表”,但是在三十年的术语/文化演进之后,事情还是一样的。