歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux綜合 >> Linux資訊 >> Linux文化

大教堂與市集


說明:
本文的作者Eric Raymond是Open Source Software領域的領袖,這方面許多
新的思想正是從他那兒產生的,同時他也是UNIX上最流行的Email軟件Fetchmail
的作者。
下面這篇文章有點兒長,然而它是值得你去耐心把它讀完的。文章以Fetchmail
為例,討論了Internet上集市風格的開發方式。
我們應該感謝HansB,是他把這篇長文章翻譯成了中文。
Eric的主頁地址在:http://www.tuxedo.org/~esr/

-------------------------------------------------------------------------

一. 大教堂和市集

  Linux的影響是非常巨大的。甚至在5年以前,有誰能夠想象一個世界級的操
作系統能夠僅僅用細細的Internet連接起來的散布在全球的幾千個開發人員有以業
余時間來創造呢?
我當然不會這麼想。在1993年早期我開始注意Linux時,我已經參與Unix
和自由軟件開發達十年之久了。我是八十年代中期GNU最早的幾個參與者之一。我
已經在網上發布了大量的自由軟件,開發和協助開發了幾個至今仍在廣泛使用的
程序(Nethack,Emacs VC和GND模式,xlife等等)。我想我知道該怎樣做。

  Linux推翻了許多我認為自己明白的事情。我已經宣揚小工具、快速原型和演
進式開發的Unix福音多年了。但是我也相信某些重要的復雜的事情需要更集中化的,
嚴密的方法。我相信多數重要的軟件(操作系統和象Emacs一樣的真正大型的工具)
需要向建造大教堂一樣來開發,需要一群於世隔絕的奇才的細心工作,在成功之前
沒有beta版的發布。
Linus Torvalds的開發風格(盡早盡多的發布,委托所有可以委托的事,對所
有的改動和融合開放)令人驚奇的降臨了。這裡沒有安靜的、虔誠的大教堂的建造
工作——相反,Linux團體看起來像一個巨大的有各種不同議程和方法的亂哄哄的
集市(Linux歸檔站點接受任何人的建議和作品,並聰明的加以管理),一個一致
而穩定的系統就象奇跡一般從這個集市中產生了。

  這種設計風格確實能工作,並且工作得很好,這個事實確實是一個沖擊。在我
的研究過程中,我不僅在單個工程中努力工作,而且試圖理解為什麼Linux世界不
僅沒有在一片混亂中分崩離析,反而以大教堂建造者們不可想象的速度變得越來越
強大。

  到了1996年中,我想我開始理解了。我有一個極好的測試我的理論的機會,
以一個自由軟件計劃的形式,我有意識的是用了市集風格。我這樣做了,並取得了
很大的成功。

在本文的余下部分,我將講述這個計劃的故事,我用它來明確一些自由軟件高
效開發的格言。並不是所有這些都是從Linux世界中學到的,但我們將看到Linux世
界給予了它們一個什麼樣的位置。如果我是正確的,它們將使你理解是什麼使Linux
團體成為好軟件的源泉,幫助你變得更加高效。

二. 郵件必須得通過

  1993年以前我在一個小的免費訪問的名為Chester County InterLink的ISP
的做技術工作,它位於Pennsylvania的West Chester。(我協助建立了CCIL,並寫了
我們獨特的多用戶BBS系統——你可以telnet到locke.ccil.org來檢測一下。今天它
在十九條線上支持三千的用戶)。這個工作使我可以一天二十四小時通過CCIL的56K
專線連在網上,實際上,它要求我這麼做!

  所以,我對Internet email很熟悉。因為復雜的原因,很難在我家裡的機器
(snark.thyrsus.com)和CCIL之間用SLIP工作。最後我終於成功了,但我發現不
得不時常telnet到locke來檢查我的郵件,這真是太煩了。我所需要的是我的郵件
發送到snark,這樣biff(1)會在它到達時通知我。

  簡單地sendmail的轉送功能是不夠的,因為snark並不是總在網上而且沒有一
個靜態地址。我需要一個程序通過我的SLIP連接把我的本地發送的郵件拉過來。
我知道這種東西是存在的,它們大多使用一個簡單的協議POP(Post Office
Protocol)。而且,locke的BSD/OS操作系統已經自帶了一個POP3服務器。

  我需要一個POP3客戶。所以我到網上去找到了一個。實際上,我發現了三、
四個。我用了一會pop-perl,但它卻少一個明顯的特征:抽取收到的郵件的地址
以便正確回復。

  問題是這樣的:假設locke上一個叫“joe”的人向我發了一封郵件。如果我
把它取到snark上准備回復時,我的郵件程序會很高興地把它發送給一個不存在的
snark上的“joe”。手工的在地址上加上“@ccil.org”變成了一個嚴酷的痛苦。

  這顯然應是計算機替我做的事。(實際上,依據RFC1123的5.2.18節,
sendmail應該做這件事)。但是沒有一個現存的POP客戶知道怎樣做!於是這就給
我們上了第一課:
  1.每個好的軟件工作都開始於搔到了開發者本人的癢處。
