原轉貼網址
1. 教堂與市集 (The Cathedral and the Bazaar)
Linux 打破了許多軟體發展的傳統, 這個世界級的作業系統在五年前僅僅靠著
如絲般的網際網路, 神奇地聯合了散布在全世界數以千計兼職的玩家們來發展
它, 誰曾料到會發生這樣的事情呢?
我當然也沒料到. Linux 出現在我電腦螢幕是在 1993 年年初, 當時我埋首於
UNIX 及開放性原始碼的軟體發展已有十年, 1980 年代中期, 我是 GNU 專案
首批的貢獻者之一, 我寫過許多開放性原始碼的軟體放到網路上供人使用, 也
曾獨立或協同發展好幾個程式 (nethack, Emacs 的 VC 和 GUD 功能, xlife,
… 等等), 這些程式到今天仍廣泛地為人所用, 我想我知道這是怎麼辦到的.
[譯注] GNU 是自由軟體基金會 (Free Software Fundation) 的一個專案,
目標是發展出 UNIX 上所有程式的自由版本.
Emacs 是自由軟體基會發展出來的一支程式, 可做文字編輯器, 提
供寫程式的整合發展環境, 用來讀電子郵件, 新聞群組, 甚至瀏覽
網頁. 更詳細的資訊請參考 http://www.gnu.org.
Linux 扭轉了許多我認為我已知道的觀念. 多年來我一直被傳以: 小工具集,
快速原型發展及程式進化的 UNIX 福音. 但我也相信對於有一定複雜度的程式
必需使用集中和有經驗的方法來開發, 我相信最重要的軟體 (作業系統以及龐
大的工具程式如 Emacs) 必須如建造一座教堂般, 由個別的高手或一小群專家
在光輝的孤立中小心翼翼地精雕細琢, 時機未到之前, 不會釋出測試版.
Linus Torvald 的軟體發展風格 (儘早並經常發表新版本, 授權每一件作者可以
委託的事, 不拒絕幾乎到混亂程度的程式) 的出現如同一個驚奇, 沒有令人肅,
然起敬的教堂, 甚至 Linux 的同好們似乎組成了一個有不同流程和不同方式的
大市集 (Linux 的檔案服務站台就是它適切的象徵, 每個人都服從著自由
的規則), 以這個風格發展出來的 Linux 既一致又穩定, 表面上看來
真是一連串的奇蹟.
[譯注] Linus Torvald 是 Linux 核心程式 (kernel) 的原始作者.
市集模式似乎是可行的, 並且運作得很好, 這個事實帶來了相當的震憾. 當以
我的方法去認知時, 我除了努力做好個人的專案, 並也試著去瞭解為什麼在 Linux
的世界, 不但沒有因為渾沌不清而四分五裂, 反而以教堂建造者幾乎想像不到
的速度在茁壯.
直到 1996 年年中, 我想我才開始瞭解這一件事. 我得到了一個絕佳的機會
來試驗我的理論, 這個機會是一個開放性原始碼型式的專案, 正好可以試用
市集模式來發展, 所以我做了這個專案, 而且更有意義的是它成功了.
接下來在這篇文章中我將陳述這個專案的故事, 並且以它為例提出關於有效
地利用開放性原始碼模式來發展軟體的格言, 這些法則並非都是我在 Linux
中第一次學到, 但我們可以看到 Linux 的世界是怎麼賦予它們特別的意義.
如果我是對的, 那麼這些格言將會幫你真確地瞭解是什麼促成 Linux 社群
成為好軟體的原創者, 並且幫助你變得更具生產力.
2. 信一定要寄到 (The Mail Must Get Through)
自 1993 年起, 我一直擔任一家提供免費上線的小型 ISP 的技術人員,這家
ISP 叫做 County InterLink (CCIL), 位於賓夕凡尼亞州的 West Chester.
(我本身參與捐款設立 CCIL, 並寫了我們獨一無二的多人佈告欄軟體 — 你
可以用 telnet 連線至 locke.ccil.org 一探究竟. 目前它共有三十條線,
可提供近三千位的使用者上網.) 這個工作讓我可以一天二十四小時透過 CCIL
56K 的線路上網. — 事實上, 我的確非常需要它!
因此我必須常常利用便捷的網際網路電子郵件, 但由於一些複雜的原因, 使得
我家裡的機器 (snark.thyrsus.com) 要以 SLIP 協定連上 CCIL 有所困難.
最後我還是做到了, 但我馬上發覺我必須週期性地以 telnet 連上 lokcke
來檢查我是否有新信件, 這實在是一件煩人的事. 我想要的是: 我的郵件可以
被送到 snark, 而且送達時會通知我, 然後我可以用 snark 上的工具程式來
處理這些郵件.
簡單的 sendmail 轉信功能在這裡幫不上忙, 因為我個人的機器並不是時時
都和網路連結著而且它也沒有固定的網址. 我所需要的程式是這樣的: 它可
以透過 SLIP 連線把我的電子郵件都抓回來並放在我的機器. 我知道有這樣
的程式, 它們大部份都使用一個簡單的網路應用協定叫 POP (Post Office
Protocol), 而 locke 的 BSD 作業系統上確定已包含有 POP3 的伺服程式.
我需要一支 POP3 客戶端的程式. 所以我到網路上搜尋之後找到一個. 其實
我找到了三或四支這樣的程式. 我使用了一陣子的 pop-perl, 但是它少了一
個滿重要的特性 — 就是精巧地處理抓回來信件檔頭附的來源處, 以使收件人
能回覆信件至正確的網址.
這個問題是這樣的: 假設 locke 上有一個叫做 joe 的使用者寄信給我, 而
pop-perl 把信抓回到我的 snark 上, 當我要回給信給 joe 時, 我的送信程式
會傻呼呼地試著把這封回信送給根本就不存在 snark 上的使用者 joe. 所以
我必須動手編輯回信的網址即加上 “@ccil.org”, 很快地這變成了一件頗痛苦
的事情.
很明顯的這是電腦應該幫我做的, 可是現有的 POP 客戶端程式卻沒有任何一
支知道要這麼做. 這使我們學會了第一課:
[格言 1] 好軟體都是起源於程式發展者要解決切身之痛.
1. Every good work of software starts by scratching a developer’s personal itch.
也許這已是眾所皆知 (不是有句著名的諺語叫: “需要為發明之母” 嗎?), 但
有多少軟體發展者為了薪水, 把時間都耗在寫他們既不需要也不喜愛的程式上
呢? 然而這樣的事不會發生在 Linux 的世界 — 這也許可以解釋為什麼由 Linux
社群們發展出來的軟體的平均水準都這麼高.
所以, 我是否該立即如抓狂般地投入寫作一支新的 POP 客戶端的程式來和既有
的一較高下? 並不如你所想的, 我仔細地檢視我手上已握有的 POP 客戶端程式,
看看那一支最符合我的需要, 因為
[格言 2] 優秀的程式師知道要寫程式, 偉大的程式師知道要改寫 (和重覆利用) 程式.
2. Good programmers know what to write. Great ones know what to rewrite (and reuse).
我並非在宣稱我是一個偉大的程式師, 但我願去效法. 偉大的程式師還有一項重
要的特色是老製造著偷懶的辦法, 他們認為人們爭取最好的成績並不是為了努
力的過程, 而是為了最後的結果. 更何況由一個部份可行的解決方法開始總比
什麼都沒有容易得多.
舉例來說, Linus Torvalds
http://www.earthspace.net/~esr/faqs/linus
當初寫 Linux 的核心程式時也不是從零開始, 他是由借重 Minix 的
程式和構想開始的 (Minix 是一個像 UNIX 的小型作業系統, 它在 386 機器
上執行), 然而到最後原來屬於 Minix 的碼不是被移出就是被改寫 — 儘管
如此, Minix 的碼畢竟曾存在於 Linux 中, 並且曾為尚未茁壯的 Linux 提供
一個骨架, 最後終於誕生了 Linux.
為仿效這樣的精神, 我開始找尋一個現有而且寫得有條理的 POP 工具程式, 來
作為我發展新程式的基礎.
在 UNIX 的世界中, 原始程式碼共享的傳統讓我們可以很容易地重覆利用程式碼
, 這也是為什麼 GNU 專案要選擇 UNIX 作為它發展的平台, UNIX 作業系統本身
幾乎沒做什麼保留, Linux 的世界也遵行著這個傳統, 到接近它技術極限的地
步, 它供人運用旳開放性原始碼程式, 有天文數字般地多, 所以在 Linux 已有
的資源中找到一個足夠好的程式要比其他的作業系統容易.
而我也的確找到了, 連我先前的搜尋再加上這一次總共有九個程式候選 —
fetchpop, PopTart, get-mail, gwpop, pimp, pop-perl, popc, popmail 及
upop. 我首先選擇 Seung-Hong Oh 寫的 “fetchpop” 作為出發點, 我加入了我
要的 “重寫郵件檔頭” 功能, 並且作了多處的改善. 原作者同意將這些納入
fetchpop 的 1.9 版.
幾個星期之後, 我緩緩地讀著 Carl Harris 寫的 “popclient” 的原始碼, 並且
發現了一個問題: 雖然 fetchpop 有一些好的初始想法 (如它的伺服程式模式),
但它只能處理 POP3 的協定, 而且它的原始程式只有業餘的水準 (Seung-Hong
是個聰明的程式設計師, 但經驗不夠老道). 而 Carl 寫的程式碼就比較好, 具
相當的職業水準和穩固性, 但他的程式缺乏了許多重要的特色, 如 fetchpop 中
巧妙的實作 (包括我加入的部份).
要換還是不換呢? 假如我選擇換的話, 那麼換到一個較好的發展基礎所要付出的
代價就是要丟掉我已經寫好的程式碼.
事實上我選擇換的動機是為了能支援多種 post-office 的協定, 雖然 POP3 最廣
為人採用, 但它卻不是唯一可用的協定. Fetchpop 和其他同類的程式並不支援
POP2, RPOP, 或 APOP, 而我早先有一個概略的想法 (只是為了有趣): 加入 IMAP
http://www.imap.org
(Internet Message Access Protocol 最新最強的 post-office 協定) 協定的
支援.
一個更正式的理論讓我覺得換到新的發展基礎是個好主意, 這個理論是早在 Linux
出現前, 我就已經學會了:
[格言 3] “計畫好如何捨棄一條路吧, 你遲早會想盡辦法這麼做的.”
(引自 Fred Brooks << 人-月 的迷思 >> 一書的第十一章)
3. “Plan to throw one away; you will, anyhow.”
(Fred Brooks, “The Mythical Man-Month”, Chapter 11)
否則, 計畫走另一條路吧. 針對一個問題, 在尚未實作出第一個解法前, 你通常並
不真正瞭解這個問題. 也許第二次的時候你才能充分瞭解怎麼做才對, 所以即使
你想做對一件事, 但起碼你要準備從第一次做起.
我告訴我自己: 修改 fetchpop 是第一次. 所以我換到 Carl Harris 的
popclient 繼續發展 (是第二次).
當 1996 年 6 月 25 日我送給 Carl Harris 我第一次對 popclient 所做的修正
後 , 我才曉得他已經對這支程式沒興趣了. 原來的程式碼乏人照料已有一段時間,
還包括一些次要的錯誤. 有許多修正要做, 很快的我們兩人都同意由我接手整個程
式是合理的一件事.
在我不經意間, 這個專案的規模擴大了, 我不再只注意現在的 popclient 要修補
那些次要的部分, 而是要接下維護整個整程式, 在我腦海曾浮現許多主意, 我想這
可以引導我改變 popclient 的主要部分.
在鼓勵分享程式碼的軟體文化下, 一個專案以這樣自然的方式演進. 我表現出:
[格言 4] 抱持正確的態度, 就會發現有趣的問題.
4. If you have the right attitude, interesting problems will find you.
但 Carl Harris 的態度更為重要, 他懂得:
[格言 5] 當你對一個問題不再感興趣時, 你最後的責任就是找位能勝任的接棒人.
5. When you lose interest in a program, your last duty to it is to
hand it off to a competent successor.
雖然 Carl 和我沒討論這些, 但我們卻有一個共同的目標就是對這個問題寫出最好
的解法. 現在唯一的問題只剩: 證明我是個可信賴的人, 而我已經做到, 所以他便
欣然地把這支程式交給了我. 我希望這個專案在我手中能變得更好.
3. 擁有使用者的重要 (The Importance of Having Users)
我繼承了 popclient, 更重要的是我也繼承了它的使用者. 擁有使用者是很棒
的一件事, 並不是因為這展現出你在解決他們的問題, 或是你在做好事. 而是
好好地培養使用者, 他們可以變成協同發展者.
UNIX 的傳統中有一種力量, 那就是許多使用者同時也是程式高手, Linux 促使這
變成一件非常愉快的事. 這是因為原始碼是公開的, 所以使用者可以變成有影響力
的高手, 這對縮短除錯的時間實在太有助益了. 只要你給一點掌聲, 使用者們會
幫你診斷問題, 建議需修正的地方, 以及改進程式碼, 這比你自己一個人包下
全部的事要快得許多.
[格言 6] 把你的使用者視為協同發展人, 可以讓你傷最少的腦筋, 但做到原始碼的快速改善, 程式的除錯有績效.
6. Treating your users as co-developers is your least-hassle route to
rapid code improvement and effective debugging.
這種效應所造成的影響力很容易就被低估, 事實上, 開放性原始碼世界的
所有人, 幾乎都嚴重低估了因使用者增多而產生用以對抗系統複雜度的力量, 直到
Linus Torvalds 明白地揭露了這一點.
其實我認為 Linus 在技術上最聰明和最重大的貢獻並不在於寫出 Linux 的核
心程式, 而在於發明 Linux 的發展模式. 在一次和他的會面中, 我提出了這點
見解, 他微笑著, 並重複他常說的一句話: “基本上我是一個非常懶的人, 因其
他人在 Linux 上真正的努力, 而感到與有榮焉.” 懶惰就像狐狸一樣地精明,
或者就如同 Rober Heinlein 曾說: “因為太懶所以成功了.”
回顧過去的例子, 在 GNU Emacs 的 Lisp 程式庫及其 Lisp 程式碼的資源庫中
, 我們可以看到 Linux 模式所用的方法和所得的成功. 相對於 Emacs 中用 C
語言寫的核心部分及自由軟體基金會其他的工具 (這都是以建造教堂的模式發
展), Emacs Lisp 程式碼的資源庫非常地使用者導向並且更新很快, 好的點子
和原型在最後成熟穩定前常常都已重寫過三或四次, 藉由網際網路而來的非緊
密合作進行得很頻繁, 就像 Linux 一樣.
我在還沒寫作 fetchmail 前, 最成功的傑作大概要算是 Emacs 的 VC 功能了,
這項專案進行時, 我用像 Linux 一樣的合作模式, 用 email 和其他三位作者
互相聯繫, 到今天為止, 我只見過其中一位 (他就是 Richard Stallman, Emacs
的作者以及自由軟體基金會
http://www.fsf.org 的創辦人). Emacs 的 VC
功能是作為 SCCS, RCS 及後來的 CVS 的前端處理, 提供版本控制功能
“按一下” 的操作法, 這是由某位仁兄撰寫的小而有力的 sccs.el 功能
改良而來, VC 功能的發展相當成功, 這是因為 Emacs 用的 Lisp 程式可以
快速地經歷 “發表 — 測試 — 改良”, 而不像 Emacs 本身核心的發展
那樣緩慢.
4. 儘早發表, 經常發表新版本 (Release Early, Release Often)
儘早, 經常發表新版本是 Linux 發展模式中非常重要的一環. 過去, 大部份的
程式發展者 (包括我) 認為這個策略對較大型的專案是不好的, 因為早期的版本
幾乎可以定義為多錯的版本, 我們並不想把使用者的耐心消磨殆盡.
這個過去的信念加強了軟體的發展要用建造教堂的方式的想法. 假如我們極欲
強調的目標是讓使用者在軟體中發現最少的錯誤, 那你何不每半年 (或更長) 才
發表一個新版本, 並且在發展新版本的期間, 賣力地除錯而累得像條狗似的.
Emacs 的核心部分 (用 C 語言寫的) 就是用這種方式發展的, 但它的 Lisp 程式
庫就不是. 因為 Emacs 的 Lisp 資源庫不在自由軟體基金會的管轄內, 你可以在
其中找到新發展的 Lisp 程式使用, 而不受限於 Emacs 的發表週期.
在 Emacs 的 Lisp 程式庫中, 最重要的一個來源是俄亥俄州的 elisp 資源庫,
它先前的精神就已經具有今日大規模 Linux 資源庫的特色, 但當時我們之中卻
很少有人思考過我們到底做了什麼, 甚至想過我們已對自由軟體基金會的 “建造
教堂” 的發展模式提出質疑. 1992 年左右, 我很認真地要把俄亥俄州 elisp
資源庫中許多程式加入 Emacs 正式的 Lisp 程式庫中, 但卻遭遇到官方的阻礙
而失敗了.
但一年之後, Linux 已受到四方的矚目, 也帶來不同而且更健康的觀點,
Linus 的開放性發展策略和 “建造教堂” 非常不同. 當時 Linux 的兩大資源庫
sunsite 和 tsx-11 正在萌芽, 有許多版本在交流著, Linux 核心系統發表新版本
的頻繁程度前所未有.
Linus 以最有效的方法, 視使用者為協同發展者:
[格言 7] 儘早, 經常發表新版本, 並且傾聽使用者的意見.
Release early. Release often. And listen to your customers.
Linus 的創新並不完全在此 (這在 UNIX 世界是行之有年的傳統了), 而在於提高
這個做法效力的層次, 使其能匹配他在發展的系統的複雜度. 早期在 1991 年左右
, 許多人都知道他一天內發表一次以上 Linux 核心程式旳新版本. 因為他善用網
際網路和協同發展者們合作更勝於其他人.
他能我也能嗎? 還是只有像他這樣的天才才辦得到?
我並不認為如此, 雖然 Linus 是一位很厲害的高手 (在我們之間, 有多少人能夠
完整地寫出一個具有商品品質的作業系統核心呢? ), 但 Linux 並不是一個空前
耀進的觀念, Linus 也並非 (或者說至少目前還不是) 如 Richard Stallman 或
James Cosling (NeWS 和 java 的創始者) 這樣的天才創新者, 而我個人認為他
是一位天才工程師, 他有避免程式錯誤及避免程式發展掉入死胡同的第六感, 和
找到兩點間最省力路徑的技巧. 事實上, 整個 Linux 的設計中, 我們可以看到
Linus 表現出的品質和他保守而簡單的設計取向.
承上所說, 如果快速地發表新版本和徹底地善用網際網路媒介不是突然冒出, 而是
以 Linus 天才工程師洞見所得的最省力路徑, 那麼他把網際網路的什麼功用發揮
到最大?
其實問題的本身已反應出答案, Linus 讓 Linux 的高手和使用者們經常感覺刺激
和有收穫 — 感覺刺激是因協助發展 Linux 得到自我滿足, 感覺有收獲是因經常
(甚至每天) 進步的 Linux 幫助他們把工作做得更好.
Linus 想直接將投入除錯和發展的 “人-時” (person-hours) 數加到最大,
即使要付出的代價是程式碼的不穩定, 或是因一些程式錯誤被證實無法追蹤而
嚇走原有的使用者. Linus 會如此做是因為他相信:
[格言 8] 以足夠多的 “beta 版” 測試者和協同發展者做基礎, 幾乎程式 中的每一個問題都可以很快地找出來, 並且對某些人而言, 針對發現的問題的解決方法是顯而易見的.
8. Given a large enough beta-tester and co-developer base, almost
every problem will be characterized quickly and the fix obvious to
someone.
或者用比較不那麼正式的說法: “足夠多的人來看程式,
所有的錯誤都變得淺顯”, 我將此命名為 “Linus 定律”.
我原本先前的論述是: “某些問題對某些人而言是容易解決的”, 但 Linus
有不同的意見: “瞭解並解決問題的人不一定是第一個發現問題的人”,
他說: “有些人發現問題, 有些人解決問題, 我願正式強調 — 發現問題是
較大的挑戰. ” 而在 Linux 的世界, 發現問題和解決問題的速度都很快.
我想這就是教堂模式和市集模式最主要的不同, 以教堂建造者的觀點來看程式
發展, 程式錯誤和相關問題難以處理, 並隱伏在深處, 需要數個月的工夫仔細察看
來找到它們, 而這對程式發展者的自信少有加許. 發展的期間越長, 一旦經冗長等
待的新版本發表後不如預期完美, 使用者的失望也越大.
另一方面就市集發展模式的觀點來看, 它假設程式錯誤都是顯而易見的, 或者說
至少在上千位渴望新版的協同發展者面前, 程式錯誤很快地都變得淺顯, 因此經常
發表新版本是為了獲得更多的指正, 以及避免偶爾笨拙的修補.
以上已說明足夠 “Linus 定律”. 如果 “Linus 定律” 是假的, 那麼任何像
Linux 核心程式這樣複雜的系統, 並且擁有像 Linux 核心程式這麼多的高手
在發展, 早就因溝通不良及未被發現的程式錯誤而崩塌. 反過來說如果
“Linus 定律” 是真的, 那正可解釋為什麼相對地 Linux 比較沒有程式錯誤.
也許 Linus 定律並不是一個驚奇, 社會學家多年前發現到在一群素質相同的觀察
家中, 他們共同做出的預測要比其中任一位單獨所做的要來得可信. 這被稱為
“Delphi 效應”. 可見 Linus 只是把 “Delphi 效應” 用在發展作業系統時
對程式的除錯上, 所以 “Delphi 效應” 能夠克服發展系統的複雜度,
即使複雜如作業系統核心.
[譯注] Delphi 是希臘古都, 以善作預言的 Apollo 神殿而聞名.
我在此要感謝 Jeff Dutky
dutky@wam.umd.edu, 他指出 “Linus 定律” 亦可稱
之為 “程式除錯可併行處理”. Jeff 觀察到多位程式除錯者在工作時需要和一些
程式發展者溝通協調, 但是程式除錯者彼此間卻不需如此. 所以增加程式除錯者
並不會像增加程式發展者那樣, 多出平方倍的複雜度和管理成本.
理論上造成程式除錯效率減低的原因是多位除錯者重複同一件工作, 就實際的情形
而言, 在 Linux 的世界中幾乎不會發生這樣的狀況. “儘早, 經常發表新版本”
這個策略使得程式錯誤的修補回饋得很快, 藉此將除錯者重複同一件工作
的機會減至最低.
Brooks 曾發表過一個即席的看法, 和 Jeff 的看法相關: “維護一個廣為人用
的程式的總成本通常是發展這個程式成本的百分之四十或更多, 令人訝異的是
這維護成本深受使用者人數的影響, 越多的使用者發現越多的程式錯誤.”
(這正是我所要強調的)
因為增加越多的使用者, 就會增加考驗程式的方法, 所以使用者越多, 發現的程式
錯誤也越多, 當使用者也是協同發展者時這種效應會再被放大, 每一位使用者以不
同的直覺 , 不同的分析工具, 和不同的角度來標明程式錯誤, 因為這些不同,
“Delphi 效應”似乎真的有作用了, 在個別情況下的除錯工作, 也因這些不同而
減少重複出力的可能.
所以, 以程式發展者的眼光看來, 增加更多的 beta 版測試者也許不會減少目前藏
在深處的程式錯誤的複雜度, 但可以增加某位除錯者以他的工具程式找到這個程式
錯誤的機會, 而這個程式錯誤對這位除錯者來說是淺顯的.
Linus 也在這種方式上下了賭注. 因為程式都會有錯誤, Linux 核心程式
以一種特別的方式來定出版本號碼, 讓使用者可以選擇要用上一個比較穩定的版本
, 還是選擇錯誤風險比較高的新版來使用新功能. 這個策略尚未正式為大部分的
Linux 高手所採行, 但是它也顯示出一個事實, 就是使用者可做選擇使得這兩種版
本都更有吸引力.
5. 今花非昨花? (When Is A Rose Not A Rose?)
由 Linus 行為的研究中, 我們得到了一個能解釋他為什麼成功的理論, 所以我想
要在我的新專案 (當然不如 Linux 核心程式的複雜和雄心勃勃) 中來測試這個理
論.
但我做的第一件事情是大力重組和簡化 popclient 的程式, Carl Harris 的實作
非常紮實, 可是卻像許多的 C 程式師一樣, 含括了一種不必要的複雜, 他以程式
碼為主, 資料結構為輔, 因此程式碼看起來漂亮, 但資料結構卻很特殊, 甚至可
以說是醜陋的 (至少以這位老資格 Lisp 高手的高標準而言).
然而, 我重寫程式除了改良原來程式碼和資料結構的設計外, 還有其他目的, 就是
把它發展到我可以完全瞭解, 否則負責修補你不懂的程式是一件很無趣的事.
專案進行的第一個月, 我簡單地依循著 Carl 原來基本設計的用意, 第一個重大的
改變是我加入 IMAP 協定的支援, 我重組原來處理協定的程式, 改成一個較為通用
的驅動程式再加上三個驅動它的方法表 (即 POP2, POP3 和 IMAP). 這個
改變闡釋了一個廣義的原則, 特別在像 C 這種先天上未提供動態資料型態的
程式語言, 程式師們最好謹記在心:
[格言 9] 聰明的資料結構配上笨拙的程式碼要比相反的組合好.
9. Smart data structures and dumb code works a lot better than the
other way around.
[譯注] 相反的組合指笨拙的資料結構配上聰明的程式碼.
Brooks 在 The Mythical Man-Month 的第九章中也說: “光給我看你的 [程式碼],
而不給我看它用的 [資料結構], 我會一頭霧水. 給我看你程式的 [資料結構]
, 我通常不需要再看你的 [程式碼], 因為已經夠明白了.”
事實上, 上述的這段話他是用 “流程圖”和 “表格” 這兩個名詞, 但由於
三十年間專業術語/文化的變遷, 這些名詞的意義幾乎是相同的.
1996 年的九月初, 從零開始工作約過了六週, 我開始在想是否要幫 popclient 取
個新名字, 畢竟 popclient 已不僅僅是單純的 POP 協定客戶端程式, 但我遲疑了
, 因為 popclient 的設計並無真正重大的改變, 我的 popclient 尚須發展出自己
的特色.
當 fetchmail 可以把抓下來的信直接轉送到 SMTP 的接收埠時, 終於和以前不一
樣了, 至於 fetchmail, 我稍待會再說明. 我之前說過要用這個專案來測試關於
Linus 成功的理論, 也許你會問我到底要怎麼做呢? 我用下面幾個辦法:
1) 我儘早並經常發表新版本 (幾乎至少每十天就發表一次, 甚至在發展的高
峰期, 一天一次)
2) 對於每一位與我討論 fetchmail 的人, 我把他們列入 beta 測試者的名單
, 所以名單越來越長.
3) 每當我發展出新版本, 一定發出像聊天般的通知給 beta 測試者名單上的
人, 鼓勵他們一起來參與這個專案.
4) 而我也總是傾聽 beta 測試者的心聲, 詢問他們對於這個程式的設計上有
無意見, 並且回應他們送來對程式的修補和回饋.
在採用上述的辦法後, 立即就得到了報償, 自從這個專案開始以來, 我所收到關於
程式錯誤的回報, 其品質足以令許多的程式發展者羡慕, 這些回報甚至還常常附上
不錯的修補辦法. 因而我做了關鍵性的思考, 我收到了使用者的來信, 得到了關於
新增智慧型功能的建議. 這說明了:
[格言 10] 如果你視 beta 版測試者如同你最珍貴的資源, 那麼他們會以此做為回報.
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 達到成功的方法中, 有趣的是一張薄薄的 beta 版測試者名單, 也就是
fetchamil 之友的名單, 當我在寫這支程式時, 有 249 位, 然後每週增加 2 到 3
位.
這張名單中的成員人數最多時幾乎到達三百, 不過, 當我在 1997 年 五月底審訂
這張名單時, 其中的成員已經因為一個有趣的原因而開始減少, 好幾位告訴我他們
要停訂 “fetchmail 之友”, 因為他們覺得 fetchmail 已能滿足他們的需求,
已經不再需要收到 “fetchmail 之友”. 也許這是成熟的市集模式專案的
正常生命週期中的一部份.
6. Popclient 變成 Fetchmail (Popclient becomes Fetchmail)
這個專案真正的轉捩點發生在 Harry Hochheiser 送給我他寫的一部份程式,
這部份的程式會把郵件轉送到客戶端機器上 SMTP 的接收埠, 我立即瞭解到
這個特色若有穩定的實作, 那麼 fetchmail 中其他的郵件傳遞模式都可以
廢除了.
有幾個禮拜, 其實我一直在扭曲 fetchmail 而不是真的改進它, 因為它
使用介面的設計雖然能提供服務, 但卻不夠高雅, 並且有太多非必要的選項
成為整個程式的累贅, 尤其是要把取回的郵件存成郵件檔或輸出至螢幕的選項
對我造成了相當的困擾, 可是我卻也說不出個所以然來.
當我思考郵件改由 SMTP 轉送這個作法時, 才發覺到原來的 popclient 包攬
太多事了, 過去它被設計成郵件轉送代理 (MTA) 兼郵件遞送代理 (MDA), 若
藉由 SMTP 轉送郵件, 那它可以完全不管郵件遞送, 單純地負責郵件轉送, 只
要把郵件轉給像 sendmail 這樣的郵件遞送程式就可以了.
在有支援 TCP/IP 通訊協定的平台, 幾乎可以保證第 25 號埠 (SMTP 用) 早
就在那裡等了, 為什麼還要和設定郵件遞送代理組態或設定郵件檔的上鎖附加
模式這些問題糾纏呢? 尤其這樣做可以保證取回的信件看起來像發信人透過
SMTP 傳送一樣, 而這正是我們想要的.
在這裡給我們上了好幾課, 第一課是, 這個透過 SMTP 轉送的巧思是從我仿效
Linus 的方法以來, 所得到最大的收穫, 一位使用者提供了絕佳的主意, 而我
所必須做的已經蘊涵在其中.
[格言 11] 體認你使用者提供的巧思, 以獲取好點子, 有時候越後到的越好.
11. The next best thing to having good ideas is recognizing good ideas
from your users. Sometimes the latter is better.
你將會發現一件很有趣的事: 如果你很誠實並很自謙地知道你欠人多少, 那麼
全世界都會認為你發明了全部, 而且對你先提出的天才創作, 也會以為你非常
謙虛, 這些我們可以在 Linus 身上得到印證.
(1997 年 8 月的時候, 當我在 Perl 會議上發表這篇論文時, Larry Wall 坐在
前排, 我唸到上一行時, 他叫了出來, 以一種復興宗教的神情, 喊著: “兄弟,
告訴他們, 告訴他們吧!”, 全場的聽眾都笑了, 因為他們知道這也發生在這位
Perl 的原創者身上.)
我以同樣的精神進行這個專案, 經過短短幾週的時間, 我開始得到類似的讚美,
這些讚美不只來自 popclient 的使用者, 也來自該得到這種讚美而卻未得到的
人, 我保留了一些感謝函, 也許當我懷疑我人生的意義為何時, 可以再看看這
些信 :-).
但除些之外, 這裡還有兩課更基礎, 不具政治性, 更適合所有設計的一般情形:
[格言 12] 通常, 最適切和最有創意的解題法來自發覺自己對問題原先的觀念是錯誤的.
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) 以 (1) 當成預設模式.
(3) 丟棄其他遞送模式的程式碼, 尤其是遞送至郵件檔及遞送至標準輸出.
我對第 (3) 步遲疑了一些時候, 因為擔心會嚇走長久以來 popclient 的使用者,
因為他們一直倚靠另一種遞送機制, 理論上他們可以立即以 .forward 檔來達到
同樣的效果而不靠 sendmail 程式, 事實上這個轉換可能含糊不清.
但當我真的去做, 結果證明益處極大, popclient 驅動程式中 ?? 的一段可以
消失了, 設定也變得簡單多了 — 不用再屈就系統的 MTA 程式及使用者的郵件
信箱檔, 也不再需要擔心底層的作業系統是否支援檔案上鎖.
而且唯一丟掉郵件的可能也不見了, 如果你指定要把郵件送到某個檔案而磁碟空間
又滿了, 那麼你的郵件就丟掉了, 然而由 SMTP 轉送信件的話, 則不會發生這種事
, 因為 SMTP 的接收者除非將信息送達, 或至少先暫存起來待會再送, 才會回覆成
功給發信者.
並且效能也改進了 (如果只跑一次, 你大概不會有感覺). 另一個有意義的好處是
使用說明變得更簡單了.
稍後, 為了要處理某些模糊的狀況, 如動態 SLIP, 我必需讓使用者可以指定本地
端要用那一個 MDA 程式來送達郵件, 我發現了一個更簡單的方法.
這寓意是什麼呢? 當你可以丟掉程式中老舊的特色而又不失掉效力, 那就別遲疑.
Antoine de Saint-Exupery (當他還不是經典童書的作者前, 他當過飛行員和飛
機設計師)曾說:
[格言 13] 設計上完美, 不是 “沒有東西能再被加入”, 而是 “沒有東西能再被移出”.
13. “Perfection (in design) is achieved not when there is nothing
more to add, but rather when there is nothing more to take away.”
[譯注] 1. “小王子” 就是 Antoine de Saint-Exupery 的作品.
2. 這句格言也曾在 “Modern Operating System” 一書中被
Andrew S. Tanenbaum 引用來說明作業系統微核心的設計哲學.
當你覺得做對了, 那麼你的程式碼越來越好, 越來越簡潔, 在這個過程中,
fetchmail 的設計終於和先前的 popclient 不同了, 而有了自己的特點.
該是這個程式改名字的時候了, 新的設計看起來比舊的 popclient 更像 sendmail
, 新的 popclient 和 sendmail 都是 MTA, 只是 sendmail 把郵件 “推” 出去
給 SMTP 收信程式, 再送達使用者, 而新的 popclient 則是把郵件 “拉” 回來
給 SMTP 收信程式, 然後再送出, 所以兩個月後, 我把它更名作 “fetchmail”.
7. Fetchmail 成長了 (Fetchmail Grows Up)
我把 fetchmail 設計得雅潔而新穎, 程式本身也跑得很好, 因為我天天都在用,
並且開始有一些 beta 版測試者加入, 這情形使我逐漸瞭解, 我已不再是為了
可能讓少數其他人能得到一些便利, 而在進行用處不大的程式棈解, 我已經為
每一位有台 UNIX 機器, 上面跑 SLIP/PPP 來取得電子郵件的玩家們, 寫了一個
真正滿足他們需要的程式.
因為藉 SMTP 埠轉送郵件的這個特色, 潛在使得 fetchmail 足以成為同領域的
殺手級程式, 在同類的典型程式中, 它已經夠資格佔到適當的位置, 使得其他
程式不是被捨棄就是幾乎被遺忘.
我認為沒有人能真的看準或計畫會有這樣的結果, 以有力的設計想法投入這個專案
, 之後的結果似乎是無可避免的, 自然的, 甚至是注定的, 要追求像這樣好的想法
, 唯一的方法就是先擁有許多的想法, 或者以工程上的判斷去取得別人好的想法,
而在此處這個想法的利用已超出原創者的想像.
Andrew Tanenbaum 在 386 上造出了一個簡單的原生 UNIX 系統, 他原先的想法只
是用來作為教學的工具, 但 Linus Torvalds 把這個系統 Minix 的觀念拓展開來,
更進一步, 已經超過 Andrew 當初能夠想像到的發展, 並且成長出一些令人讚嘆
的事物. 我用一樣的方式 (雖然規模較小), 由 Carl Harris 和 Herry Hocheiser
那裡得到一些想法, 然後把它們發揚光大. 在人們的想像中, 歷史上的原創者都是
天才, 而我們兩位都不是, 但是大部份的科學發展和軟體發展工作, 完成者不是
天才原創者, 反而是行家們.
Linux 和 fetchmail 的成果都是一樣令人興奮, 事實上這就是每一位高手追求的
成功, 這些成果指示我應該把標準設得高一點, 把 fetchmail 發展到我所能想像
的理想, 我已不只是為自己的需求而寫, 也為其他人所需要的特色而寫, 並且還要
同時保持程式簡單和強健.
第一個加入的重大特色是 “多人共用一信箱” 的支援 — 這個功能可以抓下累積
在同一個群組信箱中, 而屬於不同使用者的信件, 然後再分送給原來的個別
收信人.
我決定加入 “多人共用一信箱” 的支援, 部分是因為有一些使用者們嚷嚷著他們
需要它, 但主要是因為我認為它會迫使我以更通用的法則來處理郵件頭的地址,
並藉此除去 “一人一信箱” 功能程式碼中的錯誤, 而我的確也做到了. 為了讓
程式能按 RFC 822 中的規定來檢查信息的語法 , 花了我相當長的時間, 不是
因為規定的個別片段難以理解, 而是因為它包括了成堆相互依賴的瑣碎細節.
[譯注] RFC 822 是 “Standard for the Format of ARPA Internet Text Messages”.
結果 “多人共用一信箱” 的支援的確是一個漂亮的設計, 我是怎麼知道的呢?
[格言 14] 任何的工具以我們所知道的方法來使用都會有用, 但一個真正了不起的工具會以你從未想過的使用方法來發揮它的功能.
14. Any tool should be useful in the expected way, but a truly great
tool lends itself to uses you never expected.
支援 “多人共用一信箱” 的 fetchmail 有一種意枓外的使用方法, 就是在以
SLIP/PPP 連線方式連上 ISP 的客戶端執行 “郵遞討論名單” (mailing list),
因為它可以配合客戶端的多使用者共用 ISP 上同一信箱 (用別名 — alias —
的方法), 讓每個使用者都能在名單上, 這表示我們可以在個人的電腦上, 透過
一個 ISP 的帳號, 來維護一個郵遞討論名單, 而不必持續連著 ISP.
另一個來自我 beta 測試版的使用者的重要需求是接受 8 位元 MIME 郵件格式,
這很容易做到, 因為我過去一直都小心地保持每一個字元碼都是完整的 8 位元,
並非我未卜先知, 而是我遵從另一條法則:
[格言 15] 寫作任何的通信閘軟體時, 要盡可能地不去擾動到通訊的資料流,
— 並且絕對不要丟掉其中任何的資訊, 除非接收方強迫你這麼做.
15. When writing gateway software of any kind, take pains to disturb
the data stream as little as possible — and *never* throw away
information unless the recipient forces you to!
如果我當初沒有遵從這項原則, 那麼 8 位元 MIME 的支援勢必難以加入並多錯,
所以我需要做的只是研讀 RFC 1652, 然後加入顯然得知的程式碼以產生 MIME
的標頭.
[譯注] RFC 1652 是 “SMTP Service Extension for 8bit-MIME Transport”
一些歐洲的使用者要我在程式中加入選項, 用來限制每次連線取回郵件的數目
(這樣他們才能控制昂貴的電話線路連線花費), 我拒絕了許久, 甚至到現在, 我
對這個選項的加入仍感到不太愉快, 但假如你是在為全世界寫程式, 那麼
你就應該聽取你客戶們的意見 — 這個原則不會改變, 因為他們會以金錢之外
的形式給你報酬.
8. 由 Fetchmail 學到的一些經驗 (A Few More Lessons From Fetchmail)
在我們回頭討論一般軟體工程的議題前, 由 fetchmail 得來的一些特殊教訓值得
深思.
Fetchmail 設定檔 (rc file) 的語法包括可要可不要的關鍵字, 這些如 “噪音”
般的字眼會被語法分析程式忽略, 這些字的加入, 使得設定檔的語法和英文很
接近, 和傳統中簡潔的 “關鍵字 — 設定值” 配對表示法 (把噪音字去掉就可以
得到) 比較起來, 要來得容易閱讀.
這個教訓開始於某一個夜晚的實驗, 我注意到設定檔中的宣告語法可以組成一個
迷你的祈使語言. (這也是為什麼我把原來 popclient 中的關鍵字 “伺服器”
(server) 改成 “詢問” (poll)).
對我而言, 如果把這個祈使語言弄得更像英文, 那會讓 fetchmail 更易於使用,
雖然我現在信服如 Emacs, HTML, 及許多資料庫引擎制定出來的模範語言, 在
正常情況下我也不那麼迷英文的語法.
傳統的程式師喜歡非常精確而簡潔的設定語法, 不希望有任何冗餘在其中, 這是
因為早期的電腦計算資源昂貴而遺留下來的觀念, 他們認為語法分析的過程要
節約計算資源, 並要儘可能的簡單. 英文的語句大約有百分之五十的冗餘, 所以
不利於做為設定語法.
但這並非我在正常的情況下不用英文語法的原因, 我在此提及是為了推翻像英文
的語法不適合作設定語法的論點, 當中央處理器和記憶體都變得便宜時, 設定語法
的簡潔已不再是我們的目標, 現在的情況是: 一個電腦語言中符合人性易於使用
的重要性已超過節約電腦的計算資源.
然而還是有好幾個地方要小心, 其中之一是語法分析過程變得比較複雜的代價
— 你不會想把這個特點 (使用像英文的設定語法) 變成程式錯誤的來源及
使用者的疑惑處. 另一個是當我們要訂出一個像英文的語言時, 通常需要做些
修改, 表面上看起來修改過後的語法可重組出自然語言, 但可能也會因修改過
以致於和傳統的設定語法一樣, 令人感到疑惑. (我們可以在許多所謂的第四代
程式語言和商業用的資料庫查詢語言看到這個現象.)
Fetchmail 的控制語法看起來免除了這個問題, 因為我嚴格地限制控制語法的
範圍, 它不是一個以通用為目的的語言, 它簡單並不很複雜, 所以在極小的英文
子集和真正的控制語言之間的相混處很少, 我認為這裡還有一個更廣義的教訓:
[格言 16] 當你設計的語言不是嚴謹到 “完全 Turing”, 你可以採用比較平易的語法.
16. When your language is nowhere near Turing-complete, syntactic
sugar can be your friend.
另有一個教訓是關於含糊的保密性, 有一些 fetchmail 的使用者要我修改程式,
以把經保密處理的通行碼儲存於設定檔內, 這樣子一來, 偷窺者就沒辦法看到
真正的密碼了.
我並沒有這麼做, 因為這個做法並不能達到真正的安全, 能拿到讀取你設定檔
權限的人, 也能以你的身份執行 fetchmail — 如果你的通行密碼經保密處理
存在設定檔中, 他們可以由 fetchmail 中取得解碼程式來得到你真正的通行密碼.
如果我把程式改成可以在 fetchmail 的設定檔中儲存保密的通行密碼, 那會給
認為這並不難的人們對保密性的錯誤觀念. 一般的守則應該是:
[格言 17] 一個保密系統是否安全依存於它隱藏的秘密, 注意不要有“虛擬秘密”.
17. A security system is only as secure as its secret. Beware of
pseudo-secrets.
[譯注] 以 fetchmail 為例, 隱藏的秘密是指 “通行密碼”, “虛擬秘密” 是指把通行密碼編碼後存於設定檔中 .
9. 市集模式必要的條件 (Necessary Preconditions for the Bazaar Style)
早先看過這篇論文的書評家和試讀者都提出同樣的問題, 那就是以市集模式發展
軟體, 獲得成功的先決條件為何? 包括專案領導人的資格, 程式碼到什麼樣的
程度, 才對社群發表並開始成立協同發展團隊,
相當明顯的, 任何人無法以市集模式建立軟體基礎, 但是可以用市集模式來測試
, 除錯, 改進軟體, 在一個專案的起始點很難運用市集模式, Linus 沒試過,
我也沒有. 專案初始的協同發展團隊需要有一些東西可以測試, 可以執行.
當你開始召募專案團隊時, 你必須能提出大致合理的保證, 你的程式不需要運作
得很好, 它可以暴力, 有錯, 不完整, 及註解貧乏, 只要它可以使潛在的協同
發展者相信, 這個程式在可預見的未來大有可為.
Linux 和 fetchmail 公開發表時都具有強健及吸引人的設計, 許多人認為這和
我所報告的市集模式有所不同, 並以為這樣的設計很重要, 甚至進一步做出一個
他們的結論 — 高度的設計直覺和聰明是一個專案領導人不可或缺的特質.
但是 Linus 的設計由 UNIX 而來, 我的設計由原先的 popclient 而來 (雖然
它後來改變甚大, 比例上說來還超過 Linux), 所以市集模式專案的領導人或
協調者真的需要格外的設計技巧? 或者能提昇別人的設計技巧呢?
我想對於專案協調者是否能做出耀眼的設計並不重要, 最重要的是協調者是否能
認知別人在設計上的好點子.
Linux 和 fetchmail 都證明了這件事, Linus 這位仁兄如同之前所討論的,
他並不是偉大的創新設計師, 但他展現了另一種卓越的技巧, 即認同別人好的
設計點子, 且將這些好的設計整合到 Linux 的核心中. 而我之前描述過
fetchmail 最有力的設計 (藉 SMTP 轉送郵件) 也來自他人.
這篇論文的早期讀者指出: 我有低估市集模式專案中創造力的重要性, 因為我自己
本身就已具備了許多的創意, 所以將此視為理所當然. 這真是抬舉我, 也許這說法
有幾分真實, 相對於寫程式及除錯, 設計應該是我最強的本領.
但以聰明和創意來設計軟體的問題在於 “習慣的養成” — 當你應該保持程式的
強健和簡潔時, 反而把它弄得花俏而複雜, 我曾因犯了這個錯以致於把專案搞砸
了, 但我在 fetchmail 這個專案中小心地控制, 避免發生這種錯誤.
所以我相信 fetchmail 專案的成功部分的原因是我防止設計上 “聰明” 的傾向
, 這個論點 (至少) 已經反駁了設計上的創意是市集模式專案成功的基本條件.
以 Linux 來說, 假設 Linus Torvalds 在發展程式的過程中, 試圖在作業系統
的基本設計上力求創新, 那麼我們現在已有的 Linux 核心程式會如此穩定和
成功嗎?
當然, 任何想起始一個市集模式專案的人, 應該具備基本程度的設計能力和寫程式
技巧, 但我認為如果他們有認真想過, 那他們的程度應該已在低標之上. 開放性
原始碼社群對於名譽的重視, 給予其中的人們一種微妙的壓力, 如果無法勝任專案
後續的發展, 那麼就不會想去起始, 直到目前, 這種慣例似乎仍運作得很好.
還有一種技巧, 通常與我們不會把它和軟體發展聯想在一起, 但我認為這和市集
模式專案中聰明的設計一樣重要, 也許還更重要, 就是市集模式專案中的協調者
或領導人必須有人緣和好的溝通技巧.
這應該很明顯, 為了召集發展社群, 你需要吸引人們, 讓他們對你所做的有興趣,
並且保持他們加入後工作愉快. 技術上的末節很難達成這樣的目標, 更難以完成
整個專案, 你個人的人格特質也和專案習習相關.
Linus 是一位好人, 令人喜歡並樂於幫助他, 這不是巧合, 我精力旺盛, 活潑
外向, 喜愛為群眾們工作, 並具有喜劇演員的本能, 這也不是巧合, 為了讓
市集模式專案順利運作, 如果能用一點小技巧來吸引人們, 那幫助會很大.
10. 開放性原始碼軟體的社會關聯性 (The Social Context of Open-Source Software)
我們談過: 最好的程式起自於作者個人要解決他每天的切身之痛, 然後因為
這通常也是許多人的痛處, 所以這個程式便開始散佈, 這讓我們把 [格言 1] 用
另一種更有用的說法來陳述:
[格言 18] 為了要解有趣的問題, 開始找你感興趣的問題吧!
18. To solve an interesting problem, start by finding a problem that
is interesting to you.
所以 Carl Harris 寫了早期的 popclient, 而我寫了 fetchmail, 然而這句格言
應早已為人所知許久, Linux 和 fetchmail 發展的歷史似乎要讓我們注意到這
有趣的一點, 就是軟體發展的下一步 — 使用者和協同發展者組成了龐大而活耀
的社群, 帶動軟體的演化.
在 <<人-月的迷思>> 一書中, Fred Brooks 觀察到: 程式師的時間具
不可替換性, 在一個進度已經落後的專案中, 加入更多的發展者只會使進度
更加落後, 他討論到一個專案的複雜度和人員間溝通的代價以參與發展人數的
平方倍成長, 而完成的進度只隨人數做線性成長, 這個聲明自從發表以後,
就被稱為 Brooks 定律且被視為真理, 但假如 Brooks 定律主宰了一切,
那麼根本就不可能有 Linux 這個作業系統.
Gerald Weinberg 的經典著作 <<計算機程式寫作之心理學>> 中有
後見之明, 提出對 Brooks 定律極為重要的修正, 在 Weinberg 對 “無私程式
寫作” 的討論中, 他觀察到在軟體工作室中, 如果程式師們不會只 “自掃門前雪
”, 反而鼓勵其他的程式師去看他們的程式, 以找出錯誤或提出改進的建議,
那麼程式改善的速度會遠超過每個程式師只顧自己的部分.
也許 Weinberg 的術語選擇不當, 以致於原本該為人所接受的觀念卻未被接受,
當想到用 “無私” 來形容網際網路上的電腦行家, 令人發出微笑, 但我認為他
的論點在今天要比過去更有力.
UNIX 的歷史其實早已準備好我們從 Linux 學到的東西 (以及經由我實驗得證的
事情, 這個實驗經過仔細地仿效 Linus 的方法, 但規模較小), 當大家還認為
寫程式仍然是單打獨鬥的行為時, 真正了不起的行家已經在善用社群的注意力和
腦力. 在一個封閉專案中的程式發展者, 他們只單靠自己的頭腦, 所達成的進度
將落後於知道怎麼搞一個開放專案的發展者, 因為在開放的專案中, 有數以百計的
人從事回報錯誤及改進程式.
但是傳統 UNIX 的世界因為好幾個原因, 以致於無法把這個方法的功效發揮到最大
, 其中包括: 不同版權的法律限制, 商業機密, 市場上的利益等等, 還有一個原因
(算是後見之明) 就是: 當初的網際網路還不夠發達.
在廉價的網際網路來臨之前, 有一些地域性的社群集中在一起, 他們的文化鼓吹著
Weinberg 的 “無私” 程式寫作, 其中的程式發展者可以輕易地吸引許多
有技巧的建言者和協同發展者, 如貝爾實驗室, 麻省理工學院人工智慧實驗室及
加州大學柏克來分校 — 這些地方都是創新的來源, 都帶有傳奇性的色彩,
至今都仍具有影響力.
Linux 是第一個致力於把全世界當成是它智庫的專案, 我並不認為在 Linux 的
孕育期恰好誕生了全球資訊網是個巧合, 而且在 Linux 發展的早期, 網際網路
服務供應商的事業正在起飛, 網際網路的商機主流正在爆發, Linus 是第一位
學習在網際網路普及的情況下, 如何進行新遊戲規則的人.
雖然廉價的網際網路是 Linux 模式演進的必要條件, 但我認為它並非充分條件,
另一個極重要的因素是專案中領導人的領導風格, 以及一群合作的客戶, 其中
有人會被發展者吸引而成為協同發展者, 進而把網路媒體的功能發揮到最大.
但我們要問什麼是領導風格? 客戶是那些人? 他們之間的關係並非依賴權力而建立
— 或者就算是, 強制的領導風格沒辦法帶給我們今天這樣的成果, Weinberg 引用
十九世紀俄國無政府主義者克魯泡特金自傳中 “紀念一位革命家” 的一段,
來解釋這個問題:
“因自幼在擁有佃農的地主家庭中長大, 當我的生命開始活躍時, 就像那時所有的
年輕人一樣, 我們非常相信命令, 指使, 責罵以及處罰等等行為的必要性, 但當
我早期必須管理正式的企業時, 我要和自由的人打交道, 任何錯誤可能最後都會
引發嚴重的後果, 我才開始欣賞 ‘命令和規定’ 與 ‘建立共識’ 兩種行為間的
不同之處, 前者在軍事體系中效用極佳, 但在真實的生活中卻一文不名, 真實生活
中的目標, 是在許多人同心協力下達成的.”
“許多人同心協力” 正是像 Linux 這樣的專案所需要的 — “命令法則”
並不適用於無政府主義者天堂 (我們叫它網際網路) 的志願工作者, 為了
更有效的運作和競爭, 想要領導與他人合作的專案的電腦行家, 必須學習如何
吸引和激勵有興趣的社群, 並且是在克魯泡特金所建議的 “建立共識” 原則的
模式下進行, 他們也必須要學習去使用 Linus 定律.
稍早我提及 “Delphi 效應” 是為了它可能可以解釋 Linux 定律, 但在生物學和
經濟學中的自我調適性系統中, 有更多類似的地方可以更有力地印證它, Linux 的
世界從許多方面看來, 像是一個自由的市場或生態, 由一群個體所組成, 這些個體
以一種自發性的自我更正程序, 試著去發揮他最大的功用, 所發揮出來的功用比起
集中式的規畫要來得更精巧, 更有效率, 這種方式正是在尋求 “建立共識”.
Linux 行家們發揮到最大的功用不是典型的經濟價值, 而是在行家中得來無形的
自我滿足和榮譽, (你也許可以認為他們的動機是 “利他”, 但這忽略了一項事實,
就是利他主義只是利他主義者自我滿足的一種型式), 以這種方式進行的志工文化
並非真的不尋常, 就我長期參加的一個科學小說迷俱樂部來說, 它不像電腦行家迷
俱樂部那麼明顯地以 “egoboo” (在同好圈裡強調某人的榮耀) 做為驅動志工的
力量.
Linus 在 Linux 專案中, 成功地坐上專案守門員的位置 (這個專案大部份的工作
都由其他人所完成), 也成功地培養專案的利基, 直到它可以自我維持, 這顯示
Linus 精確地抓住克魯泡特金所說 “建立共識” 的精神, 用這個似經濟學的觀點
來看 Linux 的世界, 讓我們知道 “共識” 是如何作用的.
我們可以把 Linus 的方法, 視作一條開創有效率市場的路 — 以最強韌的方式
聯合個別的行家來達成困難的目標, 這些目標只有在持續的合作下才能達成.
在 fetchmail 的專案中 (雖然規模比較小), 我已經展示出 Linus 的方法可以
用在別的專案, 並同樣有好的成果, 或許我有意地, 更有系統地利用他的方法.
許多人 (尤其是不信任自由市場的人) 以為重視自我的個體文化會造成分裂,
自掃門前雪, 浪費, 私密, 和敵對, 只要舉一個簡短的實例, 就可以很明顯地
證明這個看法是錯的, 這個例子就是 Linux 相關的說明文件的多樣, 品質, 和
深度都相當令人驚訝, 程式師不喜歡寫說明文件似乎是金科玉律, 但 Linux 的
行家們是如何寫出這麼多的文件呢? 很明顯地, Linux 重榮譽的自由市場運作
得要比商業軟體生產者重金投資的說明文件撰寫公司好.
Fetchmail 和 Linux 這兩個專案都展示出藉由適當地回報許多行家, 優秀的發展
者或協調者能利用網際網路, 獲得許多協同發展者, 但不致讓專案因混亂而失敗,
所以針對 Brook 定律, 我提出以下的反駁:
[格言 19] 假如專案發展協調者擁有至少跟網際網路一樣好的媒體, 而他也不靠強制力來領導, 那麼一群人必定勝過一個人.
19. Provided the development coordinator has a medium at least as good
as the Internet, and knows how to lead without coercion, many heads
are inevitably better than one.
我認為開放性原始碼軟體的將來屬於知道如何進行 Linus 遊戲規則的人, 屬於
離開教堂擁抱市集的人, 這並不是說個人的眼光和明智不再重要, 而是我認為
開放性原始碼的軟體的優勢將屬於一種人, 他以個人的眼光和明智開始一個專案,
並且之後能有效地號召有興趣的志工群來加入他的專案.
也許不只是開放性原始碼的將來, 非封閉性原始碼的發展者也能吸引 Linux 社群
的智庫到他們的問題上, 很少有人付得起 fetchmail 專案中超過兩百位的貢獻者.
也許最後開放性原始碼軟體會贏, 但不是因為合作是善的, 而囤積是惡的, (可能
你相信後者, 但 Linus 和我則否) 而是因為封閉原始碼的世界無法在演化的角力
中勝過開放性原始碼的社群, 開放性原始碼專案投入純熟的人時要比封閉性原始碼
的專案來得多.
11. 致謝 (Acknowledgements)
(中譯略)
This paper was improved by conversations with a large number of people
who helped debug it. Particular thanks to Jeff Dutky
<dutky@wam.umd.edu>, who suggested the “debugging is
parallelizable” formulation, and helped develop the analysis that
proceeds from it. Also to Nancy Lebovitz
<nancyl@universe.digex.net> for her suggestion that I emulate
Weinberg by quoting Kropotkin. Perceptive criticisms also came from
Joan Eslinger <wombat@kilimanjaro.engr.sgi.com> and Marty Franz
<marty@net-link.net> of the General Technics list. I’m grateful
to the members of PLUG, the Philadelphia Linux User’s group, for
providing the first test audience for the first public version of this
paper. Finally, Linus Torvalds’s comments were helpful and his early
endorsement very encouraging.
沒有留言:
張貼留言