必读网 - 人生必读的书

TXT下载此书 | 书籍信息


(双击鼠标开启屏幕滚动,鼠标上下控制速度) 返回首页
选择背景色:
浏览字体:[ ]  
字体颜色: 双击鼠标滚屏: (1最慢,10最快)

大教堂与集市

埃里克·斯蒂芬·雷蒙(美)
《大教堂与市集》第一章 大教堂与市集
简介
Linux是颠覆性的,但是在五年以前(1991年)谁能想到,这些散布在世界各地的开发者仅仅依靠细细的网线相连,在业余的时间里就能开发出一套世界级的操作系统呢?至少这让我深感意外。我在上个世纪80年代中期加入GNU,作为第一批成员,至今已经在网上发布了不少开源作品。而且一些现在被广泛使用的软件(nethack,Emacs的VC和GUD模式,xlife等等)也是我正在开发或协助开发的。1993年初我接触到Linux的时候,已经致力于Unix和开源软件开发有十年之久了,至少我那时觉得自己很在行了。然而Linux却推翻了我的理论。当时,我已经宣扬小而专的工具、快速建立原型和演进式开发这些Unix概念好多年了。但却还是坚信对于一些重要的软件(操作系统和Emacs之类的大型工具),一旦项目进展到一定的复杂度之后就需要如同建设大教堂一样统筹管理:由个别绝世的能工巧匠细细雕琢——时机不到,公测不出。[1]
而李纳斯[2](尽早尽多的发布,托以所有可托付之事,并且能包容到泛滥之地步)的开发风格实在令人诧异。相比建造大教堂时的虔诚和肃穆,Linux社区更像是一个熙熙攘攘的市集:这里面混杂着不同流派和各种议程(Linux归档站点就是个绝佳的例证,任何人的作品都被收录其中)。如果一个统一而稳定的操作系统能从这里诞生的话,只能说是一个奇迹,一系列的奇迹。
事实是——这种风格不仅可行,而且运营良好。这给了我很深的触动。在摸索中,我不仅致力于个案,而且尝试探索为什么Linux世界不仅没有在混乱中分崩离析,反而以大教堂的建设者难以想像的速度茁壮成长。
到了1996年中,我开始略有所获。碰巧得到了一个验证这些理论的完美机会——我可以刻意的用市集的风格来运筹一个开源项目。我的确这么做了,而且成果斐然。接下来的章节,我将讲述这个项目的故事。并借此提炼出一些对开源开发有益的格言。它们并非都始于Linux世界,但是我们却能看到它们如何在Linux世界中得以印证。如果我是对的话,它们将帮助你准确理解是什么使Linux社区成为优秀软件的源泉。如果有幸,它们还可以助您提高效率。
译者按: 1.公测,Beta。在软件开发的测试阶段推出的第二个版本。相比第一个内测(Alpha)版本,测试人员范围更广但是只针对漏洞进行修补,而极少对主体程序进行改动。
2.李纳斯(Linus Benedict Torvalds, 李纳斯·本尼迪克特·托瓦兹),著名黑客,Linux之父,Linux内核的发明人。著名的李纳斯定理就是以其命名。
《大教堂与市集》第二章 邮件必达
自1993年起,我就在宾州西切斯特的一家提供免费网络服务的小公司CCIL(Chester County InterLink)负责技术工作。我协同创建了公司并编写了一个专用的多用户论坛程序——你可以通过telnet连接locke.ccil.org一探究竟。如今它在三十条线路上支持着近三千名用户。这使我可以每天二十四小时的通过CCIL的56K专线上网——其实,这是工作需要。我已经惯于使用网络邮件了,但不时地登录locke检查邮件实在很烦人。我所希望的是有办法能将邮件转送到我家的机器(snark)上,并在到达的时候通知我,而且可以用本地工具进行处理。
互联网默认的邮件传输协议SMTP显然不能满足我的要求,STMP是为全时在线的机器设计的,而我家的机器不可能全天在线——况且它也没有一个固定的IP。我需要一个程序,让我能在拨号之后链接到服务器上把邮件下载到本地。我知道有这种工具存在,它们大都使用一种称为POP的简单协议,现在常用的邮件客户端软件都支持这个协议,但那时,我的邮件阅读软件并不支持它。我在网上找到了三四个这样的POP3客户端软件。其中一个我用了一段时间,可是他明显缺少一个功能:抽取正确的邮件地址。
事情是这样的,如果locke上一个叫乔的人发给我一封邮件,我将其下载到snark上。可是在回复的时候我的邮件程序会高高兴兴的把信投寄给一个在snark上并不存在的乔。手工修正地址是件痛苦的事。显然这是一件应该由电脑来完成的事情,可是没有一个现存的POP软件知道如何解决。这给我们上了第一课:
1.好软件都源自解决开发者的切身之痛。
Every good work of software starts by scratching a developer's personal itch.
或许这是众所周知的(不是有句名谚叫做“需要是发明之母”吗?),可是有那么多软件开发者为了薪水把时间都消耗在他们及不喜欢又不需要的程序上了。然而这却不会发生在Linux世界,或许这就是Linux社区产品平均质量很高的原因吧?那么我是否应该疯狂的投入战斗,编写一套新的POP软件来和它们一较高下呢?打死都不干!相反,我仔细地检视我手中的东西,看看哪个最接近需求。因为:
2.优秀的程序员知道要写什么,而伟大的程序员知道要改写(和重用)什么。
Good programmers know what to write. Great ones know what to rewrite (and reuse).
我不敢自诩伟大,但是我努力效法那些伟大的程序员。他们都有一个重要的特点——建设性的懒惰,因为我们要的是结果而不是过程。从一个优质的部分接手总比你白手起家要容易的多。
以李纳斯为例,他并没有从零开始编写Linux。相反他借重了Minix的代码和理念。(Minix是一个用于个人电脑的小型类Unix操作系统)虽然Minix的全部代码最终被全部摘除或重写了,但是它毕竟为Linux充当了学步车。
出于同样的考虑,我开始寻找一个现存的有最有条理的POP程序来作为开发基础。
Unix世界共享源代码的传统让我们很容易的对它们重新加以利用。(这也是为什么尽管GNU对Unix成见很深,却依然采用Unix为基础开发操作系统的原因)而Linux世界更是把这种传统发挥到了技术的极限。在浩如烟海的Linux开放代码中花点时间来寻找一个不错的程序,总比去别处要强的多。
加上我之前用到的,第二次的搜索让我有了九个候选对象:fetchpop、PopTart、get-mail、gwpop、pimp、pop-perl、popc、popmail和upop。首先选用的是肖恩[1]的fetchpop,我对其做了一些改动并将改写邮件地址的功能加了进去。后来他把这些改动加入到了自己的1.9版本中。
几周之后,我偶然接触到了卡尔·哈里斯的popclient代码时,问题出现了。尽管fetchpop有那么多优秀的原创功能(比如他的后台程序),但是却只能支持POP3协议,而且代码不够老练(肖恩很聪明,但是缺少经验)。卡尔的代码则更好,专业而稳固。但是却缺少很多重要的功能——那些fetchpop中的妙作(包括我加入的部分)。
是继续使用fetchpop还是改用popclinent?如果转换的话,就意味着我不得不放弃已经完成的代码来换取一个更好的开发基础。
一个实际的转换动机是去支持更多协议。POP3使用最广,却不是唯一。Fetchpop和那个竞争对手同样不支持POP2、RPOP和APOP。出于好玩,我那时已经有了在其中加入IMAP(最新设计的,最强大的POP协议)的模糊想法。
其实我还有一个更正式的理由支持我更换软件,这是我在玩Linux之前就学到的:
3.“为舍弃而计划,无论如何,你都要这样做。”(弗雷德里克·布鲁克斯,《人月神话》第十一章,)[2]
“Plan to throw one away; you will, anyhow.” (Fred Brooks, The Mythical Man-Month, Chapter 11)
换言之,当你开始尝试解决一个问题之后,你通常并不知道症结所在。再次着手,或许能够技经肯綮。所以想把事情做好,你得准备“至少重来一次”。【注】
好吧,(我对自己说)对fetchpop的修改就算是我的第一次吧。于是,放弃了它。
1996年6月25日,我给卡尔寄去了第一批程序补丁。才发现他对这个程序基本失去了兴趣。代码已经乏人照料很久了,小错误流连不去,有很多改动要做。我们一拍即合,由我接手。
不经意间,工作的规模扩大了。我不再只是针对一个POP客户端进行修补,而是要负责维护整个程序。一些可能会引发变革的想法在我脑海中浮现。
在鼓励代码共享的软件文化里,这样的演进方式是自然而然的。我只是将这些原理付诸实践:
4.只要你态度正确,有趣的问题就会找上门来。
If you have the right attitude, interesting problems will find you.
而卡尔的态度更加重要,他懂得:
5.对一个项目失去兴趣的时候,你的最后责任就是找一个称职的接班人。
When you lose interest in a program, your last duty to it is to hand it off to a competent successor.
为了创造一个最佳的解决方案,我和卡尔不谋而合。唯一的问题是,我是否能证明我的能力。一旦我做到了,卡尔便优雅而迅速的交托给我。希望有一天轮到我这么做的时候,我能同样的出色。
注:
著名的计算机学家乔·本特利(Jon Bentley)在其著作《编程珠玑》(Programing Pearls)对其做了如下评注:“如果你舍弃了一个,你还会舍弃第二个”。他的话完全正确,布鲁克斯和本特利指出:不要期望一蹴而就,以一个好主意重头来过通常要比梳理一团乱麻要好的多。
译者按:
1.肖恩,Sean Oh,fetchpop的作者,书中出现的名称是Seung-Hong Oh。Sean是其英文名。有译者将其音译作“欧松宏”,我认为这个译音有失精当。因为Oh Seung Hong这三个拼写在韩英互译时是很常见的。与其对应的韩文大致是“???”,译成汉语则大致是“吴承弘”。在没有办法联系到作者本人的情况下,为了行文不出差错,我选用了其英文名。
2.The Mythical Man-Month,Frederick P. Brooks。《人月神话》,作者弗雷德里克·布鲁克斯。计算机学家,被称作“IBM 360之父”,曾获得图灵奖和美国国家技术奖——两个计算机界举足轻重的奖项。《人月神话》是其随笔集,其在书中对繁复的工程管理做了洞见的观察。在第十一章《未雨绸缪》(Plan to Throw One Away)中其提出了舍弃型原型的概念。本文引言是强调“为舍弃而计划”,“one”用来指代一个计划或者原型,我认为不能直接译为“一个”所以用了代词“它”放宽其概念。
《大教堂与市集》第三章 用户的重要性
我接手了popclient。同样重要的是,我也承继了popclient的用户基础。拥有用户是件美好的事情,他们的存在不仅仅印证了你正在供其所需,而且说明你做的还不赖。加以适当的培养,他们还能成为你的开发伙伴。
许多用户也是黑客,这是Unix传统的另一个强项,而Linux把它推向极致。因为可以获得源代码,大家的工作会更加卓有成效,这可以有效的缩短调试时间。加上一些掌声,他们会帮忙解决问题,提交改进,这总比你单枪匹马要快得多。
6.把用户当作开发伙伴,是快速改进代码和有效调试的不二法门。
Treating your users as co-developers is your least-hassle route to rapid code improvement and effective debugging.
而这所蕴含的能量很容易被低估了。我们开源世界里的所有人都没有想到,同比增加的用户可以有效地应对系统的复杂性。直到李纳斯另辟蹊径。
其实,李纳斯的睿智和最有影响的手笔并不在于他发明了Linux内核,而是创造了一种模式。有一次我当面向他表达这个见解的时候,他莞尔地说起那句口头禅:“基本上,我很懒,懒到用他人的工作换取口碑。”像狐狸一样懒惰,或许如同罗伯特·海因莱茵[1]笔下那个著名的人物一样——太懒了,才不会失败。
回顾过去,Linux方法的一个成功先例就是GNU Emacs的Lisp库和Lisp代码文档。与Emacs的C核心和其他GNU工具的大教堂模式相比,Lisp代码集则是有诸多活跃用户驱动的。创意和原型都通常要经过三四次重写才能最终成型。如同Linux,基于网络的松散协作也很频繁。
在fetchmail之前我最成功的作品要算是VC模式的Emacs了,它是我与其他三个人以互通邮件这种类似Linux的模式开发完成的,至今我也只见过其中一人——理查德·斯多曼(Richard Stallman,Emacs的作者,自由软件基金会的创始人)。其实它是由别人编写的一个微小粗糙的sccs.el模式演进而来的,后来成为SCCS、RCS和CVS的前台,并为Emacs提供“单击式”版本控制操作。与Emacs本身不同,VC模式的成功源于Emacs Lisp代码可以快捷的完成“释放/测试/改进”的循环。
Emacs的故事并不是惟一的。这种双级架构双层用户群(教堂形而上,市集形而下)的模式也被其他软件采用。比如MATLAB,一款用于数据分析的可视化商业软件。MATLAB和其他类似产品的用户一致认为,动力、热情和创造都源自其开放部分——一个可以让各色用户都来舞刀弄棒的大校场。
译者按:1.罗伯特·安森·海因莱茵(Robert Anson Heinlein),著名科幻作家。共获得了五次星云奖和七次雨果奖。文中提及人物出自其1973年出版的小说《Time Enough for Love》。
《大教堂与市集》 第四章 早发布,常发布
尽早和尽量频繁的发布是Linux开发模式的一个重要部分。包括我在内的大多数开发人员都曾一贯认为——对于一个大型工程来说这并不是个好办法。因为早期版本几乎就是问题版的同义词,而你却并不想过早地把用户的耐心消耗殆尽 。
这种信念促使人们普遍采用大教堂式的开发模式。如果首要目标是令用户尽可能少的遭遇错误,那么何不半年(或者更久)发布一次呢?这样我们就有足够的时间像只狗一样周旋其间。Emacs的C核心就是这样开发的,而Lisp库则恰恰相反——在自由软件基金会所辖以外,有很多独立的新版本或研发代码可供选择。【注1】
其中最重要的,俄亥俄州立大学的Emacs Lisp 存档,在当时就已经具有了今天Linux大型数据管理的许多精神与气质。但是我们之中少有人深思过究竟要做什么,以及这个存档的存在暴露了自由软件基金会大教堂模式的哪些问题。在1992年前后,我曾尽力想把大量的俄亥俄代码融入官方数据库,但是却在政治纠葛下半途而废了。
一年后,Linux的影响逐步扩大。显然,这要归结于一些另类不过更加有益的理念。李纳斯的开放性方针与大教堂模式大不相同。Linux的网络存档枝繁叶茂,各色发行版在坊间流传。而所有这一起都要归功于这种前所未有的核心发布模式。
以最有效的方法,李纳斯把用户视作合作伙伴:
7.早发布,常发布。并听取用户意见。
Release early. Release often. And listen to your customers.
快速发布,汲取用户反馈并不是李纳斯的创新(Unix世界历来如此),而他的创举在于将这个方法推升到了能和开发中的复杂度相匹敌的高度。早先(1991年前后)我不是没听过他那个一天之内不止一次发布核心的故事!因为他比其他任何人都辛勤的培养合作群体,促成网络协作。这是卓有成效的。
这是如何生效的?难道是源于李纳斯的天赋?
我不这么认为。无可厚非,李纳斯是个骨灰级的黑客(我们之中有几个可以从无到有创造一个企业级的操作系统内核呢?),但是Linux并不代表任何理念上的飞跃。李纳斯也不像(至少目前没有)理查德·斯多曼和詹姆斯·戈士林(NeWS和JAVA之父)那样在在设计领域天赋异禀,在我看来,他的才智更多的表现在操控和执行中。凭借着规避错误和防止陷入僵局的第六感,他能够发现解决问题的捷径。事实上,整个Linux的设计都散发出这种气质,处处体现出他质朴简洁的设计风格。
承上所述,如果快速发布和淋漓尽致的使用网络协作并非天成,而是源自李纳斯的操控天赋和对捷径的洞见。那么他究竟要把什么挥洒至极,又打算从中释放什么呢?
这样一问,答案自明。李纳斯让他的用户/黑客们不断得到激励和奖赏:激励源自参与过程中的自我实现,而奖赏则是那些持续(甚至是每天)的改进。
李纳斯直接锁定了在开发和调试中“人力—时间”绩效最大化的目标,甚至牺牲程序的稳定性以及因为难以修正的错误而流失用户也在所不惜。似乎他坚信:
8.只要有足够多的人手参与公测和开发,任何问题都会显而易见并被很快化解。
Givena large enough beta-tester and co-developer base, almost every problemwill be characterized quickly and the fix obvious to someone.
更通俗一点,就是:“足够多的眼睛,就可让所有问题浮现”,我称之为“李纳斯定律”
我最初的表述是:“(任何问题)都会被某人化解”,李纳斯却对此存有异议,他认为问题的发现和解决并不一定要由同一个人来完成,甚至可以说解决问题的通常不是发现者本人,我想这个纠正是必要的。“有人发现问题”,他说道。“其他人解决问题,而我要特别强调——发现问题才是重头戏。”在下面的章节,我们会深入探讨在调试时会发生什么。而关键是,在Linux的世界里无论发现还是修补问题都很迅速。
这就是大教堂与市集模式的区别。在修建教堂时,你所面临的错误和开发中的问题狡黠凶险、隐伏至深。哪怕几个人在几个月的时间里竭尽全力也不见得能把它们通通解决。一旦漫长的等待换来不尽如人意的产品,那么失望就在所难免了。
另一方面,站在市集的角度。你可以假设所有问题都是显而易见的——至少在上千个热情参与者的反复推敲下,它们都会变得显而易见。频繁的发布可以换取更多的修正,所以偶尔捅个大漏子也没什么大不了的!
这足可以说明问题了。如果“李纳斯定律”是错的,那么一个像Linux内核这么杂糅的东西,早该毁于一旦了。罪魁祸首自然是那些根深蒂固的错误和持续的恶性循环。换个角度,如果它是对的,也足够解释为什么Linux历来罕有错误,并且能经年累月的持续运营。
大可不必为“三个臭皮匠顶个诸葛亮”而感到诧异。多年以前,社会学家就证实:一群同样内行(或白痴)的人做出的平均预测要比其中任意一个都准确。这被称为“德尔菲效应”。[1]显然,李纳斯是把这用在操作系统调试上了。然而即使面对如同操作系统内核这样的复杂之事,“德尔菲效应”也能应对自如。【注2】
在Linux世界里,每个贡献者都是自愿参与的,这也是促成“德尔菲效应”的特别之处。早期有评论指出,这些贡献者不是随机产生的,而是要经过层层过滤。这包括:要有足够的兴趣使用软件;意图了解其运行机理;尝试自己解决遇到的问题;并且能做出实质性改进。最终产生的贡献者往往是有真材实料的家伙。
“李纳斯定律”也可以描述成“平行调试”。有时调试者可能需要和开发人员取得联系,但是他们彼此之间却不需要多少协调。故而增加开发者并不会带来成指数增长的复杂度和边际成本。
理论上,重复劳动带来的能效消耗在Linux世界一直算不上个大问题。“早发布,常发布”策略的一个结果,就是用准确及时的反馈来尽可能的减少了重复劳动。【注3】
甚至对此,布鲁克斯(《人月神话》的作者)曾做过一个非正式的论述:“一款广泛使用的软件,其维护费用是开发成本的40%以上。令人惊讶的是,其受用户影响很大,用户越多发现的错误就越多”【这是我所要强调的】
增加用户意味着增加检测程序的角度,自然发现的问题就更多。当用户参与协同开发的时候这个效应便扩大了。在纠错的时候,大家可以用不同的观察方法和分析工具,从不同视角逼近同一个问题。“德尔菲效应”便应运而生了。在这个特定的调试环境下,多样性也有助于减少重复劳动。
从开发者的角度看,更多的公测参与也许不能让最棘手的问题易于梳理。但是却能增加为解决问题找到合适人选的机会,对于这些人来说,某些问题或许称不上问题。
李纳斯还留了一手。Linux可以在出现重大缺陷的时候,为用户提供两个选择——选用上一个稳定版本或冒险体验实验版。这个策略还没有被Linux黑客普遍采用,也许他们真应该这么做。因为无论选择哪一个都能让彼此更具魅力。【注4】
注释:
1.采用市集模式的开源软件成功先例,在因特网热潮之前就出现了。所以这当然不会源自Unix和因特网传统。比如在1990年到92年初首先出现在DOS机上的info-Zip压缩工具就是一例,另外就是同样始于DOS的RBBS电子公告板系统。从1983年发展起来的强大的RBBS社团,使其至今(1999年中)都充满活力——无论其间网络邮件和文件共享技术发生了多么翻天覆地的变化。如果说info-Zip社团还或多或少的使用了网络邮件的话,那么RBBS开发则纯粹的依托于一个以TCP/IP为基础形成的在线社团。
2.对于扫清操作系统开发的复杂障碍,公开平等的审视是大有助益的,其实,这算不上是个新观点。在1956年考巴托和维萨斯基共同设计了一个名为Multics的早期分时操作系统。[2]他们希望当Multics运行良好并满足下面两个条件的时候能得以发布:首先,它要经受的起来自用户无偿地公开审视和批评。其次,当自身越来越复杂的时候,其有责任对未来的开发者做出贡献,以便令他们可以尽己所能开发出内核明晰的操作系统。换言之,就是有责任公开自己的最基础版本。
3.对于在开源开发中,为何重复劳动算不上个大问题的原因,约翰·哈斯勒(John Hasler)做过一个有趣的解释。他建议我命名为哈斯勒定律:重复劳动开销的增长趋向低于由开发团队扩大带来的指数式成本增长。也就是说,开发团队扩大所带来计划和管理成本增速要远高于重复做功的开销。
这与布鲁克斯定律并不冲突,总体而言,抚平复杂度和纠正错误的成本是与开发团队规模成平方正比增长的,然而重复做功带来的开销则是其中同比增速缓慢的一个独特环节。我们不难为此找到一个看似可信的原因:以一个既定的目标开始工作比让一群自主的开发者达成一致要简单的多,而且可以预防重复做功。但是却不能有效的阻止开发陷入无法预期的恶性循环,最终导致整个系统置身错误之中。
将李纳斯定律和哈斯勒定律结合起来,我们不难找到三种软件工程的对应模式:对于开发者不超过三人的小工程,无需领导和预设管理结构。对于中型工程,采用传统的管理模式成本则相对较低。并且可以有效的防止重复劳动,错误追踪,并且能很快的发现详细资料是否有遗漏,从而确保万无一失。
在此之上,李纳斯定律和哈斯勒定律共同说明了:对于大型工程,传统管理模式带来的问题和成本增幅,远超过预期的重复劳动的开销。而这种调动大家参与所带来的微小开销并不是一个结构上的缺陷,相反(我们看到)这能比传统方法更有力的保证错误和细节无一遗漏。在大型工程中,应用这两则定律可以让那些传统模式下的本息(沉默成本和边际成本——译者按)趋近于零。
4. Linux拆分稳定版和实验版的作法,除了分担风险之外还有一个作用——干掉发布期限。实际上,一旦程让序员同时面对刻版的功能列表和该死发布时间,软件的质量就会大打折扣。这是研发中的一个重要问题。感谢来自哈佛商学院的马可·伊恩斯蒂(Marco Iansiti)和艾伦·麦科马克(Alan MacCormack)让我明白了一个道理——放松二者任意一个,都可以让工作进程更加有效。
一个做法就是制定发布日期,但让功能列表可以变通调整。也就是说,在发布时允许舍弃部分功能。这是稳定版内核开发的基本策略;艾伦·考克斯(Alan Cox,稳定版内核的维护者)定期发布稳定版,但是不承诺何时解决某个问题或者何时添加某个实验版的新功能。
另一个做法则是,锁定开发列表但不制定发布时间。这是实验版内核开发的基本策略。我们称之为:“做完再叫醒我(wake me up when it's done)策略”。达·马可(De Marco)和利斯特(Lister)的研究表明这不仅可以提高软件质量,而且平均而言,它比任何“激进”或“保守”的策略都节省研发时间。
2000年初,我开始怀疑自己在前作(指本书的前期版本——译者按)中严重低估了这种反发布时间(做完再叫醒我)策略对于开源社区的生产力以及质量的重要性。1999年GNOME仓促1.0版的教训表明:即使是开源项目,为了赶进度而草率发布,也会严重影响软件质量。
有充分的理由可以表明:开发过程的透明化、“做完在叫醒我”的策略以及开发者自主选择研发对象的方法。是影响开源项目质量的三个同等重要的作用力。
译者按:
1.德尔菲效应, Delphi effect。德尔菲(Delphi)是希腊古都,宏伟的阿波罗(Apollo,太阳神)神殿便座落于此。相传阿波罗经常在此宣布神谕,而在决断之前会广泛争取意见。故而这里成为古希腊先哲聚集论道的场所。20世纪中期,美国军方和兰德(RAND)公司合作开展国防项目——“德尔菲项目”。顾名思义,其着重采用广泛收集观点意见的方法,从而产生了“德尔非法”(Delphi method)。日后“德尔菲法”被广泛应用于工程和管理领域,形成了“立论-驳论-综述”的三段式方法。
本书中的“德尔菲效应”则是作者的创造。德尔菲法强调广泛征集专家的建议。而作者则并不认为必须专家参与,而且参与者的广泛度和涵盖面都远超过德尔菲法。德尔菲法是一种方法,众多专家参与,是其前提条件。而德尔菲效应则是强调一种广泛平等参与所带来的结果。
简而言之,我认为这就是我们中国人说的“兼听则明,偏信则暗”。
2.考巴托:费尔南多·考巴托(Fernando J. Corbató)杰出的计算机学家,1990年图灵奖的得主。
维萨斯基:维克托·A·维萨斯基(Victor A. Vyssotsky)著名数学家、计算机学家。
二人曾共同设计了Multics的内核,在该计划停止之后,由贝尔实验室的工程师以C语言为基础借此开发而成了Unix。
《大教堂与市集》 第五章 要多少只眼来驯服复杂
从宏观上,可以说市集风格大大加速了调试和代码演进,但是如果想从微观(开发者和测试者日复一日的工作中)上,准确理解这是如何和怎样起到作用的,却又是另一回事了。在本章中(作于本书初版后三年,采纳了阅读本书,并身体力行的开发人员的意见),我们将关注其背后的机理,对于技术不感兴趣的读者可以安心的跳到下一章。
理解问题的一个关键在于认清如下的重要事实,那就是那些对源代码知之甚少的用户所提交的错误报告通常派不上大用场。因为他们一般只看到表面症状。在提交错误报告的时候,习惯从自身环境出发,这样(一)会忽视重要的背景数据,(二)通常会遗漏重现错误的关键步骤。
更深层的问题是,开发者和测试者的思维模式不同。测试者是由表及里的看问题,而开发者则是自内而外。在封闭源代码的开发环境里,他们被各自的角色羁绊,往往各说各话而且认为对方很难沟通。
开源开发打破了这种束缚。基于源代码,测试者和开发者可以很容易建立一个统一的模型,并借此有效沟通。仅仅描述表面症状的问题报告和深入源代码基础抽象模型的报告,对于开发者而言作用是截然不同的。
在代码层,即使一个不完整的提示性错误描述,都可以让它们在大多数情况下得以修正。比如当某个公测人员指出:“在某某行存在边界问题”,甚至只是说出“在某某条件下,变量溢出”的时候。通常进行一次对于问题代码的快速扫描就足以锁定成因,加以修复了。
所以,如果公测人员和核心开发者都对代码心中有数,那么沟通和协作就很容易展开。这就意味着节省核心开发者的时间,即使协作者众多。
另一个节约开发者时间的方法源自典型的开源通讯结构。我在文中使用了“核心开发者”一词,这有别于“项目核心”和“项目外延”。(“项目核心”一般很小;通常包括一到三个核心开发者,当然如果只有一人也不足为怪;“项目外延”则通常包括数以百计的“公测人员”和“贡献者”)
正如布鲁克斯定律所言传统软件开发结构下的根本问题是:“为已经延期的项目增添人手会让它拖的更久。”通俗的讲,布鲁克斯定律昭示了:项目的复杂度和通讯成本会以开发人数为基础,呈现平方指数的增长态势,而绩效则仅能直线上升。
经验证实,错误大多集中在(不同人编写的)代码的接口处,而沟通/协调成本则会随着人员交流渠道的增加而增加,这就是布鲁克斯定律建立的基础。然而问题也会随着开发者沟通渠道的增多而增加,后者恰好等于开发人数的平方。(更确切地说,是遵循N*(N-1)/2公式,其中N代表开发者人数)
布鲁克斯定律(对于开发团队过大所导致的令人担忧的结果)的分析是基于一个潜在假设的:即项目必须采用全向连通的通讯结构,也就是说每个人都能与其他任何人取得联系。然而在开源项目中,外延开发是可以分离的平行子环节,彼此关联甚少。代码变动和错误报告都流经项目的核心团队,只有在那里我们才需要担负“布鲁克斯式”的管理成本。
代码层的错误报告对开发大有助益的原因还有很多,然而它们都围绕着一个事实。那就是:同一个错误在不同的操作习惯和环境下会表现出不同的症状。这类问题通常复杂隐蔽,难以重现和静态捕捉,它们正是造成软件长期问题的祸根。(比如动态内存管理出错或者随机窗口中断的影响)
一则源自测试者的(源代码层)试探性描述(例如“我觉得1250行附近像是有个信号处理窗口”或者“你在哪把缓存清零了?”),就可能会成为“当局者迷”的开发者同时解决六七个不同表象问题的关键线索。我们往往很难为五花八门的症状找到对应的错误,但是只要你发布的够频繁就无需为此担忧。因为其他协作者会很快的去查看自己提交的问题是否已经被修正了。多数情况下,源代码层的错误报告可以让许多问题没有经过特定修补就消失殆尽。
对于复杂多变的错误,从表面症状探索其成因的途径通常也很多。而对开发者和测试者而言,走哪条路则取决于他们自身所在的环境,而且也可能因为时间而产生一些无法预期的变化。实际上,开发者和测试者在为症状寻找病因的时候,都可以看作是对程序某部分运行状态的“半随机”取样。错误越是隐蔽复杂,取样对症的成功率也就越低。
对于简单易于重现的错误,重音应该落在“半”而不是“随机”上;此时,调试技巧和对代码以及其结构的熟识能派上大用场。然而对于复杂的错误,重音则转向“随机”。因为在这种情况下,众人多管齐下比少数人循序渐进要强的多——即使这“少数人”的平均水品很高。
如果挖掘错误的途径不一,很难凭表面现象预测的话,并行纠错的效果就很明显了。一个循序渐进的开发者可能一开始就选择了一条复杂的途径,当然他也可能一开始就选择到了简单的途径。让我们换一个角度,如果软件发布的够及时,那么众人就可以多管齐下。他们其中很可能有人立即就能找到一条快捷的途径,所以在极短的时间里就能修复问题。项目的维护人员看到改进,于是发布新版本。这样,那些通过其他困难途径探索同一个错误成因的人就可以在浪费掉更多时间之前停下来。【注1】
注释:
1. 根据为我提供不同难易追踪途径的读者的推测,这种对多表象错误的追踪的复杂度呈“指数”分布(我理解为高斯或者泊松分布,而且这听上去很有道理)。要是能通过实证绘出类似分布曲线的话,绝对很有价值。假如其与等概率分布平行线大相径庭,那么即使独自开发也应该努力效仿市集模式。也就是限定追踪问题的成因的时间,如果在限定时间内没有结果,那么就跳转到下一问题。坚持有时不见得是件好事……
《大教堂与市集》 第六章 花香何曾随名去?
1038个读者 翻译: Angelo 08/29/2007 原文 引用 双语对照及眉批
在研究了李纳斯的作法,并得到他何以成功的理论之后。我决定在我的新项目中(当然没有Linux那么复杂和雄心勃勃)有意地尝试这些理论。
但是我首先要对popclient做大幅的重写和简化。卡尔·哈里斯的代码很扎实,但是却如同大多C程序设计师一样,有种不必要的繁琐。他把代码置于核心,而数据结构作为其支撑。结果代码很漂亮,而数据结构就很特别了,甚至可以说很缭乱了。(至少就LISP老手的标准而言是这样的)
除了改进代码和数据结构,我的重写还有另一层目的,就是要把它演进成一个我完全理解的东西。因为要是你不能对程序了如指掌,维护起来可就不好玩了。
在最初的一个月里,我只是遵循卡尔的设计理念。我所作的第一个重要改变是加入了对IMAP的支持。做法是:把原来的协议支持部分改写成一个通用驱动和三个可调用的方发表(分别针对POP2、POP3和IMAP)。这些变动都阐明了一个程序员需要铭记在心的通用原则(特别是对于像C这样本身不支持动态类型的语言):
9.精巧的数据结构即使搭配笨拙的程序代码,也比精巧代码加笨拙结构的组合要强得多。
Smart data structures and dumb code works a lot better than the other way around.
布鲁克斯在《人月神话》的第九章中写道:“只给我看你的工作流程却隐藏表单,我将仍然一头雾水。但是如果你给我展示表单,或许不需要流程图,就能柳暗花明了。”[1]哪怕历经三十年的文化和术语变迁,这个观点依旧正确。
这时(1996年9月初,开工后大约六周),我开始考虑要给软件换个名字了。因为毕竟它已经不仅仅是个POP客户端了。但是我在犹豫,因为设计上没有什么新突破,我的popclient需要独具一格。
当popclient学会如何将收取到的邮件再通过本机SMTP端转发的时候,这一切迅速改变了。这个容后再表。首先,我之前说过要在开发过程中验证李纳斯成功的理论,那么(你也会问)我是怎么做到的呢?
* 我早发布,常发布(从未低于十天一次,在高强度的开发周期则每天一次)。
* 我把每个曾和我讨论fetchmail的人都列入公测名单。
* 每当新版本发布,我都会不厌其烦的给公测名单里的每个人寄送一份,并鼓励其参与。
* 我听取公测人员的意见,在设计上征求他们的看法。并且当他们寄回补丁和反馈的时候,给予鼓励。
这些简单的方法立竿见影。在项目一开始,我就收到了很多能让大多数程序员垂涎三尺的高质量错误报告,而且经常还附带不错的修补方法。我还收到过深刻的评论、支持者的来信,高明的功能建议。这一切都证明:
10.如果你把公测参与者作为最宝贵的资源来对待,那么他们就会成为你最宝贵的资源。
If you treat your beta-testers as if they're your most valuable resource, they will respond by becoming your most valuable resource.
这个项目庞大的公测名单(我称之为“fetchmail之友”)成为衡量fetchmail成功的重要标准。在我最后一次修订本书(2000年11月)的时候,已经有了287个成员,而且每周还要增加两到三名。
实际上,在1997年5月下旬我改写本书的时候发现,发现出于一个有趣的原因,当人数逼近300峰值时就会开始流失成员。一些人要求我把他们从名单中去掉,因为fetchmail对他们而言已经近乎完美了,所以他们不再需要收到通讯了。或许对于一个成熟的市集型项目,这是其正常生命周期的一部分吧。
译者按:
题解:本章原题为“When Is a Rose Not a Rose?”,化典自莎士比亚名句“A Rose, by any other name, would smell as sweet.”(即使玫瑰不再叫做玫瑰,其依然香醇如故),作者这里的反问是说,即使软件的名字变了但是其优良的质量不会变。至于其名称和质量究竟变与没变,将在下文见分晓。
1.其中原文是:“Show me your flowchart and conceal your tables, and I shall continue to be mystified. Show me your tables, and I won't usually need your flowchart; it'll be obvious.”在计算机领域flowchart指流程、运作机制、发生过程、在此处可以理解为程序代码。而table则指数据的有序排列,这里可以理解为数据结构。《人月神话》是软件工程方法概论;而且布鲁克斯在写作的时候,现在的计算机词汇还没有产生,比如数据结构(data structures)的说法大致是与其写作同期(1968年)才开始被广泛使用的。所以作者说“历经三十年的文化和术语变迁”。
《大教堂与市集》 第七章 Popclient变成了Fetchmail
项目的真正转折点来自一份哈利·豪切斯的草拟程序,通过它我们可以将邮件转发至客户机的SMTP端。几乎在收到程序的同时,我就意识到,这个功能会让其他的邮件传送模式都成为历史。
我曾用几周的时间摆弄fetchmail,当时总觉得虽然界面还能用但是却不够漂亮,到处是用处不大的选项。“将收取到的邮件归档”或者“标准输出”选项尤其让人心烦,可我却说不出个所以然来。
(如果你对网络邮件的技术细节不感兴趣,那么就可以安心的略过下面两段。)
当我考虑加入SMTP转发的时候,才发现popclient包揽了太多的事情。它身兼两职——既是一个邮件传输工具(MTA)又是一个本地投寄工具(MDA)。但是如果有了SMTP转发功能,它就可以摆脱MDA的工作。像sendmail一样专注于MTA并把邮件的本地投寄工作交给其他软件。
几乎每个支持TCP/IP的平台都预留了25号端口,那么何必去折腾复杂的代理设置或者“添加-锁定”本地邮箱呢?特别是,这样可以保证收到的邮件看上去就和一封直接投寄的普通SMTP邮件一样。这才是我们想要的!
(承前段……)
就算你没看懂前面的技术细节,这里还是有几条值得学习的重要经验。首先,这个SMTP的创意是我效法李纳斯的最大收获。用户提供好的创意——而我要做的仅仅是理解它的含义。
11.自主创意很好,能认可源自用户的点子也不错。有时借笔生花更具成效。
The next best thing to having good ideas is recognizing good ideas from your users. Sometimes the latter is better.
有趣的是,你会很快发现,即使你谦卑地坦陈别人为此做出多大的贡献,外界也不会这么看。大多数人认为是你创造了一切,而你只是为自己的天赋表示出适当的谦虚。李纳斯就是个生动的例子!
(1997年8月,我在第一届Perl大会上发言时,杰出的黑客拉里·沃尔正坐在前排。当我讲到上面那句的时候,他醍醐灌顶般的叫出声来:“说下去,说下去,哥们!”引得哄堂大笑。因为大家知道,这一点对于Perl的发明人也不例外。)[1]
在以同样的精神将项目运营了几周后,我开始收到类似的褒奖。不仅来自我的用户,而且来自对此有所耳闻的人。其中一些邮件被我收藏起来了,万一哪天我开始怀疑我生命的意义了,就翻出来看看:-)。
12.通常,当你确信自己在解决一个错误问题的时候,会激发最具突破和创造力的方案。
Often, the most striking and innovative solutions come from realizing that your concept of the problem was wrong.
把popclient开发成一个组合软件(作为MTA兼MDA,让他支持五花八门的本地投寄模式),实际上等于在尝试解决一个错误的问题。fetchmail应该被重新设计为一个纯粹的MTA,作为常规SMTP邮件传输路径的一部分。
当你在开发中碰壁(绞尽脑汁也无法做出下一个补丁)的时候,通常应该问问自己:“我是否找到了正确的答案?”或者“我是不是找对了问题?”。也许有些问题需要重新定义。
好,我这就重新定义我的问题。显然,正确的做法是:(1)在主驱动中加入SMTP转发支持,(2)把它设置为默认模式,(3)最后,抛弃所有其他传输模式,尤其是“本地归档”和“标准输出”两项。
第三步让我踌躇颇久,因为担心会流失依赖此模式的老用户。理论上,他们可以立即使用forward格式文件或者非sendmail的类似功能来达到同样的效果。但实践中,这种转变大费周章。
一旦真这么做了,我发现好处非明显。驱动代码中的症结就此消失,配置选项也大大简化了。再不需要围着系统的MDA和用户的本机邮箱打转了,也不需要为操作系统是否支持归档文件锁定而伤脑筋了。
而且,惟一可能出现邮件丢失的情况也没有了。过去,假设你指定了邮件归档路径,而恰好磁盘满了话,你的邮件就没了。而这在SMTP转发中不会出现。因为除非传送完成或至少已经暂入缓存了,不然SMTP接收端不会发送确认信号。
同时,性能也提高了(尽管这不是你运行一次就能感觉到的)。另外值得一提的是,用户手册也简化了许多。
下一页 尾页 共2页
返回书籍页