也許這應該是顯而易見的(“需要是發明之母”長久以來就被證明是正確的),
但是軟件開發人員常常把他們的精力放在它們既不需要也不喜歡的程序,但在
Linux世界中卻不是這樣——這解釋了為什麼從Linux團體中產生的軟件質量都如
此之高。

  那麼,我是否立即投入瘋狂的工作中,要編出一個新的POP3客戶與現存的那
些競爭呢?才不是哪!我仔細考察了手頭上的POP工具,問自己“那一個最接近我
的需要?”因為:
  2.好程序員知道該寫什麼,偉大的程序員知道該重寫(和重用)什麼。

  我並沒有聲稱自己是一個偉大的程序員,可是我試著效仿他們。偉大程序員
的一個重要特點是建設性的懶惰。他們知道你是因為成績而不是努力得到獎賞,
而且從一個好的實際的解決方案開始總是要比從頭干起容易。

  例如,Linux並不是從頭開始寫Linux的。相反的它從重用Minix(一個386機
型上的類似Unix的微型操作系統)的代碼和思想入手。最後所有的Minix代碼都消
失或被徹底的重寫了,但是當它們在的時候它為最終成為Linux的雛形做了鋪墊。

  秉承同樣的精神,我去尋找良好編碼的現成的POP工具,用來作為基礎。

  Unix世界中的代碼共享傳統一直對代碼重用很友好(這正是為什麼GNU計劃不
管Unix本身有多麼保守而選取它作為基礎操作系統的原因)。Linux世界把這個傳
統推向技術極限:它有幾個T字節的源代碼可以用。所以在Linux世界中花時間尋
找其他幾乎足夠好的東西,會比在別處帶來更好的結果。

  這也適合我。加上我先前發現的,第二次尋找找到了9個候選者——fetchPOP
,PopTart,get-mail,gwpop,pimp,pop-perl,popc,popmail 和 upop)。我
首先選定的是“fetchpop”。我加入了頭標重寫功能,並且做了一些被作者加入
他的1.9版中的改進。

  但是幾個星期之後,我偶然發現了Carl Harris寫的“popclient”的代碼,
然後發現有個問題,雖然fetchpop有一些好的原始思想(比如它的守護進程模式),
它只能處理pop3,而且編碼的水平相當業余(Seung-Hong是個很聰明但是經驗不足
的程序員),Carl的代碼更好一些,相當專業和穩固,但他的程序缺少幾個重要的
相當容易實現的fetchpop的特征(包括我自己寫的那些)。

  繼續呢還是換一個? 如果換一個的話,作為得到一個更好開發基礎的代價,
我就要扔掉我已經有的那些代碼。

  換一個的一個實際的動機是支持多協議,pop3是用的最廣的郵局協議,但並
非唯一一個,Fetchpop和其余幾個沒有實現POP2.RPOP,或者APOP,而且我還有一
個為了興趣加入IMAP(Internet Message Access Protocol,最近設計的最強大的
郵局協議)的模糊想法。

  但是我有一個更加理論化的原因認為換一下會是一個好主意,這是我在Linux
很久以前學到的:
 3.“計劃好拋棄,無論如何,你會的”(Fred Brooks,《神秘的人月》第11章)

  或者換句話說,你常常在第一次實現一個解決方案之後才能理解問題所在,
第二次你也許才足夠清楚怎樣做好它,因此如果你想做好,准備好推翻重來至少
一次。

  好吧(我告訴自己),對fetchpop的嘗試是我第一次的嘗試,因此我換了一下。

  當我在1996年6月25日把我第一套popclient的補丁程序寄給Carl Harris之
後,我發現一段時間以前他已經對popclient基本上失去了興趣,這些代碼有些陳
舊,有一些次要的錯誤,我有許多修改要做,我們很快達成一致,我來接手這個
程序。不知不覺的,這個計劃擴大了,再也不是我原先打算的在已有的pop客戶上
加幾個次要的補丁而已了,我得維護整個的工程,而且我腦袋裡湧動著一些念頭
要引起一個大的變化。

  在一個鼓勵代碼共享的軟件文化裡,這是一個工程進化的自然道路,我要指
出:
 4. 如果你有正確的態度,有趣的問題會找上你的,但是Carl Harris的態度甚
至更加重要,他理解:
 5.當你對一個程序失去興趣時,你最後的責任就是把它傳給一個能干的後繼者。

  甚至沒有商量,Carl和我知道我們有一個共同目標就是找到最好的解決方
案,對我們來說唯一的問題是我能否證明我有一雙堅強的手,他優雅而快速的寫
出了程序,我希望輪到我時我也能做到。

三. 擁有用戶的重要性

  於是我繼承了popclient,同樣重要的是,我繼承了popclient的用戶基礎,
用戶是你所擁有的極好的東西,不僅僅是因為他們顯示了你正在滿足需要,你做
了正確的事情,如果加以適當的培養,他們可以成為合作開發者。

  Unix傳統另一有力之處是許多用戶都是黑客,因為源優碼是公開的,他們可
