大教堂和市集
Eric Raymond
HansB翻譯
一. 大教堂和市集
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變得便宜之前,有一些在地理上緊密的社團,它們的文化鼓勵Weingberg的「忘我」編程,一個開發人員很容易吸引許多熟練的人和協作開發人員,貝爾實驗室,MIT A1實驗室,UC Berkeley,都成為傳統的、今天仍然是革新的源泉。
Linux是第一個有意識的成功的利用整個世界做為它的頭腦庫的項目,我不認為Linux的孕育和萬維網的誕生相一致是一個巧合,而且Linux在 1993-1994的一段ISP工業大發展和對Internet的興趣爆炸式增長的時期中成長起來,Linus是第一個學會怎樣利用Internet的新 規的人。
廉價的Internet對Linux模式的演化來說是一個必要條件,但它並不充分,另一個關鍵因素是領導風格的開發和一套協作的氛圍使開發人員可以吸引協作開發人員和最大限度地利用媒體。
但是這種領導風格與氛圍到底是什麼呢?它不能建立在權力關係之上——甚至如果它們可以,高壓的領導權力不能產生我們所看到的結果,Weinberg引用了19世紀俄國的無政府主義者Kropotkin的「Memoris of a Revolutionist」來證明這個觀點:
「我從小生活在一個農奴主的家庭中,我有一個活躍的生活,像我們時代的所有年輕人一樣,我深信命令、強制、責罵、懲罰等等的必要性。但是當我(在早 期)必須管理一個企業,和(自由)人打交道時,當每一個錯誤都會產生嚴重後果時,我開始接受以命令和紀律為準則來行動和以普通理解為準則來行動的區別。前 者在軍事閱兵中工作的很好,但是它在現實生活中一文不值,目標達成只是靠許多願望的聚合的簡單後果。」「許多聚合在一起的願望的直接後果」精確地指出了象 Linux的項目所需要的東西。「命令的準則」在Internet這種無政府主義的天堂中一群自願者之中是沒有市場的,為了更有效的操作和競爭,想領導協 作項目的黑客們必須學會怎樣以Kropotkins含糊指出的「理解的準則」模式來恢復和激活社團的力量,他們必須學會使用Linus定律。
前面我引用「Delhpi效應」來作為Linus定律的一個可能的解釋,但是來自生物學和經常學的自適應系統的更強大的分析也提出了自己的解 釋,Linus世界的行為更像一個自由市場或生態系統,由一大群自私的個體組成,它們試圖取得(自己)最大的實效,在這個過程中產生了比任何一種中央計劃 都細緻和高效的自發的改進的結果,所以,這裡就是尋找「理解的準則」的地方。
Linux黑客取得的最大化的「實際利益」不是經典的經濟利益,而是無形的他們的自我滿足和在其他黑客中的聲望,(有人會說他們的動機是「利他的」, 但這忽略了這樣的事實:利他主義本身是利他主義者的一種自我滿足的形式),自願的文化以這種方式工作的實際上並非不尋常,我已參與一個科幻迷團體很長時間 了,它不像黑客團體一樣,顯式地識別出「egoboo」(一個人在其他愛好者之中的聲望的增長)作為自願者活動背後的基礎驅動力)。
Linus成功地把自己置於項目的守門人的位置,在項目中開發大部分是別人做的,他只是在項目中培養興趣直到它可以自己發展下去,這為我們展示了對 Kropokin的「共同理解原則」的敏銳把握,對Linux這種類似經濟學的觀點讓我們看到這種理解是怎樣應用的。
我們可以把Linus的方法視為創建一個高效的關於「egoboo」(而不是錢)的市場,來把自私的黑客個體儘可能緊密的聯繫起來,達成只能通過高度 協作才能得到的困難的結果,在fetchmail項目中我展示了(在較小規模上)這種模式可以複製,得到良好的結果,也許我比他更有意識一點、更加系統一 點。
許多人(尤其是哪些由於政治原因不信任自由市場的人)會盼望自我導向的自我主義者的文化破碎、報廢、秘密和敵對,但這種盼望很明顯地被Linux的文 檔的多樣性、質量和深度打破了,程序員討厭寫文檔似乎已是聖訓,但Linux的黑客們怎麼產生了這麼多?顯然Linux的egoboo自由市場比有大量資 金的商業軟件產品的文檔部在產生有品德的、他人導向的行為方面工作的更好。
Fetchmail和Linux內核項目都表明,通過恰當的表彰許多其他黑客,一個強大的開發者/協調者可以用Internet得到許多協同開發人員而不是讓項目分崩離析為一片混亂,所以關於Brooks定律我得到了下面的想法:
19. 如果開發協調人員有至少和Internet一樣好的媒介,而且知道怎樣不通過強迫來領導,許多頭腦將不可避免地比一個好。
我認為自由軟件的將來將屬於那些知道怎樣玩Linus的遊戲的人,把大教堂拋之腦後擁抱市集的人,這並不是說個人的觀點與才氣不再重要,而是,我認為自由軟件的前沿將屬於從個人觀點和才氣出發的人,然後通過共同興趣自願社團的高效建造來擴展。
可能不只是自由軟件的將來,在解決問題方面,沒有任何商業性開發者可以與Linux社團的頭腦庫相匹敵,很少有人能負擔起僱傭200多個為fetchmail出過力的人!
也許最終自由軟件文化將勝利,不是因為協作在道德上是正確的或軟件「囤積居奇」在道德上是錯的(假設你相信後者,Linus和我都不),而僅僅是因為商業世界在進化的軍備競賽中不能戰勝自由軟件社團,因為後者可以把更大更好的開發資源放在解決問題上。
**** 網友寫給作者的感想: ****
你好,Eric:
我剛讀了你的大教堂/市集的文章,因為你的主頁指出你還要繼續關於這個問題的思考,我提供一些個人的觀察。
首先介紹一些背景:當1990年出現BSD Net/2的時候,Brad Grantham和我把它移植到了MacⅡ平台上,它在幾個月之後以Mac BSD發佈(當然是以市集風格),後來成為Net BSD/Mac。
我作為一個市集協調人學到了一些東西:
1. 人們很快地自願提供幫助,但是常常很慢,我們收到上百封信說:「我很想幫助,請告訴我需要什麼?」 這些人沒提供什麼幫助,不管他們有多麼積極,真正有幫助的人那些給我們的第一封信便說:「嘿,我修改了這個,這兒有一個補丁。」最後我們忽略了所有第一種 類型的郵件(只是把他們引向工作列表),培養與第二種人的關係,這種情況所有協調人都應知道,來克服看到這麼多「志願者」時的盲目高興。
(注意:他們的動機是好的,他們只是沒有認識到他們正在志願做什麼)。
2. 你已經提到了這一點,但我認為它是極端重要的:甚至在你宣佈產品以前你必須有一個可工作的系統:例如,我們一直等到有了一個可引導的內核和一個單用戶根 shell之後才把它貼到Usenet,曾有過(據我所知)四個不同的Mac Linux項目,每一個都在Linux新聞組中有一大批擁護者,都創建了郵件列表,每個人都很熱情,寫了FAQ,還有許多諸如MacOS的圖標應是什麼樣 的討論。所有這些項目沒有發佈一行代碼或者一個內核、我挑選了MkLinux(Apple開發的)作為一個可工作的Mac版Linux(在一個項目 中,MacLinux假設運轉在68K Mac上,而郵件列表中所有的討論都是關於怎樣把它移植到Power Mac上。68K版本甚至不能遠程工作!),這些項目吸引了上述的第一種「幫助者」,熱情高漲但是實際上卻沒做什麼事,殺掉一個項目最快的方法是在你什麼 都還沒有之前就宣佈它,我已經見的太多了,尤其是在
Linux世界裡。
我知道這兩點看起來相當悲觀,但我知道當我們想到「啊,我們做了這麼多事了,肯定搞定了不少問題了吧!」的時候,我們太容易失去理智。而那實際上只不過是一些善良的動機罷了(誰說過:「不要把動機和行動混淆在一起?」 本·弗蘭克林?)協調人需要解散所有那些諸如圖標應該是什麼樣的、FAQ用HTML格式還是SGML模式的熱情討論,而把注意力放在取得產品的一個可工作的版本,一旦得到了,人們就真正開始幫助了。
(從正面來看,MacBSD極大地得益於從它的開發風格,我們得到了代碼、設備驅動程序、錢和一些捐贈和借到的測試和開發的硬件設備)。
我期望看到對我上述觀點的任何評論和你關於這個主題寫的任何東西。
Lawrrance