一.大教堂和市集
Linux的影響是非常巨大的。甚至在5年以前,有誰能夠想象一個世界級的操作係統能夠僅僅用細細的I連接起來的散布在全球的幾千個開發人員有以業餘時間來創造呢?
我當然不會這麼想。在1993年早期我開始注意Linux時,我已經參與Unix和自由軟件開發達十年之久了。我是八十年代中期GNU最早的幾個參與者之一。我已經在網上發布了大量的自由軟件,開發和協助開發了幾個至今仍在廣泛使用的程序(hack,EmaD模式,xlife等等)。我想我知道該怎樣做。
Linux推翻了許多我認為自己明白的事情。我已經宣揚小工具、快速原型和演進式開發的Unix福音多年了。但是我也相信某些重要的複雜的事情需要更集中化的,嚴密的方法。我相信多數重要的軟件(操作係統和象Emacs一樣的真正大型的工具)需要向建造大教堂一樣來開發,需要一群於世隔絕的奇才的細心工作,在成功之前沒有beta版的發布。
LinusTorvalds的開發風格(盡早盡多的發布,委托所有可以委托的事,對所有的改動和融合開放)令人驚奇的降臨了。這裏沒有安靜的、虔誠的大教堂的建造工作——相反,Linux團體看起來像一個巨大的有各種不同議程和方法的亂哄哄的集市(Linux歸檔站點接受任何人的建議和作品,並聰明的加以管理),一個一致而穩定的係統就象奇跡一般從這個集市中產生了。
這種設計風格確實能工作,並且工作得很好,這個事實確實是一個衝擊。在我的研究過程中,我不僅在單個工程中努力工作,而且試圖理解為什麼Linux世界不僅沒有在一片混亂中分崩離析,反而以大教堂建造者們不可想象的速度變得越來越強大。
到了1996年中,我想我開始理解了。我有一個極好的測試我的理論的機會,以一個自由軟件計劃的形式,我有意識的是用了市集風格。我這樣做了,並取得了很大的成功。
在本文的餘下部分,我將講述這個計劃的故事,我用它來明確一些自由軟件高效開發的格言。並不是所有這些都是從Linux世界中學到的,但我們將看到Linux世界給予了它們一個什麼樣的位置。如果我是正確的,它們將使你理解是什麼使Linux團體成為好軟件的源泉,幫助你變得更加高效。
二.郵件必須得通過
1993年以前我在一個小的免費訪問的名為ChesterterLink的ISP的做技術工作,它位於Pennsylvaer。(我協助建立了CCIL,並寫了我們獨特的多用戶BBS係統——你可以tel到locke.ccil.來檢測一下。今天它在十九條線上支持三千的用戶)。這個工作使我可以一天二十四小時通過CCIL的56K專線連在網上,實際上,它要求我怎麼做!
所以,我對Iemail很熟悉。因為複雜的原因,很難在我家裏的機器(snark.thyrsus.)和CCIL之間用SLIP工作。最後我終於成功了,但我發現不得不時常tel到locke來檢查我的郵件,這真是太煩了。我所需要的是我的郵件發送到snark,這樣biff(1)會在它到達時通知我。
簡單地sendmail的轉送功能是不夠的,因為snark並不是總在網上而且沒有一個靜態地址。我需要一個程序通過我的SLIP連接把我的本地發送的郵件拉過來。我知道這種東西是存在的,它們大多使用一個簡單的協議POP(PostOfficeProtocol)。而且,locke的BSD/OS操作係統已經自帶了一個POP3服務器。
我需要一個POP3客戶。所以我到網上去找到了一個。實際上,我發現了三、四個。我用了一會popperl,但它卻少一個明顯的特征:抽取收到的郵件的地址以便正確回複。
問題是這樣的:假設locke上一個叫“joe”的人向我發了一封郵件。如果我把它取到snark上準備回複時,我的郵件程序會很高興地把它發送給一個不存在的snark上的“joe”。手工的在地址上加上“@ccil.”變成了一個嚴酷的痛苦。
這顯然應是計算機替我做的事。(實際上,依據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個候選者——fetchPetmail,gwpop,pimp,popperl,popail和upop)。我首先選定的是“fetchpop”。我加入了頭標重寫功能,並且做了一些被作者加入他的1.9版中的改進。
但是幾個星期之後,我偶然發現了CarlHarris寫的“popt”的代碼,然後發現有個問題,雖然fetchpop有一些好的原始思想(比如它的守護進程模式),它隻能處理pop3,而且編碼的水平相當業餘(SeungHong是個很聰明但是經驗不足的程序員),Carl的代碼更好一些,相當專業和穩固,但他的程序缺少幾個重要的相當容易實現的fetchpop的特征(包括我自己寫的那些)。
繼續呢還是換一個?如果換一個的話,作為得到一個更好開發基礎的代價,我就要扔掉我已經有的那些代碼。
換一個的一個實際的動機是支持多協議,pop3是用的最廣的郵局協議,但並非唯一一個,Fetchpop和其餘幾個沒有實現POP2.RPOP,或者APOP,而且我還有一個為了興趣加入IMAP(IMessageAccessProtocol,最近設計的最強大的郵局協議)的模糊想法。
但是我有一個更加理論化的原因認為換一下會是一個好主意,這是我在Linux很久以前學到的:
3.“計劃好拋棄,無論如何,你會的”(FredBrooks,《神秘的人月》第11章)
或者換句話說,你常常在第一次實現一個解決方案之後才能理解問題所在,第二次你也許才足夠清楚怎樣做好它,因此如果你想做好,準備好推翻重來至少一次。
好吧(我告訴自己),對fetchpop的嚐試是我第一次的嚐試,因此我換了一下。
當我在1996年6月25日把我第一套popt的補丁程序寄給CarlHarris之後,我發現一段時間以前他已經對popt基本上失去了興趣,這些代碼有些陳舊,有一些次要的錯誤,我有許多修改要做,我們很快達成一致,我來接手這個程序。不知不覺的,這個計劃擴大了,再也不是我原先打算的在已有的pop客戶上加幾個次要的補丁而已了,我得維護整個的工程,而且我腦袋裏湧動著一些念頭要引起一個大的變化。
在一個鼓勵代碼共享的軟件文化裏,這是一個工程進化的自然道路,我要指出:
4.如果你有正確的態度,有趣的問題會找上你的,但是CarlHarris的態度甚至更加重要,他理解:
5.當你對一個程序失去興趣時,你最後的責任就是把它傳給一個能幹的後繼者。
甚至沒有商量,Carl和我知道我們有一個共同目標就是找到最好的解決方案,對我們來說唯一的問題是我能否證明我有一雙堅強的手,他優雅而快速的寫出了程序,我希望輪到我時我也能做到。
三.擁有用戶的重要性
於是我繼承了popt,同樣重要的是,我繼承了popt的用戶基礎,用戶是你所擁有的極好的東西,不僅僅是因為他們顯示了你正在滿足需要,你做了正確的事情,如果加以適當的培養,他們可以成為合作開發者。
Unix傳統另一有力之處是許多用戶都是黑客,因為源優碼是公開的,他們可以成為高效的黑客,這一點在Linux世界中也被推向了令人高興的極致,這對縮短調試時間是極端重要的,在一點鼓勵之下,你的用戶會診斷問題,提出修訂建議,幫你以遠比你期望快得多的速度的改進代碼。
6.把用戶當做協作開發者是快速改進代碼和高效調試的無可爭辯的方式。
這種效果的力量很容易被低估,實際上,幾乎所有我們自由軟件世界中的人都強烈低估了用戶可以多麼有效地對付係統複雜性,直到Linus讓我們看到了這一點。
實際上,我認為Linus最聰明最了不起的工作不是創建了Linux內核本身,而是發明了Linux開發模式,當我有一次當著他的麵表達這種觀點時,他微笑了一下,重複了一句他經常說的話:“我基本上是一個懶惰的人,依靠他人的工作來獲取成績。”象狐狸一樣懶惰,或者如RobertHeinlein所說,太懶了而不會失敗。
回顧起來,在GNUEmacsLisp庫和Lisp代碼集中可以看到Linux方法的成功,與Emacs的C內核和許多其他FSF的工具相比,Lisp代碼庫的演化是流動性的和用戶驅動的,思想和原型在達到最終的穩定形式之前往往要重寫三或四次,而且經常利用I的鬆散合作。
實際上,我自己在fetchmail之前最成功的作品要算EmacsVC模式,它是三個其他的人通過電子郵件進行的類似Linux的合作,至今我隻見過其中一個人(RichardStallman),它是SCCS、RCS和後來的CVS的前端,為Emaetouch”版本控製操作,它是從一個微型的、粗糙的別人寫好的sccs.el模式開始演化的,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的開發模式正好與建造教堂方式相反,Susx11的庫開始成長,推動了許多發布。所有這些都是聞所未聞的頻繁的內核係統的發布所推動的。
Linus以所有實際可能的方式把它的用戶作為協作開發人員。
7.早發布、常發布、聽取客戶的建議
Linus的創新並不是這個(這在Unix世界中是一個長期傳統),而是把它擴展到和他所開發的東西的複雜程度相匹配的地步,在早期一天一次發布對他來說都不是罕見的!而且因為他培育了他的協作開發者基礎,比其他任何人更努力地充分利用了I進行合作,所以這確實能行。
但是它是怎樣進行的呢?它是我能模仿的嗎?還是這依賴於Linus的獨特天才?
我不這樣想,我承認Linus是一個極好的黑客(我們有多少人能夠做出一個完整的高質量的操作係統內核?),但是Linux並不是一個令人敬畏的概念上的飛躍,Linus不是(至少還不曾是)象Richardstallman或JamesGosling一樣的創新天才,在我看來,Linus更象一個工程天才,具有避免錯誤和開發失敗的第六感覺,掌握了發現從A點到B點代價最小的路徑的決竅,確實,Linux的整個設計受益於這個特質,並反映出Linus的本質上保守和簡化設計的方法。
如果快速的發布和充分利用I不是偶然而是Linus的對代價最小的路徑的洞察力的工程天才的內在部分,那麼他極大增強了什麼?他創建了什麼樣的方法?
問題回答了它自己,Linus保持他的黑客用戶經常受到激勵和獎賞:被行動的自我滿足的希望所激勵,而獎賞則是經常(甚至每天)都看到工作在進步。
Linus直接瞄準了爭取最多的投入調試和開發的人時,甚至冒代碼不穩定和一旦有非常棘手的錯誤而失去用戶基礎的險,Linus似乎相信下麵這個:
8.如果有一個足夠大的beta測試人員和協作開發人員的基礎,幾乎所有的問題都可以被快速的找出並被一些人糾正。
或者更不正式的講:“如果有足夠多的眼睛,所有的錯誤都是淺顯的”(群眾的眼睛是雪亮的),我把這稱為“Linus定律”。
我最初的表述是每個問題“對某些人是透明的”,Linus反對說,理解和修訂問題的那個人不一定非是甚至往往不是首先發現它的人,“某個人發現了問題”,他說,“另一個理解它,我認為發現它是個更大的挑戰”,但是要點是所有事都趨向於迅速發生。
我認為這是建造教堂和集市模式的核心區別,在建造教堂模式的編程模式看來,錯誤和編程問題是狡猾的、陰險的、隱藏很深的現象,花費幾個月的仔細檢查,也不能給你多大確保把它們都挑出來的信心,因此很長的發布周期,和在長期等待之後並沒有得到完美的版本發布所引起的失望都是不可避免的。