以成為高效的黑客,這一點在Linux世界中也被推向了令人高興的極致,這對縮短
調試時間是極端重要的,在一點鼓勵之下,你的用戶會診斷問題,提出修訂建
議,幫你以遠比你期望快得多的速度的改進代碼。

 6. 把用戶當做協作開發者是快速改進代碼和高效調試的無可爭辯的方式。

  這種效果的力量很容易被低估,實際上,幾乎所有我們自由軟件世界中的人
都強烈低估了用戶可以多麼有效地對付系統復雜性,直到Linus讓我們看到了這一
點。

  實際上,我認為Linus最聰明最了不起的工作不是創建了Linux內核本身,而
是發明了Linux開發模式,當我有一次當著他的面表達這種觀點時,他微笑了一
下,重復了一句他經常說的話:“我基本上是一個懶惰的人,依靠他人的工作來
獲取成績。”象狐狸一樣懶惰,或者如Robert Heinlein所說,太懶了而不會失
敗。

  回顧起來,在GNU Emacs Lisp庫和Lisp代碼集中可以看到Linux方法的成功,
與Emacs的C內核和許多其他FSF的工具相比,Lisp代碼庫的演化是流動性的和用戶
驅動的,思想和原型在達到最終的穩定形式之前往往要重寫三或四次,而且經常
利用Internet的松散合作。

  實際上,我自己在fetchmail之前最成功的作品要算Emacs VC模式,它是三個
其他的人通過電子郵件進行的類似Linux的合作,至今我只見過其中一個人
(Richard Stallman),它是SCCS、RCS和後來的CVS的前端,為Emacs提供“one-
touch”版本控制操作,它是從一個微型的、粗糙的別人寫好的sccs.el模式開始
演化的,VC開發的成功不像Emacs本身,而是因為Emacs Lisp代碼可以很快的通過
發布/測試/改進的過程。

  (FSF的試圖把代碼放入GPL之下的策略有一個未曾預料到的副作用,它讓FSF
難以采取市集模式,因為他們認為每個想貢獻二十行以上代碼的人都必須得到一
個授權,以使受到GPL的代碼免受版權法的侵擾,具有BSD和MITX協會的授權的用
戶不會有這個問題,因為他們並不試圖保留那些會使人可能受到質詢的權力)。

 四. 早發布、常發布

  盡量早盡量頻繁的發布是Linux開發模式的一個重要部分,多數開發人員(包
括我)過去都相信這對大型工程來說是個不好的策略,因為早期版本都是些充滿錯
誤的版本,而你不想耗光用戶的耐心。
這種信仰強化了建造大教堂開發方式的必要性,如果目標是讓用戶盡可能少
的見到錯誤,那你怎能不會僅僅每六個月發布一次(或更不經常),而且在發布之
間象一只狗一樣辛勤“捉蟲”呢? Emacs C內核就是以這種方式開發的,Lisp庫,
實際上卻相反,因為有一些有FSF控制之外的Lisp庫,在那裡你可以獨立於Emacs
發布周期地找尋新的和開發代碼版本。

  這其中最重要的是Ohio州的elisp庫,預示了今天的巨大的Linux庫的許多特
征的精神,但是我們很少真正仔細考慮我們在做什麼,或者這個庫的存在指出了
FSF建造教堂式開發模式的什麼問題,1992年我曾經做了一次嚴肅的嘗試,想把
Ohio的大量代碼正式合並到Emacs的官方Lisp庫中,結果我陷入了政治斗爭中,徹
底失敗了。

  但是一年之後,在Linux廣泛應用之後,很清楚,一些不同的更加健康的東西
誕生了,Linus的開發模式正好與建造教堂方式相反,Sunsite和tsx-11的庫開始
成長,推動了許多發布。所有這些都是聞所未聞的頻繁的內核系統的發布所推動
的。

  Linus以所有實際可能的方式把它的用戶作為協作開發人員。

 7. 早發布、常發布、聽取客戶的建議
  Linus的創新並不是這個(這在Unix世界中是一個長期傳統),而是把它擴展到
和他所開發的東西的復雜程度相匹配的地步,在早期一天一次發布對他來說都不
是罕見的!而且因為他培育了他的協作開發者基礎,比其他任何人更努力地充分利
用了Internet進行合作,所以這確實能行。

  但是它是怎樣進行的呢?它是我能模仿的嗎?還是這依賴於Linus的獨特天才?

  我不這樣想,我承認Linus是一個極好的黑客(我們有多少人能夠做出一個完
整的高質量的操作系統內核?),但是Linux並不是一個令人敬畏的概念上的飛躍,
Linus不是(至少還不曾是)象Richard stallman或James Gosling一樣的創新天
才,在我看來,Linus更象一個工程天才,具有避免錯誤和開發失敗的第六感覺,
掌握了發現從A點到B點代價最小的路徑的決竅,確實,Linux的整個設計受益於這
個特質,並反映出Linus的本質上保守和簡化設計的方法。

  如果快速的發布和充分利用Internet不是偶然而是Linus的對代價最小的路徑
