?? 7.html
字號:
<br> 1993年以前我在一個小的免費訪問的名為Chester County InterLink的ISP的做技術(shù)工作,它位于Pennsylvania的West Chester。(我協(xié)助建立了CCIL,并寫了我們獨特的多用戶BBS系統(tǒng)——你可以telnet到locke.ccil.org來檢測一下。今天它在十九條線上支持三千的用戶)。這個工作使我可以一天二十四小時通過CCIL的56K專線連在網(wǎng)上,實際上,它要求我怎么做!<p><br> 所以,我對Internet email很熟悉。因為復(fù)雜的原因,很難在我家里的機(jī)器(snark.thyrsus.com)和CCIL之間用SLIP工作。最后我終于成功了,但我發(fā)現(xiàn)不得不時常telnet到locke來檢查我的郵件,這真是太煩了。我所需要的是我的郵件發(fā)送到snark,這樣biff(1)會在它到達(dá)時通知我。<p><br> 簡單地sendmail的轉(zhuǎn)送功能是不夠的,因為snark并不是總在網(wǎng)上而且沒有一個靜態(tài)地址。我需要一個程序通過我的SLIP連接把我的本地發(fā)送的郵件拉過來。我知道這種東西是存在的,它們大多使用一個簡單的協(xié)議POP(Post Office Protocol)。而且,locke的BSD/OS操作系統(tǒng)已經(jīng)自帶了一個POP3服務(wù)器。<p><br> 我需要一個POP3客戶。所以我到網(wǎng)上去找到了一個。實際上,我發(fā)現(xiàn)了三、四個。我用了一會pop-perl,但它卻少一個明顯的特征:抽取收到的郵件的地址以便正確回復(fù)。<p><br> 問題是這樣的:假設(shè)locke上一個叫“joe”的人向我發(fā)了一封郵件。如果我把它取到snark上準(zhǔn)備回復(fù)時,我的郵件程序會很高興地把它發(fā)送給一個不存在的snark上的“joe”。手工的在地址上加上“@ccil.org”變成了一個嚴(yán)酷的痛苦。<p><br> 這顯然應(yīng)是計算機(jī)替我做的事。(實際上,依據(jù)RFC1123的5.2.18節(jié),sendmail應(yīng)該做這件事)。但是沒有一個現(xiàn)存的POP客戶知道怎樣做!于是這就給我們上了第一課:<p> 1.每個好的軟件工作都開始于搔到了開發(fā)者本人的癢處。<p> 也許這應(yīng)該是顯而易見的(“需要是發(fā)明之母”長久以來就被證明是正確的),但是軟件開發(fā)人員常常把他們的精力放在它們既不需要也不喜歡的程序,但在Linux世界中卻不是這樣——這解釋了為什么從Linux團(tuán)體中產(chǎn)生的軟件質(zhì)量都如此之高。<p><br> 那么,我是否立即投入瘋狂的工作中,要編出一個新的POP3客戶與現(xiàn)存的那些競爭呢?才不是哪!我仔細(xì)考察了手頭上的POP工具,問自己“那一個最接近我的需要?”因為:<br> 2.好程序員知道該寫什么,偉大的程序員知道該重寫(和重用)什么。<p><br> 我并沒有聲稱自己是一個偉大的程序員,可是我試著效仿他們。偉大程序員的一個重要特點是建設(shè)性的懶惰。他們知道你是因為成績而不是努力得到獎賞,而且從一個好的實際的解決方案開始總是要比從頭干起容易。<p><br> 例如,Linux并不是從頭開始寫Linux的。相反的它從重用Minix(一個386機(jī)型上的類似Unix的微型操作系統(tǒng))的代碼和思想入手。最后所有的Minix代碼都消失或被徹底的重寫了,但是當(dāng)它們在的時候它為最終成為Linux的雛形做了鋪墊。<p><br> 秉承同樣的精神,我去尋找良好編碼的現(xiàn)成的POP工具,用來作為基礎(chǔ)。<p><br> Unix世界中的代碼共享傳統(tǒng)一直對代碼重用很友好(這正是為什么GNU計劃不管Unix本身有多么保守而選取它作為基礎(chǔ)操作系統(tǒng)的原因)。Linux世界把這個傳統(tǒng)推向技術(shù)極限:它有幾個T字節(jié)的源代碼可以用。所以在Linux世界中花時間尋找其他幾乎足夠好的東西,會比在別處帶來更好的結(jié)果。<p><br> 這也適合我。加上我先前發(fā)現(xiàn)的,第二次尋找找到了9個候選者——fetchPOP,PopTart,get-mail,gwpop,pimp,pop-perl,popc,popmail 和 upop)。我首先選定的是“fetchpop”。我加入了頭標(biāo)重寫功能,并且做了一些被作者加入他的1.9版中的改進(jìn)。<p><br> 但是幾個星期之后,我偶然發(fā)現(xiàn)了Carl Harris寫的“popclient”的代碼,然后發(fā)現(xiàn)有個問題,雖然fetchpop有一些好的原始思想(比如它的守護(hù)進(jìn)程模式),它只能處理pop3,而且編碼的水平相當(dāng)業(yè)余(Seung-Hong是個很聰明但是經(jīng)驗不足的程序員),Carl的代碼更好一些,相當(dāng)專業(yè)和穩(wěn)固,但他的程序缺少幾個重要的相當(dāng)容易實現(xiàn)的fetchpop的特征(包括我自己寫的那些)。<p><br> 繼續(xù)呢還是換一個? 如果換一個的話,作為得到一個更好開發(fā)基礎(chǔ)的代價,我就要扔掉我已經(jīng)有的那些代碼。<p><br> 換一個的一個實際的動機(jī)是支持多協(xié)議,pop3是用的最廣的郵局協(xié)議,但并非唯一一個,F(xiàn)etchpop和其余幾個沒有實現(xiàn)POP2.RPOP,或者APOP,而且我還有一個為了興趣加入IMAP(Internet Message Access Protocol,最近設(shè)計的最強(qiáng)大的郵局協(xié)議)的模糊想法。<p><br> 但是我有一個更加理論化的原因認(rèn)為換一下會是一個好主意,這是我在Linux很久以前學(xué)到的:<p> 3.“計劃好拋棄,無論如何,你會的”(Fred Brooks,《神秘的人月》第11章)<p><br> 或者換句話說,你常常在第一次實現(xiàn)一個解決方案之后才能理解問題所在,第二次你也許才足夠清楚怎樣做好它,因此如果你想做好,準(zhǔn)備好推翻重來至少一次。<p><br> 好吧(我告訴自己),對fetchpop的嘗試是我第一次的嘗試,因此我換了一下。<p><br> 當(dāng)我在1996年6月25日把我第一套popclient的補(bǔ)丁程序寄給Carl Harris之后,我發(fā)現(xiàn)一段時間以前他已經(jīng)對popclient基本上失去了興趣,這些代碼有些陳舊,有一些次要的錯誤,我有許多修改要做,我們很快達(dá)成一致,我來接手這個程序。不知不覺的,這個計劃擴(kuò)大了,再也不是我原先打算的在已有的pop客戶上加幾個次要的補(bǔ)丁而已了,我得維護(hù)整個的工程,而且我腦袋里涌動著一些念頭要引起一個大的變化。<p><br> 在一個鼓勵代碼共享的軟件文化里,這是一個工程進(jìn)化的自然道路,我要指出:<p> 4. 如果你有正確的態(tài)度,有趣的問題會找上你的,但是Carl Harris的態(tài)度甚至更加重要,他理解:<p> 5.當(dāng)你對一個程序失去興趣時,你最后的責(zé)任就是把它傳給一個能干的后繼者。<p><br> 甚至沒有商量,Carl和我知道我們有一個共同目標(biāo)就是找到最好的解決方案,對我們來說唯一的問題是我能否證明我有一雙堅強(qiáng)的手,他優(yōu)雅而快速的寫出了程序,我希望輪到我時我也能做到。<p>三. 擁有用戶的重要性<p><br> 于是我繼承了popclient,同樣重要的是,我繼承了popclient的用戶基礎(chǔ),用戶是你所擁有的極好的東西,不僅僅是因為他們顯示了你正在滿足需要,你做了正確的事情,如果加以適當(dāng)?shù)呐囵B(yǎng),他們可以成為合作開發(fā)者。<p><br> Unix傳統(tǒng)另一有力之處是許多用戶都是黑客,因為源優(yōu)碼是公開的,他們可以成為高效的黑客,這一點在Linux世界中也被推向了令人高興的極致,這對縮短調(diào)試時間是極端重要的,在一點鼓勵之下,你的用戶會診斷問題,提出修訂建議,幫你以遠(yuǎn)比你期望快得多的速度的改進(jìn)代碼。<p><br> 6. 把用戶當(dāng)做協(xié)作開發(fā)者是快速改進(jìn)代碼和高效調(diào)試的無可爭辯的方式。<p><br> 這種效果的力量很容易被低估,實際上,幾乎所有我們自由軟件世界中的人都強(qiáng)烈低估了用戶可以多么有效地對付系統(tǒng)復(fù)雜性,直到Linus讓我們看到了這一點。<p><br> 實際上,我認(rèn)為Linus最聰明最了不起的工作不是創(chuàng)建了Linux內(nèi)核本身,而是發(fā)明了Linux開發(fā)模式,當(dāng)我有一次當(dāng)著他的面表達(dá)這種觀點時,他微笑了一下,重復(fù)了一句他經(jīng)常說的話:“我基本上是一個懶惰的人,依靠他人的工作來獲取成績。”象狐貍一樣懶惰,或者如Robert Heinlein所說,太懶了而不會失敗。<p><br> 回顧起來,在GNU Emacs Lisp庫和Lisp代碼集中可以看到Linux方法的成功,與Emacs的C內(nèi)核和許多其他FSF的工具相比,Lisp代碼庫的演化是流動性的和用戶驅(qū)動的,思想和原型在達(dá)到最終的穩(wěn)定形式之前往往要重寫三或四次,而且經(jīng)常利用Internet的松散合作。<p><br> 實際上,我自己在fetchmail之前最成功的作品要算Emacs VC模式,它是三個其他的人通過電子郵件進(jìn)行的類似Linux的合作,至今我只見過其中一個人(Richard Stallman),它是SCCS、RCS和后來的CVS的前端,為Emacs提供“one-touch”版本控制操作,它是從一個微型的、粗糙的別人寫好的sccs.el模式開始演化的,VC開發(fā)的成功不像Emacs本身,而是因為Emacs Lisp代碼可以很快的通過發(fā)布/測試/改進(jìn)的過程。<p><br> (FSF的試圖把代碼放入GPL之下的策略有一個未曾預(yù)料到的副作用,它讓FSF難以采取市集模式,因為他們認(rèn)為每個想貢獻(xiàn)二十行以上代碼的人都必須得到一個授權(quán),以使受到GPL的代碼免受版權(quán)法的侵?jǐn)_,具有BSD和MITX協(xié)會的授權(quán)的用戶不會有這個問題,因為他們并不試圖保留那些會使人可能受到質(zhì)詢的權(quán)力)。<p><br>四. 早發(fā)布、常發(fā)布<p><br> 盡量早盡量頻繁的發(fā)布是Linux開發(fā)模式的一個重要部分,多數(shù)開發(fā)人員(包括我)過去都相信這對大型工程來說是個不好的策略,因為早期版本都是些充滿錯誤的版本,而你不想耗光用戶的耐心。<p> 這種信仰強(qiáng)化了建造大教堂開發(fā)方式的必要性,如果目標(biāo)是讓用戶盡可能少的見到錯誤,那你怎能不會僅僅每六個月發(fā)布一次(或更不經(jīng)常),而且在發(fā)布之間象一只狗一樣辛勤“捉蟲”呢? Emacs C內(nèi)核就是以這種方式開發(fā)的,Lisp庫,實際上卻相反,因為有一些有FSF控制之外的Lisp庫,在那里你可以獨立于Emacs發(fā)布周期地找尋新的和開發(fā)代碼版本。<p><br> 這其中最重要的是Ohio州的elisp庫,預(yù)示了今天的巨大的Linux庫的許多特征的精神,但是我們很少真正仔細(xì)考慮我們在做什么,或者這個庫的存在指出了FSF建造教堂式開發(fā)模式的什么問題,1992年我曾經(jīng)做了一次嚴(yán)肅的嘗試,想把Ohio的大量代碼正式合并到Emacs的官方Lisp庫中,結(jié)果我陷入了政治斗爭中,徹底失敗了。<p><br> 但是一年之后,在Linux廣泛應(yīng)用之后,很清楚,一些不同的更加健康的東西誕生了,Linus的開發(fā)模式正好與建造教堂方式相反,Sunsite和tsx-11的庫開始成長,推動了許多發(fā)布。所有這些都是聞所未聞的頻繁的內(nèi)核系統(tǒng)的發(fā)布所推動的。<p><br> Linus以所有實際可能的方式把它的用戶作為協(xié)作開發(fā)人員。<p><br> 7. 早發(fā)布、常發(fā)布、聽取客戶的建議<p> Linus的創(chuàng)新并不是這個(這在Unix世界中是一個長期傳統(tǒng)),而是把它擴(kuò)展到和他所開發(fā)的東西的復(fù)雜程度相匹配的地步,在早期一天一次發(fā)布對他來說都不是罕見的!而且因為他培育了他的協(xié)作開發(fā)者基礎(chǔ),比其他任何人更努力地充分利用了Internet進(jìn)行合作,所以這確實能行。<p><br> 但是它是怎樣進(jìn)行的呢?它是我能模仿的嗎?還是這依賴于Linus的獨特天才?<p><br> 我不這樣想,我承認(rèn)Linus是一個極好的黑客(我們有多少人能夠做出一個完整的高質(zhì)量的操作系統(tǒng)內(nèi)核?),但是Linux并不是一個令人敬畏的概念上的飛躍,Linus不是(至少還不曾是)象Richard stallman或James Gosling一樣的創(chuàng)新天才,在我看來,Linus更象一個工程天才,具有避免錯誤和開發(fā)失敗的第六感覺,掌握了發(fā)現(xiàn)從A點到B點代價最小的路徑的決竅,確實,Linux的整個設(shè)計受益于這個特質(zhì),并反映出Linus的本質(zhì)上保守和簡化設(shè)計的方法。<p><br> 如果快速的發(fā)布和充分利用Internet不是偶然而是Linus的對代價最小的路徑的洞察力的工程天才的內(nèi)在部分,那么他極大增強(qiáng)了什么?他創(chuàng)建了什么樣的方法?<p><br> 問題回答了它自己,Linus保持他的黑客用戶經(jīng)常受到激勵和獎賞:被行動的自我滿足的希望所激勵,而獎賞則是經(jīng)常(甚至每天)都看到工作在進(jìn)步。<p><br> Linus直接瞄準(zhǔn)了爭取最多的投入調(diào)試和開發(fā)的人時,甚至冒代碼不穩(wěn)定和一旦有非常棘手的錯誤而失去用戶基礎(chǔ)的險,Linus似乎相信下面這個:<p> 8. 如果有一個足夠大的beta測試人員和協(xié)作開發(fā)人員的基礎(chǔ),幾乎所有的問題都可以被快速的找出并被一些人糾正。<p><br> 或者更不正式的講:“如果有足夠多的眼睛,所有的錯誤都是淺顯的”(群眾的眼睛是雪亮的),我把這稱為“Linus定律”。<p><br> 我最初的表述是每個問題“對某些人是透明的”,Linus反對說,理解和修訂問題的那個人不一定非是甚至往往不是首先發(fā)現(xiàn)它的人,“某個人發(fā)現(xiàn)了問題”,他說,“另一個理解它,我認(rèn)為發(fā)現(xiàn)它是個更大的挑戰(zhàn)”,但是要點是所有事都趨向于迅速發(fā)生。<p><br> 我認(rèn)為這是建造教堂和集市模式的核心區(qū)別,在建造教堂模式的編程模式看來,錯誤和編程問題是狡猾的、陰險的、隱藏很深的現(xiàn)象,花費幾個月的仔細(xì)檢查,也不能給你多大確保把它們都挑出來的信心,因此很長的發(fā)布周期,和在長期等待之后并沒有得到完美的版本發(fā)布所引起的失望都是不可避免的。<p><br> 以市集模式觀點來看,在另一方面,我們認(rèn)為錯誤是淺顯的現(xiàn)象,或者至少當(dāng)暴露給上千個熱切的協(xié)作開發(fā)人員,讓他們來對每個新發(fā)布進(jìn)行測試的時候,它們很快變得淺顯了,所以我們經(jīng)常發(fā)布來獲得更多的更正,作為一個有益的副作用,如果你偶爾做了一個笨拙的修改,也不會損失太多。也許我們本不應(yīng)該這樣的驚奇,社會學(xué)家在幾年前已經(jīng)發(fā)現(xiàn)一群相同專業(yè)的(或相同無知的)觀察者的平均觀點比在其中隨機(jī)挑選一個來得更加可靠,他們稱此為“Delhpi效應(yīng)”,Linus所顯示的證明在調(diào)試一個操作系統(tǒng)時它也適用——Delphi效應(yīng)甚至可以戰(zhàn)勝操作系統(tǒng)內(nèi)核一級的復(fù)雜度。<p><br> 我受Jeff Dutky (dutky @ wam.umd.edu)的啟發(fā)指出Linus定律可以重新表述為“調(diào)試可以并行”,Jeff觀察到雖然調(diào)試工作需要調(diào)試人員和對應(yīng)的開發(fā)人員相交流,但它不需要在調(diào)試人員之間進(jìn)行大量的協(xié)調(diào),于是它就沒有陷入開發(fā)時遇到的平方復(fù)雜度和管理開銷。<p> 在實際中,由于重復(fù)勞動而導(dǎo)致的理論上的喪失效率的現(xiàn)象在Linux世界中并不是一個大問題,“早發(fā)布、常發(fā)布策略”的一個效果就是利用快速的傳播反饋修訂來使重復(fù)勞動達(dá)到最小。<p><br> Brooks甚至做了一個與Jeff相關(guān)的更精確的觀察:“維護(hù)一個廣泛使用的程序的成本一般是其開發(fā)成本的40%,奇怪的是這個成本受到用戶個數(shù)的強(qiáng)烈影響,更多的用戶發(fā)現(xiàn)更多的錯誤”(我的強(qiáng)調(diào))。<p> 更多的用戶發(fā)現(xiàn)更多的錯誤是因為更多的用戶提供了更多測試程序的方法,當(dāng)用戶是協(xié)作開發(fā)人員時這個效果被放大了,每個找尋錯誤的人都有自己稍微不同的感覺和分析工具,從不同角度來看待問題。“Delphi效應(yīng)”似乎因為這個變體工作變得更加精確,在調(diào)試的情況下,這個變體同時減小了重復(fù)勞動。<p><br> 所以加入更多的beta測試人員雖不能從開發(fā)人員的P.O.V中減小“最深”的錯誤的復(fù)雜度,但是它增加了這樣一種可能性,即某個人的工具和問題正好匹配,而這個錯誤對這個人來說是淺顯的。<p><br> Linus也做了一些改進(jìn),如果有一些嚴(yán)重的錯誤,Linux內(nèi)核的版本在編號上做了些處理,讓用戶可以自己選擇是運行上一個“穩(wěn)定”的版本,還是冒遇到錯誤的險而得到新特征,這個戰(zhàn)略還沒被大多數(shù)Linux黑客所仿效,但它應(yīng)該被仿效,存在兩個選擇的事實讓二者都很吸引 人。<p><br>五. 什么時候玫瑰不是玫瑰?<p><br> 在研究了Linus的行為和形成了為什么它成功的理論之后,我決定在我的工程(顯然沒有那么復(fù)雜和雄心勃勃)里有意識的測試這個理論。<br>但我首先做的事是熟悉和簡化Popclient。 Carl Harris的實現(xiàn)非常好,但是有一種對許多C程序來說沒有必要的復(fù)雜性。他把代碼當(dāng)作核心而把數(shù)據(jù)結(jié)構(gòu)當(dāng)作對代碼的支持,結(jié)果是代碼非常漂亮但是數(shù)據(jù)結(jié)構(gòu)設(shè)計得很特別,相當(dāng)丑陋(至少對以這個老LISP黑客的標(biāo)準(zhǔn)來看),然而除了提高代碼和數(shù)據(jù)結(jié)構(gòu)設(shè)計之外,重寫它還有一個目的,就是要把它演化為我徹底理解的東西,對修改你不理解的程序中的錯誤負(fù)責(zé)可不是一件有趣的事。<p><br> 第一個月我只是在領(lǐng)會Carl's的基本設(shè)計的含義,我所做的第一個重大修改是加入了IMAP支持,我把協(xié)議機(jī)重新組織為一個通用驅(qū)動程序和三個方法表(對應(yīng)POP2、POP3和IMAP),這個前面的修改指出一個需要程序員(特別是象C這種沒有自然的動態(tài)類型支持的語言)記在腦中的一般原理:<p><br> 9. 聰明的數(shù)據(jù)結(jié)構(gòu)和笨拙的代碼要比相反的搭配工作的更好<p><br> Fred Brooks也在他第11章中講道:“讓我看你的[代碼],把你的[數(shù)據(jù)結(jié)構(gòu)]隱藏起來,我還是會迷惑;讓我看看你的[數(shù)據(jù)結(jié)構(gòu)],那我就不需要你的[代碼]了,它是顯而易見的”。<p><br> 實際上,他說的是“流程圖”和“表”,但是在三十年的術(shù)語/文化演進(jìn)之后,事情還是一樣的。<p><br> 此時(1996年9月初,在從零開始六個月后),我開始想接下來修改名字——畢竟,它已不僅僅是一個POP客戶,但我猶豫了,因為還沒有什么新的漂亮設(shè)計呢,我的popclient版本需要有自己的特色。<p><br> 當(dāng)fetehmail學(xué)會怎樣把取到的郵件轉(zhuǎn)送到SMTP端口時,事情就完全改變了,但是首先:上面我說過我決定使用這個工程來測試我關(guān)于Linus Torualds所做的行為的理論,(你可能會問)我怎樣做到這點呢? 以下面的方式:<br> 1. 我盡早盡量頻繁的發(fā)布(幾乎從未少于每十天發(fā)布一次;在密集開發(fā)的時候是每天一次)。<br>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -