黑客圣经:大教堂和市集(1 / 2)
一大教堂和市集
liu的影响是非常巨大的。甚至在5年以前,有谁能够想象一个世界级的操作系统能够仅仅用细细的ir连接起来的散布在全球的几千个开人员有以业余时间来创造呢?
我当然不会这么想。在199年早期我开始注意liu时,我已经参与ui和自由软件开达十年之久了。我是八十年代中期gu最早的几个参与者之一。我已经在上布了大量的自由软件,开和协助开了几个至今仍在广泛使用的程序(had模式,1if等等)。我想我知道该怎样做。
liu推翻了许多我认为自己明白的事情。我已经宣扬工具、快原型和演进式开的ui福音多年了。但是我也相信某些重要的复杂的事情需要更集中化的,严密的方法。我相信多数重要的软件(操作系统和象as一样的真正大型的工具)需要向建造大教堂一样来开,需要一群于世隔绝的奇才的细心工作,在成功之前没有ba版的布。
lirva1ds的开风格(尽早尽多的布,委托所有可以委托的事,对所有的改动和融合开放)令人惊奇的降临了。这里没有安静的、虔诚的大教堂的建造工作——相反,liu团体看起来像一个巨大的有各种不同议程和方法的乱哄哄的集市(liu归档站点接受任何人的建议和作品,并聪明的加以管理),一个一致而稳定的系统就象奇迹一般从这个集市中产生了。
这种设计风格确实能工作,并且工作得很好,这个事实确实是一个冲击。在我的研究过程中,我不仅在单个工程中努力工作,而且试图理解为什么liu世界不仅没有在一片混乱中分崩离析,反而以大教堂建造者们不可想象的度变得越来越强大。
到了1996年中,我想我开始理解了。我有一个极好的测试我的理论的机会,以一个自由软件计划的形式,我有意识的是用了市集风格。我这样做了,并取得了很大的成功。
在本文的余下部分,我将讲述这个计划的故事,我用它来明确一些自由软件高效开的格言。并不是所有这些都是从liu世界中学到的,但我们将看到liu世界给予了它们一个什么样的位置。如果我是正确的,它们将使你理解是什么使liu团体成为好软件的源泉,帮助你变得更加高效。
二邮件必须得通过
199年以前我在一个的免费的名为k的is的做技术工作,它位于sy1vai协助建立了il,并写了我们独特的多用户bbs系统——你可以1来检测一下。今天它在十九条线上三千的用户)。这个工作使我可以一天二十四时通过il的56k专线连在上,实际上,它要求我怎么做!
所以,我对irai1很熟悉。因为复杂的原因,很难在我家里的机器和il之间用sli工作。最后我终于成功了,但我现不得不时常1到1k来检查我的邮件,这真是太烦了。我所需要的是我的邮件送到sark,这样biff1会在它到达时通知我。
简单地sdai1的转送功能是不够的,因为sark并不是总在上而且没有一个静态地址。我需要一个程序通过我的sli连接把我的本地送的邮件拉过来。我知道这种东西是存在的,它们大多使用一个简单的协议(sffir1)。而且,1k的bsds操作系统已经自带了一个3服务器。
我需要一个3客户。所以我到上去找到了一个。实际上,我现了三、四个。我用了一会r1,但它却少一个明显的特征:抽取收到的邮件的地址以便正确回复。
问题是这样的:假设1k上一个叫“j”的人向我了一封邮件。如果我把它取到sark上准备回复时,我的邮件程序会很高兴地把它送给一个不存在的sark上的“j”。手工的在地址上加上“变成了一个严酷的痛苦。
这显然应是计算机替我做的事。(实际上,依据rfdai1应该做这件事)。但是没有一个现存的客户知道怎样做!于是这就给我们上了第一课:
1每个好的软件工作都开始于搔到了开者本人的痒处。
也许这应该是显而易见的(“需要是明之母”长久以来就被证明是正确的),但是软件开人员常常把他们的精力放在它们既不需要也不喜欢的程序,但在liu世界中却不是这样——这解释了为什么从liu团体中产生的软件质量都如此之高。
那么,我是否立即投入疯狂的工作中,要编出一个新的3客户与现存的那些竞争呢?才不是哪!我仔细考察了手头上的工具,问自己“那一个最接近我的需要?”因为:
2好程序员知道该写什么,伟大的程序员知道该重写(和重用)什么。
我并没有声称自己是一个伟大的程序员,可是我试着效仿他们。伟大程序员的一个重要特点是建设性的懒惰。他们知道你是因为成绩而不是努力得到奖赏,而且从一个好的实际的解决方案开始总是要比从头干起容易。
例如,liu并不是从头开始写liu的。相反的它从重用ii(一个3八6机型上的类似ui的微型操作系统)的代码和思想入手。最后所有的ii代码都消失或被彻底的重写了,但是当它们在的时候它为最终成为liu的雏形做了铺垫。
秉承同样的精神,我去寻找良好编码的现成的工具,用来作为基础。
ui世界中的代码共享传统一直对代码重用很友好(这正是为什么gu计划不管ui本身有多么保守而选取它作为基础操作系统的原因)。liu世界把这个传统推向技术极限:它有几个字节的源代码可以用。所以在liu世界中花时间寻找其他几乎足够好的东西,会比在别处带来更好的结果。
这也适合我。加上我先前现的,第二次寻找找到了9个候选者——fh,ar,gai1,g,i,r1,,ai1和u)。我先选定的是“fh”。我加入了头标重写功能,并且做了一些被作者加入他的19版中的改进。
但是几个星期之后,我偶然现了”的代码,然后现有个问题,虽然fh有一些好的原始思想比如它的守护进程模式,它只能处理3,而且编码的水平相当业余sughg是个很聪明但是经验不足的程序员,ar1的代码更好一些,相当专业和稳固,但他的程序缺少几个重要的相当容易实现的fh的特征包括我自己写的那些。
继续呢还是换一个如果换一个的话,作为得到一个更好开基础的代价,我就要扔掉我已经有的那些代码。
换一个的一个实际的动机是多协议,3是用的最广的邮局协议,但并非唯一一个,fh和其余几个没有实现,或者a,而且我还有一个为了兴趣加入iairssagassr1,最近设计的最强大的邮局协议的模糊想法。
但是我有一个更加理论化的原因认为换一下会是一个好主意,这是我在liu很久以前学到的:
3“计划好抛弃,无论如何,你会的”frd
ks,《神秘的人月》第11章
或者换句话说,你常常在第一次实现一个解决方案之后才能理解问题所在,第二次你也许才足够清楚怎样做好它,因此如果你想做好,准备好推翻重来至少一次。
好吧我告诉自己,对fh的尝试是我第一次的尝试,因此我换了一下。
当我在1996年6月25日把我第一套的补丁程序寄给ar1harris之后,我现一段时间以前他已经对基本上失去了兴趣,这些代码有些陈旧,有一些次要的错误,我有许多修改要做,我们很快达成一致,我来接手这个程序。不知不觉的,这个计划扩大了,再也不是我原先打算的在已有的客户上加几个次要的补丁而已了,我得维护整个的工程,而且我脑袋里涌动着一些念头要引起一个大的变化。
在一个鼓励代码共享的软件文化里,这是一个工程进化的自然道路,我要指出:
4如果你有正确的态度,有趣的问题会找上你的,但是ar1harris的态度甚至更加重要,他理解:
5当你对一个程序失去兴趣时,你最后的责任就是把它传给一个能干的后继者。
甚至没有商量,ar1和我知道我们有一个共同目标就是找到最好的解决方案,对我们来说唯一的问题是我能否证明我有一双坚强的手,他优雅而快的写出了程序,我希望轮到我时我也能做到。
三拥有用户的重要性
于是我继承了,同样重要的是,我继承了的用户基础,用户是你所拥有的极好的东西,不仅仅是因为他们显示了你正在满足需要,你做了正确的事情,如果加以适当的培养,他们可以成为合作开者。
ui传统另一有力之处是许多用户都是黑客,因为源优码是公开的,他们可以成为高效的黑客,这一点在liu世界中也被推向了令人高兴的极致,这对缩短调试时间是极端重要的,在一点鼓励之下,你的用户会诊断问题,提出修订建议,帮你以远比你期望快得多的度的改进代码。
6把用户当做协作开者是快改进代码和高效调试的无可争辩的方式。
这种效果的力量很容易被低估,实际上,几乎所有我们自由软件世界中的人都强烈低估了用户可以多么有效地对付系统复杂性,直到li让我们看到了这一点。
实际上,我认为li最聪明最了不起的工作不是创建了liu内核本身,而是明了liu开模式,当我有一次当着他的面表达这种观点时,他微笑了一下,重复了一句他经常说的话:“我基本上是一个懒惰的人,依靠他人的工作来获取成绩。”象狐狸一样懒惰,或者如r
hi1i所说,太懒了而不会失败。
回顾起来,在guaslis库和lis代码集中可以看到liu方法的成功,与as的内核和许多其他fsf的工具相比,lis代码库的演化是流动性的和用户驱动的,思想和原型在达到最终的稳定形式之前往往要重写三或四次,而且经常利用ir的松散合作。
实际上,我自己在fhai1之前最成功的作品要算asv模式,它是三个其他的人通过电子邮件进行的类似liu的合作,至今我只见过其中一个人ri,它是ss、rs和后来的uh”版本控制操作,它是从一个微型的、粗糙的别人写好的模式开始演化的,v开的成功不像as本身,而是因为aslis代码可以很快的通过布/测试/改进的过程。
fsf的试图把代码放入gl之下的策略有一个未曾预料到的副作用,它让fsf难以采取市集模式,因为他们认为每个想贡献二十行以上代码的人都必须得到一个授权,以使受到gl的代码免受版权法的侵扰,具有bsd和i协会的授权的用户不会有这个问题,因为他们并不试图保留那些会使人可能受到质询的权力。
四早布、常布
尽量早尽量频繁的布是liu开模式的一个重要部分,多数开人员包括我过去都相信这对大型工程来说是个不好的策略,因为早期版本都是些充满错误的版本,而你不想耗光用户的耐心。
这种信仰强化了建造大教堂开方式的必要性,如果目标是让用户尽可能少的见到错误,那你怎能不会仅仅每六个月布一次或更不经常,而且在布之间象一只狗一样辛勤“捉虫”呢as内核就是以这种方式开的,lis库,实际上却相反,因为有一些有fsf控制之外的lis库,在那里你可以独立于as布周期地找寻新的和开代码版本。
这其中最重要的是h州的1is库,预示了今天的巨大的liu库的许多特征的精神,但是我们很少真正仔细考虑我们在做什么,或者这个库的存在指出了fsf建造教堂式开模式的什么问题,1992年我曾经做了一次严肃的尝试,想把h的大量代码正式合并到as的官方lis库中,结果我陷入了政治斗争中,彻底失败了。
但是一年之后,在liu广泛应用之后,很清楚,一些不同的更加健康的东西诞生了,li的开模式正好与建造教堂方式相反,si和s11的库开始成长,推动了许多布。所有这些都是闻所未闻的频繁的内核系统的布所推动的。
li以所有实际可能的方式把它的用户作为协作开人员。
7早布、常布、听取客户的建议
li的创新并不是这个这在ui世界中是一个长期传统,而是把它扩展到和他所开的东西的复杂程度相匹配的地步,在早期一天一次布对他来说都不是罕见的!而且因为他培育了他的协作开者基础,比其他任何人更努力地充分利用了ir进行合作,所以这确实能行。
但是它是怎样进行的呢它是我能模仿的吗还是这依赖于li的独特天才
我不这样想,我承认li是一个极好的黑客我们有多少人能够做出一个完整的高质量的操作系统内核,但是liu并不是一个令人敬畏的概念上的飞跃,li不是至少还不曾是象ri或jasgs1ig一样的创新天才,在我看来,li更象一个工程天才,具有避免错误和开失败的第六感觉,掌握了现从a点到b点代价最的路径的决窍,确实,liu的整个设计受益于这个特质,并反映出li的本质上保守和简化设计的方法。
如果快的布和充分利用ir不是偶然而是li的对代价最的路径的洞察力的工程天才的内在部分,那么他极大增强了什么他创建了什么样的方法
问题回答了它自己,li保持他的黑客用户经常受到激励和奖赏:被行动的自我满足的希望所激励,而奖赏则是经常甚至每天都看到工作在进步。
li直接瞄准了争取最多的投入调试和开的人时,甚至冒代码不稳定和一旦有非常棘手的错误而失去用户基础的险,li似乎相信下面这个:
八如果有一个足够大的ba测试人员和协作开人员的基础,几乎所有的问题都可以被快的找出并被一些人纠正。
或者更不正式的讲:“如果有足够多的眼睛,所有的错误都是浅显的”群众的眼睛是雪亮的,我把这称为“li定律”。
我最初的表述是每个问题“对某些人是透明的”,li反对说,理解和修订问题的那个人不一定非是甚至往往不是先现它的人,“某个人现了问题”,他说,“另一个理解它,我认为现它是个更大的挑战”,但是要点是所有事都趋向于迅生。
我认为这是建造教堂和集市模式的核心区别,在建造教堂模式的编程模式看来,错误和编程问题是狡猾的、阴险的、隐藏很深的现象,花费几个月的仔细检查,也不能给你多大确保把它们都挑出来的信心,因此很长的布周期,和在长期等待之后并没有得到完美的版本布所引起的失望都是不可避免的。
以市集模式观点来看,在另一方面,我们认为错误是浅显的现象,或者至少当暴露给上千个热切的协作开人员,让他们来对每个新布进行测试的时候,它们很快变得浅显了,所以我们经常布来获得更多的更正,作为一个有益的副作用,如果你偶尔做了一个笨拙的修改,也不会损失太多。也许我们本不应该这样的惊奇,社会学家在几年前已经现一群相同专业的或相同无知的观察者的平均观点比在其中随机挑选一个来得更加可靠,他们称此为“d1hi效应”,li所显示的证明在调试一个操作系统时它也适用——d1hi效应甚至可以战胜操作系统内核一级的复杂度。
我受jffduky的启指出li定律可以重新表述为“调试可以并行”,jff观察到虽然调试工作需要调试人员和对应的开人员相交流,但它不需要在调试人员之间进行大量的协调,于是它就没有陷入开时遇到的平方复杂度和管理开销。
在实际中,由于重复劳动而导致的理论上的丧失效率的现象在liu世界中并不是一个大问题,“早布、常布策略”的一个效果就是利用快的传播反馈修订来使重复劳动达到最。
ks甚至做了一个与jff相关的更精确的观察:“维护一个广泛使用的程序的成本一般是其开成本的4,奇怪的是这个成本受到用户个数的强烈影响,更多的用户现更多的错误”我的强调。
更多的用户现更多的错误是因为更多的用户提供了更多测试程序的方法,当用户是协作开人员时这个效果被放大了,每个找寻错误的人都有自己稍微不同的感觉和分析工具,从不同角度来看待问题。“d1hi效应”似乎因为这个变体工作变得更加精确,在调试的情况下,这个变体同时减了重复劳动。
所以加入更多的ba测试人员虽不能从开人员的减“最深”的错误的复杂度,但是它增加了这样一种可能性,即某个人的工具和问题正好匹配,而这个错误对这个人来说是浅显的。
li也做了一些改进,如果有一些严重的错误,liu内核的版本在编号上做了些处理,让用户可以自己选择是运行上一个“稳定”的版本,还是冒遇到错误的险而得到新特征,这个战略还没被大多数liu黑客所仿效,但它应该被仿效,存在两个选择的事实让二者都很吸引人。
五什么时候玫瑰不是玫瑰
在研究了li的行为和形成了为什么它成功的理论之后,我决定在我的工程显然没有那么复杂和雄心勃勃里有意识的测试这个理论。
但我先做的事是熟悉和简化的实现非常好,但是有一种对许多程序来说没有必要的复杂性。他把代码当作核心而把数据结构当作对代码的,结果是代码非常漂亮但是数据结构设计得很特别,相当丑陋至少对以这个老lis黑客的标准来看,然而除了提高代码和数据结构设计之外,重写它还有一个目的,就是要把它演化为我彻底理解的东西,对修改你不理解的程序中的错误负责可不是一件有趣的事。
第一个月我只是在领会ar1‘s的基本设计的含义,我所做的第一个重大修改是加入了ia,我把协议机重新组织为一个通用驱动程序和三个方法表对应2、3和ia,这个前面的修改指出一个需要程序员特别是象这种没有自然的动态类型的语言记在脑中的一般原理:
9聪明的数据结构和笨拙的代码要比相反的搭配工作的更好
frd
ks也在他第11章中讲道:“让我看你的[代码],把你的数据结构]隐藏起来,我还是会迷惑;让我看看你的数据结构],那我就不需要你的代码]了,它是显而易见的”。
实际上,他说的是“流程图”和“表”,但是在三十年的术语/文化演进之后,事情还是一样的。
此时1996年9月初,在从零开始六个月后,我开始想接下来修改名字——毕竟,它已不仅仅是一个客户,但我犹豫了,因为还没有什么新的漂亮设计呢,我的版本需要有自己的特色。
当fhai1学会怎样把取到的邮件转送到s端口时,事情就完全改变了,但是先:上面我说过我决定使用这个工程来测试我关于lirua1ds所做的行为的理论,你可能会问我怎样做到这点呢以下面的方式:
1我尽早尽量频繁的布几乎从未少于每十天布一次;在密集开的时候是每天一次。
2我把每一个和我讨论fhai1的人加入一个ba表中。
3每当我布我都向ba表中的人出通告,鼓励人们参与。
4我听取ba测试员的意见,向他们询问设计决策,对他们寄来的补丁和反馈表示感谢。
这些简单的手段立即收到的回报,在工程的开始,我收到了一些错误报告,其质量足以使开者因此被杀掉,而且经常还附有补丁、我得到了理智的批评,有趣的邮件,和聪明的特征建议,这导致了:
1如果你象对待最宝贵的资源一样对待你的ba测试员,他们就会成为你最宝贵的资源。
六变成了fbs这个工程的真正转折点是harryhh1isr寄给我他写的代码草稿,他把邮件转到客户端机器的s端口,我立即意识到这个特征的可靠实现将淘汰所有其他的递送模式。
几个星期以来我一直在修改而不是改进fhai1,因为我觉得界面设计虽然有用但是太笨拙琐碎了,到处充满了太多的粗陋的细选项。
当我思考s转时我现试图做的事太多了,它被设计成既是一个邮件传输代理a也是一个本地递送代理da。使用s转,它就可以从da的事务中解脱出来而成为一个纯a,而象sdai1一样把邮件交给本地递送程序来处理。
既然端口25在所有支撑/i的平台上早已被预留,为什么还要为一个邮件传输代理的配置或为一个邮箱设置加锁的附加功能而操心呢尤其是当这意味着抽取的邮件就象一个正常的送者出的s邮件一样,而这就是我们需要的。
这里有几个教益:第一,s转的想法是我有意识地模拟li的方法以来的最大的单个回报,一个用户告诉我这个非同寻常的想法——我所需做的只是理解它的含义。
11想出好主意是好事,从你的用户那里现好主意也是好事,有时候后者更好。
很有趣的是,你很快将现,如果你完全承认你从其他人那里得到多少教益的话,整个世界将会认为所有的明都是你做出的,而你会对你的天才变得谦虚。我们可以看到这在li身上体现得多明显!当我在1997年八月的r1会议上表这个论文时,rrya11坐在前排,当我讲到上面的观点时,他激动的叫了出来:“对了!说对了!哥们!”所有的听众都哄堂大笑起来,因为他们知道同样的事情也生在r1的明者身上。
于是在同样精神指导下工程进行了几个星期,我开始不光从我的用户那儿也从听说我的系统的人那儿得到类似的赞扬,我把一些这种邮件收藏起来,我将在我开始怀疑自己的生命是否有价值时重新读读这些信。:
但是有两个更基本的,非政治性的对所有设计都有普遍意义的教益。
12最重要和最有创新的解决方案常常来自于你认识到你对问题的概念是错误的。
一个衡量fhai1成功的有趣方式是工程的ba测试人员表fghai1的朋友们的长度,在创立它的时候已经有249个成员了,而且每个星期增加两到三个。
实际上,当我在1997年5月校订它时,这张表开始因为一个有趣的原因而缩短了,有几个人请求我把他们从表中去掉,因为fhai1已经工作的如此之好,他们不需要看到这些邮件了!也许这是一个成熟的市集风格工程的生命周期的一部分。
我以前一直在解决错误的问题,把当作a和具有许多本地递送模式的da的结合物,fhai1的设计需要从头考虑为一个纯的a,做为一个普通ir邮件路径的一部分。
当你在开中碰了壁时当你现自己很难想通下一步时,那通常不是要问自己是否找到正确答案,而是要问是否问了正确问题,也许需要重新构造问题。
↑返回顶部↑