的洞察力的工程天才的內在部分,那麼他極大增強了什麼?他創建了什麼樣的方法?

  問題回答了它自己,Linus保持他的黑客用戶經常受到激勵和獎賞:被行動的
自我滿足的希望所激勵,而獎賞則是經常(甚至每天)都看到工作在進步。

  Linus直接瞄准了爭取最多的投入調試和開發的人時,甚至冒代碼不穩定和一
旦有非常棘手的錯誤而失去用戶基礎的險,Linus似乎相信下面這個:
 8. 如果有一個足夠大的beta測試人員和協作開發人員的基礎,幾乎所有的問題
都可以被快速的找出並被一些人糾正。

  或者更不正式的講:“如果有足夠多的眼睛,所有的錯誤都是淺顯的”(群眾
的眼睛是雪亮的),我把這稱為“Linus定律”。

  我最初的表述是每個問題“對某些人是透明的”,Linus反對說,理解和修訂
問題的那個人不一定非是甚至往往不是首先發現它的人,“某個人發現了問題”,
他說,“另一個理解它,我認為發現它是個更大的挑戰”,但是要點是所有事都趨
向於迅速發生。

  我認為這是建造教堂和集市模式的核心區別,在建造教堂模式的編程模式看
來,錯誤和編程問題是狡猾的、陰險的、隱藏很深的現象,花費幾個月的仔細檢
查,也不能給你多大確保把它們都挑出來的信心,因此很長的發布周期,和在長
期等待之後並沒有得到完美的版本發布所引起的失望都是不可避免的。

  以市集模式觀點來看,在另一方面,我們認為錯誤是淺顯的現象,或者至少
當暴露給上千個熱切的協作開發人員,讓他們來對每個新發布進行測試的時候,
它們很快變得淺顯了,所以我們經常發布來獲得更多的更正,作為一個有益的副
作用,如果你偶爾做了一個笨拙的修改,也不會損失太多。也許我們本不應該這
樣的驚奇,社會學家在幾年前已經發現一群相同專業的(或相同無知的)觀察者的
平均觀點比在其中隨機挑選一個來得更加可靠,他們稱此為“Delhpi效應”,
Linus所顯示的證明在調試一個操作系統時它也適用——Delphi效應甚至可以戰勝
操作系統內核一級的復雜度。

  我受Jeff Dutky (dutky @ wam.umd.edu)的啟發指出Linus定律可以重新表述
為“調試可以並行”,Jeff觀察到雖然調試工作需要調試人員和對應的開發人員
相交流,但它不需要在調試人員之間進行大量的協調,於是它就沒有陷入開發時
遇到的平方復雜度和管理開銷。
在實際中,由於重復勞動而導致的理論上的喪失效率的現象在Linux世界中並
不是一個大問題,“早發布、常發布策略”的一個效果就是利用快速的傳播反饋
修訂來使重復勞動達到最小。

  Brooks甚至做了一個與Jeff相關的更精確的觀察:“維護一個廣泛使用的程
序的成本一般是其開發成本的40%,奇怪的是這個成本受到用戶個數的強烈影響,
更多的用戶發現更多的錯誤”(我的強調)。
更多的用戶發現更多的錯誤是因為更多的用戶提供了更多測試程序的方法,
當用戶是協作開發人員時這個效果被放大了,每個找尋錯誤的人都有自己稍微不
同的感覺和分析工具,從不同角度來看待問題。“Delphi效應”似乎因為這個變
體工作變得更加精確,在調試的情況下,這個變體同時減小了重復勞動。

  所以加入更多的beta測試人員雖不能從開發人員的P.O.V中減小“最深”的錯
誤的復雜度,但是它增加了這樣一種可能性,即某個人的工具和問題正好匹配,
而這個錯誤對這個人來說是淺顯的。

  Linus也做了一些改進,如果有一些嚴重的錯誤,Linux內核的版本在編號上
做了些處理,讓用戶可以自己選擇是運行上一個“穩定”的版本,還是冒遇到錯
誤的險而得到新特征,這個戰略還沒被大多數Linux黑客所仿效,但它應該被仿
效,存在兩個選擇的事實讓二者都很吸引 人。
  
五. 什麼時候玫瑰不是玫瑰?

  在研究了Linus的行為和形成了為什麼它成功的理論之後,我決定在我的工程
(顯然沒有那麼復雜和雄心勃勃)裡有意識的測試這個理論。
但我首先做的事是熟悉和簡化Popclient。 Carl Harris的實現非常好,但是
有一種對許多C程序來說沒有必要的復雜性。他把代碼當作核心而把數據結構當作
對代碼的支持,結果是代碼非常漂亮但是數據結構設計得很特別,相當丑陋(至少
對以這個老LISP黑客的標准來看),然而除了提高代碼和數據結構設計之外,重寫
它還有一個目的,就是要把它演化為我徹底理解的東西,對修改你不理解的程序
中的錯誤負責可不是一件有趣的事。

  第一個月我只是在領會Carl's的基本設計的含義,我所做的第一個重大修改
