# 二十四、絕不去做的事情,第一部
Netscape 6.0第一個公開的beta版終于出來了。5.0版從來沒出現過,最后一版重大改版是 大約三年前發行的4.0版。在Internet世界里三年的時間長得可怕。就在這段時間中, Netscape只能無望地坐看市場占有率直線下降。
我這樣批評他們在兩個版本間等了很久,似乎有點惹人厭。他們并不是故意的這樣的吧。真有人會故意這樣做嗎?
呃,沒錯,他們是故意的。他們做了一個每家軟件公司都可能犯的一個最糟的策略錯誤: 他們決定把程序從頭重寫過。
Netscape并不是第一家犯這種錯的公司。Borland買下Arago,想把它變成Windows版的dBase 時就犯了同樣的錯。這個注定失敗的項目用了很長的時間開發,長到讓它被微軟的Access 徹底打敗。Bor land后來又重蹈覆轍整個重寫QuattroPro,還想拿重寫的新功能來嚇人。微 軟幾乎也做了相同的蠢事,想要在一個叫Pyramid的專案里重寫Windows版的Word,不過這個 案子己經結束,并且消失在塵土之間。微軟很幸運,他們從未停止使用原有的程序代碼庫, 所以一直有東西可以推出。因此這個錯誤只成為財務上的問題,而不是策略上的災難。
我們都是程序員。而程序員在內心其實是個設計者,他們每到一個地方第一件事,就是先把 一切鏟平然后創造偉大的事物。我們對修補改進和種種花床的漸進式革新不會感覺興奮。
程序員總想把舊程序丟掉重新開始,其中的原因很微妙。他們會認為舊的程序是一團亂,不 過下面這有趣的觀察指出他們可能是錯的。他們會認為舊程序一團亂的直正原因是一個很基 本的程序設計原理:
讀程序比寫程序困難。
這就是程序再使用如此困難的原因。這也說明為何團隊中每個人都喜歡用不同的函數把字符 串切成字符串數組。他們自己寫自己的函數,因為這樣比去弄懂舊程序更簡單而有趣。
依據這個原則推論,你可以詢問任何一個現役程序員正在用的程序代碼。幾乎每一個人都會 告訴你:「這真是一團亂,我真想把它丟掉重新開始。」
為什么會說是一團亂呢?
「嗯,」他們說:「看看這個函數。有兩頁那么長耶!這些東西都不屬于這里的!我真不知 道里頭一半的API是叫來做啥的。」 在Borland新的Windows版電子表格軟件推出前,該公司有意思的創辦人Philippe Kahnwas 在媒體上到處吹墟,說些QuattroPro是整個重寫的,所以比微軟Excel好上多少倍等等的鬼 話。全新的原始碼哦!好像原始碼會生銹一樣。
新程序代碼比舊程序代碼好的想法顯然是很荒唐的。舊程序代碼己經被用過也被測試過。很 多問題都己被找出來并被修好。它并沒有什么問題,不會因為在你的硬盤里放久了就生出新 的問題。你錯得離譜了,寶貝!軟件應該要像舊奔馳一樣,光在放在車庫里就會生銹嗎?軟 件應該要像泰迪熊那樣,不用全新的材料做就不好嗎?
回到那個兩頁長的函數吧。是的,我了解這只是個顯示某個窗口的簡單函數,不過卻多了很 多怪東西而且沒有人知道為什么。嗯,我會告訴你原因:它們是問題的修正。其中一個是南 西在沒有Internet Explore「的計算機上安裝時寫的。另一個是對付內存不足時的問題。還 有一個是要應付檔案放在軟磁上,用戶卻中途抽掉磁盤的狀況。LoadLibrary呼叫很難看, 不過卻能讓程序在舊版Windows 95上也可以執行。
里面每個問題都是在真實世界使用好幾個星期之后才發現的。而程序員可能也花了好幾天才 在實驗室重現并予以修正。問題看起來很多,可是解決方法可能只有一行程序,甚至可能只 有幾個字符,可是光兩個字符的背后有著許多的時間和心血。
當你把程序代碼丟掉從頭重寫時,其實是把這所有的知識都丟掉了。這所有己修正的問題, 好幾年的寫程序的成果。
你會讓出市場領導地位。你會把兩三年的時間當禮物送給競爭者。相信我,軟件的一年可是 很長的。
你會讓自己陷入一個極端危險的位置,到時候會有很多年都只能發行舊版程序,完全無法因 應市場需求的新功能而改變策略,因為你沒有可以發行的程序。這段時期最好還是把公司收 起來算了。 你會浪費大量的資金去撰寫己有的程序。
有代替的方案嗎?大家都同意Netscape的舊程序似乎真的非常糟。嗯,或許它真的很糟,不 過你知道嗎?它還是能在世界上數不清的計算機系統上運作的還不錯。
當程序員照他們一貫的作風,說他們的程序是團神圣的垃圾時,其實里頭會包含三種錯誤的 理由。
首先是架構上的問題。程序代碼并沒有被正確地安排。網絡聯機的程序代碼會在莫名奇妙的 地方自己顯示對話盒;而這應該是由使用接口來處理才對。你可以小心的搬動程序代碼,重 構并修改接口,一次一個地解決這些問題。你可以找一個程序員小心處理好,再把所有修改 一次放回版本管理系統,就不會影響到其他人。即使很重大的架構修改,都不必丟掉程序代 碼就可完成。我們花了好幾個月重整Juno項目的架構:只是把東西搬來搬去,把程序代碼清 理干凈,建立合理的基脆別,并且在模塊間建立明確的接口。不過我們非常小心的處理現 有的程序代碼庫,結果沒有產生新問題也不必把還能用的程序丟掉。
程序員認為程序代碼一團糟的第二個原因是效率不好。謠傳Netscape的成像程序很慢。不過 這只牽涉整個項目的一小部份,你可以優化甚至重寫這一小部份,并不需要把所有程序都重 寫。在優化速度時,抓到1%的工作重點可以得到99%的效果。
第三個理由是說程序代碼他X的丑。某個我做過的案子真的有一個叫FuckedString的數據類 型。另一個案子則是在開始時在成員變量名字前加底線1_’,后來卻改用比較標準的1m_’。 結果一半的函數是用開頭而另一半是用1m_’開頭,看起來很丑。坦白地說,這種問題用 Emacs的宏功能五分鐘就解決了,不需要從頭開始。
你一定要記住,在要從頭重新開始時,完全沒有理由相信這次會做得比第一次好。首先你的 程序團隊根本不可能和當初相同,所以并不會真的有「更多的經驗」。你其實只會把大部份
的舊錯重新再犯一次,另外再多加一些舊版本沒有的新問題。
在面對大型商業應用程序時,做了就丟掉是很危險的舊咒語。如果你只是寫程序做做實 驗,想到更好的算法時大可把上星期寫的函數丟掉,這是很正常的。想藉重構讓某個類別更 容易使用,這也不會有任何問題,不過把整個程序都丟掉是個危險的愚行。如果Netscape 真的運用軟件業經驗成熟地管理,就不會把自己害得這么慘了。
- 第一部分 位與字節:編程實踐點滴
- 一、語言的選擇
- 二、深入底層
- 三、joel測試:改進代碼的12個步驟
- 四、每一位軟件開發人員必須、絕對要至少具備UNICODE 與字符集知識(沒有任何例外!)
- 五、輕松寫就功能規格說明書 - 第1節:為什么煩心?
- 六、輕松寫就功能規格說明書 - 第2節:什么是規格說明書?
- 七、輕松寫就功能規格說明書 - 第3節:但是……如何?
- 八、輕松寫就功能規格說明書 - 第4節:技巧
- 九、輕松制訂軟件進度表
- 十、每日連編是朋友
- 十一、難伺候的故障修復
- 十二、軟件開發中的5個世界
- 十三、稿紙原型開發
- 十四、不要被太空架構師所嚇倒
- 十五、開火與運動
- 十六、人員技能
- 十七、源于計算機學科的三個錯誤思想
- 十八、二元文化
- 十九、自動獲取用戶故障報表
- 第二部分 開發人員的管理
- 二十、面試游擊指南
- 二十一、重金激勵害多利少
- 二十、二不配備測試人員的五個首要(錯誤)原因
- 二十三、任務換人有害無益
- 二十四、絕不去做的事情,第一部
- 二十五、冰川下的秘密
- 二十六、漏洞抽象定律
- 二十七、程序設計界的LordPalmerston
- 二十八、評測
- 第三部分 Joel對常態問題的遐想
- 二十九、RickChapman解讀愚昧
- 三十、在這個國家狗是干什么的? 我們有多么天真?
- 三十一、作為哼哈二將,只管去做事
- 三十二、兩個故事
- 三十三、巨無霸麥當勞與天才廚師JamieOliver
- 三十四、沒有什么像IT看起來那么簡單
- 三十五、提防非自主開發綜合癥
- 三十六、策略I:BEN&JERRY公司與AMAZON
- 三十七、策略II:雞與蛋問題
- 三十八、策略III:讓我回去!
- 三十九、策略IV:大件與80/20神話
- 四十、策略V:公開源代碼的經濟因素
- 四十一、墨菲法則肆掠的禮拜
- 四十二、微軟公司是如何敗北API之戰的
- 第四部分 對.NET稍多的評說
- 四十三、微軟精神失常了
- 四十四、我們的.NET對策
- 四十五、請問,我可以使用連接程序嗎