是加入了IMAP支持,我把協議機重新組織為一個通用驅動程序和三個方法表(對應
POP2、POP3和IMAP),這個前面的修改指出一個需要程序員(特別是象C這種沒有自
然的動態類型支持的語言)記在腦中的一般原理:

 9. 聰明的數據結構和笨拙的代碼要比相反的搭配工作的更好

  Fred Brooks也在他第11章中講道:“讓我看你的[代碼],把你的[數據結
構]隱藏起來,我還是會迷惑;讓我看看你的[數據結構],那我就不需要你的[代
碼]了,它是顯而易見的”。

  實際上,他說的是“流程圖”和“表”,但是在三十年的術語/文化演進之
後,事情還是一樣的。

  此時(1996年9月初,在從零開始六個月後),我開始想接下來修改名字——畢
竟,它已不僅僅是一個POP客戶,但我猶豫了,因為還沒有什麼新的漂亮設計呢,
我的popclient版本需要有自己的特色。

  當fetehmail學會怎樣把取到的郵件轉送到SMTP端口時,事情就完全改變了,
但是首先:上面我說過我決定使用這個工程來測試我關於Linus Torualds所做的
行為的理論,(你可能會問)我怎樣做到這點呢? 以下面的方式:

 1. 我盡早盡量頻繁的發布(幾乎從未少於每十天發布一次;在密集開發的時候
是每天一次)。

 2. 我把每一個和我討論fetchmail的人加入一個beta表中。

 3. 每當我發布我都向beta表中的人發出通告,鼓勵人們參與。

 4. 我聽取beta測試員的意見,向他們詢問設計決策,對他們寄來的補丁和反饋
表示感謝。

  這些簡單的手段立即收到的回報,在工程的開始,我收到了一些錯誤報告,
其質量足以使開發者因此被殺掉,而且經常還附有補丁、我得到了理智的批評,
有趣的郵件,和聰明的特征建議,這導致了:

 10. 如果你象對待最寶貴的資源一樣對待你的beta測試員,他們就會成為你最
寶貴的資源。

六. popclient變成了Fetchmail

  這個工程的真正轉折點是Harry Hochleiser寄給我他寫的代碼草稿,他把郵
件轉發到客戶端機器的SMTP端口,我立即意識到這個特征的可靠實現將淘汰所有
其他的遞送模式。

  幾個星期以來我一直在修改而不是改進fetchmail,因為我覺得界面設計雖然
有用但是太笨拙瑣碎了,到處充滿了太多的粗陋的細小選項。

  當我思考SMTP轉發時我發現popclient試圖做的事太多了,它被設計成既是一
個郵件傳輸代理(MTA)也是一個本地遞送代理(MDA)。使用SMTP轉發,它就可以從
MDA的事務中解脫出來而成為一個純MTA,而象sendmail一樣把郵件交給本地遞送
程序來處理。

  既然端口25在所有支撐TCP/IP的平台上早已被預留,為什麼還要為一個郵件
傳輸代理的配置或為一個郵箱設置加鎖的附加功能而操心呢?尤其是當這意味著抽
取的郵件就象一個正常的發送者發出的SMTP郵件一樣,而這就是我們需要的。

  這裡有幾個教益:第一,SMTP轉發的想法是我有意識地模擬Linus的方法以來
的最大的單個回報,一個用戶告訴我這個非同尋常的想法——我所需做的只是理
解它的含義。

 11. 想出好主意是好事,從你的用戶那裡發現好主意也是好事,有時候後者更
好。

  很有趣的是,你很快將發現,如果你完全承認你從其他人那裡得到多少教益
的話,整個世界將會認為所有的發明都是你做出的,而你會對你的天才變得謙
虛。我們可以看到這在Linus身上體現得多明顯!(當我在1997年8月的Perl會議上
發表這個論文時,Larry Wall坐在前排,當我講到上面的觀點時,他激動的叫了
出來:“對了!說對了!哥們!”所有的聽眾都哄堂大笑起來,因為他們知道同樣的
事情也發生在Perl的發明者身上)。

  於是在同樣精神指導下工程進行了幾個星期,我開始不光從我的用戶那兒也
從聽說我的系統的人那兒得到類似的贊揚,我把一些這種郵件收藏起來,我將在
我開始懷疑自己的生命是否有價值時重新讀讀這些信。:)

  但是有兩個更基本的,非政治性的對所有設計都有普遍意義的教益。

 12. 最重要和最有創新的解決方案常常來自於你認識到你對問題的概念是錯誤
的。

  一個衡量fetchmail成功的有趣方式是工程的beta測試人員表(fegtchmail的
朋友們)的長度,在創立它的時候已經有249個成員了,而且每個星期增加兩到三
個。

  實際上,當我在1997年5月校訂它時,這張表開始因為一個有趣的原因而縮短
了,有幾個人請求我把他們從表中去掉,因為fetchmail已經工作的如此之好,他
們不需要看到這些郵件了!也許這是一個成熟的市集風格工程的生命周期的一部分。

  我以前一直在解決錯誤的問題,把popclient當作MTA和具有許多本地遞送模
式的MDA的結合物,Fetchmail的設計需要從頭考慮為一個純的MTA,做為一個普通
Internet郵件路徑的一部分。

  當你在開發中碰了壁時(當你發現自己很難想通下一步時),那通常不是要問
自己是否找到正確答案,而是要問是否問了正確問題,也許需要重新構造問題。

  於是,我重新構造了我的問題,很清楚,要做的正確的事是(1)把SMTP轉發支
持放在通用驅動程序中,(2)把它做為缺省模式,(3)最終分離所有其他的遞送模
式,尤其是遞送到文件和標准輸出的選項。

  我在第三步上猶豫了一下,擔心會讓popdiant的長期用戶對新的遞送方法感
到煩心,在理論上,他們可以立即轉而轉發文件或者他們的非sendmail等價物來
得到同樣的效果,在實際中這種轉換可能會很麻煩。
但是當我這麼做之後,證明好處是巨大的,驅動程序代碼的冗余的部分消失
了,配置完全變得簡單了——不用屈從於系統MDA和用戶的郵箱,也不用為下層
OS是否支持文件鎖定而擔心了。

  而且,丟失郵件的唯一漏洞也被堵死了,如果你選擇了遞送到一個文件而磁
盤已滿,你的郵件就會丟失,這在SMTP轉發中不會發生,因為SMTP偵聽器不會返
回OK的,除非郵件可以遞送成功或至少被緩沖留待以後遞送。

  還有,性能也改善了(雖然在單次執行中你不會注意到),這個修改的另一個
不可忽視的好處是手冊變得大大簡單了。

  後來,為了允許處理一些罕見的情況,包括動態SLIP,我必須回到讓用戶定
義本地MDA遞送上來,但是我發現了一個更加簡單的方法。

  所有這些給了我們什麼啟發呢?如果可以不損失效率,就要毫不猶豫拋棄陳舊
的特性,Antonine de Saint-Exupery(在他成為經典兒童書籍作家之前是一個飛
行員和飛機設計師)曾說過:

 13. “最好的設計不是再也沒有什麼東西可以添加了,而是再也沒有什麼東西
可以去掉。”

  當你的代碼變得更好和更簡單時,這就是你知道它是正確的時候了,而且在
這個過程中,fetehmail的設計具有了自己的特點,而區別於其前身popclient。

  現在是改名的時候了,這個新的設計看起來比老popclient更象一個sendmail
的復制品,它們都是MTA,但是Senmail是推然後遞送,而新的popclient是拉然後
遞送。於是,在兩個月之後,我把它重新命名為fetehmail。

 七. Fetchmail成長起來

  現在我有了一個簡潔和富有創意的設計,工作得很好的代碼,因為我每天都
用它,和一直在增長的beta表,它讓我漸漸明白我已經不是在從事只能對少數其
他人有用的工作中,我寫了一個所有有一個Unix郵箱和SLIP/PPP郵件連接的人都
真正需要的程序。

  通過SMTP轉發功能,它成為一個潛在的“目錄殺手”,遠遠領先於它的競爭
者,這個程序如此能干以至於其他的程序不但被放棄簡直被忘記了。

  我知道你不可以真得瞄准或計劃出這樣的結果,你只能努力去設計這些強大
的思想,以後這些結果就好象是不可避免的、自然的、注定了的,得到這種思想
的唯一辦法是獲取許多思想,或者用工程化的思考其他人的好主意而超過原來想
到它的人的設想。

  Andrew Tanenbanm原來設想建造一個適合386的簡單的Unix用做教學,Linus
Torvalels把Andrew的可能想到的Minix可以做什麼的概念推進了一步,成長為一
個極好的東西,同樣的(雖然規模較小),我接受了Card Harris和Harry
Hochheiser的想法,把它們變得更強大,我們都不是人們所浪漫幻想的天才的創
始人,但是大多數科學和工程和軟件開發不是被天才的創始人完成的,這和流傳
的神話恰恰相反。

結果總是執著的原因——實際上,它是每個黑客為之生存的成功!而且它們意
味著我必須把自己的標准定高一點,為了把fetchmail變得和我所能設想的那樣
好,我必須不僅為我自己的需要寫代碼,而且也要包括對在我生活圍主頁外的人
們的需求的支持,而且同時也要保證程序的簡單和健壯。

  在實現它之後我首先寫的最重要的特征是支持多投——從集中一組用戶的郵
件的郵箱中取出郵件,然後把它路由到每個人手中。

  我之所以加上多投功能部分是因為有些用戶一直在鬧著要它,更是因為我想
它可以從單投的代碼中揭露出錯誤來,讓我完全一般地處理尋址,而且這被證明
了。正確解釋RFC822花了我相當長的時間,不僅因為它的每個單獨部分都很難,
而且因為它有一大堆相互依賴的苛刻的細節。

  但是多投尋址也成為一個極好的設計決策,由此我知道:

14. 任何工具都應該能以預想的方式使用,但是一個偉大的工具提供你沒料到
的功能。

  Fetchmant多投功能的一個沒有料到的用途是在SLIP/PPP的客戶端提供郵件
列表、別名擴展。這意味著一個使用個人機器的人不必持續訪問ISP的別名文件就
能通過一個ISP帳戶管理一個郵件列表。我的beta測試員提出的另一個重要的改變
是支持8位MIME操作,這很容易做,因為我已經仔細的保證了8位代碼的清晰,不
僅因為我預見到了這個特性的需求,而且因為我忠實於另一准則:

 15. 當寫任何種類的網關型程序時,多費點力,盡量少干擾數據流,永遠不要
拋棄信息,除非接收方強迫這麼作!

  如果我不遵從這個准則,那麼8位MIME支持將會變得困難和笨拙,現在我所需
要做的,是只讀一下RFC 1652,在產生信頭的邏輯加上一點而已。

  一些歐洲用戶要求我加上一個選項來限制每次會話取得消息數(這樣他們就可
以從昂貴的電話網中控制花費了),我很長一段時間拒絕這樣做,而且我仍然對它
不很高興,但是如果你是為了世界而寫代碼,你必須聽取顧客的意見——這並不
隨他們不付給你錢而改變。

八. 從Fetchmail得來的另一些教益

  在他們回到一般的軟件工程問題以前,還有幾個從fetchmail得到的教益需要
思考。

  rc文件語法包括可選的“noise”關鍵字,它被掃描器完全忽略了,當你把它
們全抽取出的時候,關鍵字/值對更具可讀性。

  當我注意到rc文件的聲明在多大程度上開始象一個微型命令語言時,這是一個
Late-night的體驗(這也是我為什麼把popclient原來的“server”關鍵字改成了
“poll”)。

  對我來說似乎把這個微型命令語言變得更象英語可能會使它更容易使用。現在,
雖然我對經過Emacs和HTML及許多數據庫引擎所證實的“把它做成一個語言”的設計
方式確信不疑,但是我並不是一個通常的“類英語”語法的狂熱擁護者。

  傳統程序員容易控制語法使它盡量精確和緊湊,完全沒有冗余,這是計算機資
源還很昂貴時遺留下的一種文化傳統,所以掃描策略需要盡可能的廉價和簡單,而
具有50%冗余度的英語,看來好象是一個非常不合適的模型。

  這並不是我不用類英語語法的原因,我提到這一點是為了推翻它,在更廉價的
時鐘周期與核心的時代,簡潔並沒有走到盡頭,今天對一個語言來說,對人更方便
比對機器更廉價來的更加重要。

  然而,有幾個原因提醒我們小心一點,一個是掃描策略的復雜度開銷——你並
不想把它變成一個巨大的錯誤來源和讓用戶困惑,另一個是試圖使語言表面上的類
似可以和傳統語言一樣令人困惑(你可以在許多4GL和商業數據庫查詢語言上看到這
一點)。

  Fetchmail的控制語法避免了這些問題,因為語言的領域是極其有限的。它一
點也不象一個一般性的語言,它很簡單地描述的東西並不復雜,所以很少可能在英
語的一個小子集與實際的控制語言之間發生混淆,我想這有一個更廣泛的教益:

 16. 如果你的語言一點也不象是圖靈完備的,嚴格的語法會有好處。

  另一個教益是關於安全的,一些fetchmail用戶要求我修改軟件把口令加密存
貯在rc文件裡,這樣觑探者就不能看到它們了。

  我沒有這樣做,因為這實際上起不到任何保護作用,任何有權讀取你的rc文件
的人都可以以你的名義運行fetchmail——如果他們要破你的口令,它們可以從
fetchmail的代碼中找到制作解碼器的方法。

  所以fetchmail口令的加密都會給那些不慎重思考的人一種安全的錯覺,這裡
一般性的准則是:

 17. 一個安全系統只能和它的秘密一樣安全,當心偽安全。

九. 集市風格的必要的先決條件

  本文的早期評審人員和測試人員堅持提出成功的市集模式開發的先決條件,
包括工程領導人的資格問題和在把項目公開和開始建造一個協作開發人員的社團
的時候代碼的狀態。

  相當清楚,不能以一個市集模式從頭開發一個軟件,我們可以以市集模式、
測試、調試和改進,但是以市集模式從頭開始一個項目將是非常困難的,Linus
沒有這樣做,我也沒有,初期的開發人員的社團應該有一此可以運行和測試的
東西來玩。

  當你開始創建社團時,你需要演示的是一個諾言,你的程序不需要工作的
很好,它可以很粗糙、很笨拙、不完整和缺少文檔、它不能忽略的東西是要吸
引哪些人卷入一個整潔的項目。

  Linux和fetchmail都是以一個吸引人的基本設計進入公共領域的,許多和
我一樣在思考市集模式的人已經正確的認為這是非常關鍵的,然後得出了一個
結論,工程領導者的高度的設計直覺和聰穎是必不可少的。

  但是Linus是從Unix得到他的設計的,我最初是從先前的popmail得到啟發的
(雖然相對Linux而言,它最後改變巨大),所以市集風格的領導人/協調人需要有
出眾的設計才能,或者他可以利用別人的設計才能?

  我認為能夠提出卓越的原始設計思想對協調人來說不是最關鍵的,但是對
他/她來說絕對關鍵的是要能把從他人那裡得到的好的設計重新組織起來。

  Linux和fetchmail項目都顯示了這些證據,Linus(如同前面所說)並不是驚人
的原始設計者,但他顯示了發現好的設計並把它集成到Linux內核中的強大決竅。
還有我也描述了怎樣從別人那裡得到了fetchmail中最強大的設計思想(SMTP轉發)。

  本文的早期讀者稱贊我,說因為我做了許多關於原始設計的事,所以傾向於
低估原始設計在市集項目中的價值,也許有些是對的吧,但是設計(而不是編碼或
調試)本來就是我最強的能力。

  變得聰明和軟件設計的原始創作的問題是它會變成一個習慣,當需要保持事
物健壯和簡潔的時候,你卻開始把事情變得漂亮但卻復雜。我曾經犯過錯誤,使
得一些項目因我而崩潰了,但我努力不讓它發生在fetchmail身上。

  所以我相信fetchmail項目的成功部分是因為我抑制自己不要變得太聰明,這
說明(至少)對市集模式而言原始設計並不是本質的,請考察一下Linux假設Linus
Torvalds在開發時試圖徹底革新操作系統設計,它還會象今天我們所擁有的內核
那樣穩定和成功嗎?

  當然基本的設計和編碼技巧還是必需的,但我希望每個嚴肅考慮發起一個市
集計劃的人都已至少具備這些能力,自由軟件社團的內部市場對人們有某些微妙
的壓力,讓他們不要發起自由不能搞定的開發,目前為止,這工作得仍然相當好。

  對市集項目來說,我認為還有另一種通常與軟件開發無關的技能和設計能力
同樣重要——或者更加重要,市集項目的協調人或領導人必須有良好的人際和交
流能力。

  這是很顯然的,為了建造一個開發社團,你需要吸引人,你所做的東西要讓
他們感到有趣,而且要保持他們對他們正在做的工作感到有趣,而且要保持他們
對他們正在做的工作感到高興,技術方面對達成這些目標有一定幫助,但這遠遠
不是全部,你的個人素質也有關系。

  並不是說Linus是一個好小伙子,讓人們喜愛並樂於幫助他,也並不是說我是
個積極外向的,喜歡扎堆兒工作,有出眾的幽默感的人,對市集模式的工作而
言,至少有一點吸引人的技巧是非常有幫助的。

十. 自由軟件的社會學語境

 下述如實:最好的開發是從作者解決每天工作中的個人問題開始的,因為它
對一大類用戶來說是一個典型問題,所以它就推廣開來了,這把我們帶回到准則1,
也許是用一個更有用的方式來描述:

 18. 要解決一個有趣的問題,請從發現讓你感興趣的問題開始。

  這是Carl Harris和原先的popclient的情形,也是我和fetchmail的情形,但
這已在很長一段時間被大家知曉了,Linux和fetchmail的歷史要求我們注意的有
趣之處是下一個階段——軟件在一個龐大的活躍的用戶和協作開發人員的社團中
的進化。

  在《神秘的人月》一書中,Fred Brooks觀察到程序員的工作時間是不可替代
的:在一個誤了工期的軟件項目中增加開發人員只會讓它拖得更久,他聲稱項目
的復雜度和通訊開銷以開發人員的平方增長,而工作成績只是以線性增長,這個
說法被稱為“Brooks定律”,被普遍當作真理,但如果Brooks定律就是全部,那
Linux就不可能成功。

  幾年之後,Gerald Weinbeng的經典之作“The Psychology Of Computer
Progromming”為我們更正了Brooks的看法,在他的“忘我(egoless)的編程”中,
Weinberg觀察到在開發人員不頑固保守自己的代碼,鼓勵其他人尋找錯誤和發展
潛力的地方,軟件的改進的速度會比其他地方有戲劇性的提高。

  Weinberg的用詞可阻止了他的分析得到應有的接受,人們對把Internet黑客
稱為“忘我”的想法微笑,但是我想今天他的想法比以往任何時候都要引人注目。

  Unix的歷史已經為我們准備好了我們正在從Linux學到的(和我在更小規模上
模仿Linus的方法所驗證的)東西,這就是,雖然編碼仍是一個人干的活,真正偉
大的工作來自於利用整個社團的注意和腦力,在一個封閉的項目中只利用他自己
的腦力的人會落在知道怎樣創建一個開放的、進化的,成百上千的人在其中查找
錯誤和進行修改的環境的開發人員之後。

  但是Unix的傳統中有幾個因素阻止把這種方法推到極致。一個是各種授權的
法律約束、商業機密和商業利益,另一個(事後來看)是Internet還不夠好。

  在Internet變得便宜之前,有一些在地理上緊密的社團,


——摘自:http://www.tuxedo.org/~esr


Copyright © Linux教程網 All Rights Reserved