你絕對不應該做的事 之一 Things You Should Never Do, Part I

作者:周思博 (Joel Spolsky)
譯:Paul May 梅普華
Thursday, April 06, 2000
屬於 Joel on Software, https://www.joelonsoftware.com/2000/04/06/things-you-should-never-do-part-i/

Netscape 6.0第一個公開的 beta 版終於出來了。5.0版從來沒出現過,最後一版重大改版是大約三年前發行的4.0版。在 Internet 世界裡三年的時間長得可怕。就在這段時間中,Netscape 只能無望地坐看市場佔有率直線下降。

我這樣批評他們在兩個版本間等了很久,似乎有點惹人厭。他們並不是故意的這樣的吧。真有人會故意這樣做嗎?

呃,沒錯,他們是故意的。他們做了一個每家軟體公司都可能犯的一個最糟的策略錯誤

Upper_West_Side_Brownstones_2.jpg

他們決定把程式從頭重寫過。

Netscape 並不是第一家犯這種錯的公司。Borland 買下 Arago,想把它變成 Windows 版的 dBase 時就犯了同樣的錯。這個注定失敗的專案用了很長的時間開發,長到讓它被微軟的 Access 徹底打敗。Borland 後來又重蹈覆轍整個重寫 Quattro Pro,還想拿重寫的新功能來嚇人。微軟幾乎也做了相同的蠢事,想要在一個叫 Pyramid 的專案裡重寫 Windows 版的 Word,不過這個案子已經結束,並且消失在塵土之間。微軟很幸運,他們從未停止使用原有的程式碼庫,所以一直有東西可以推出。因此這個錯誤只成為財務上的問題,而不是策略上的災難。

我們都是程式師。而程式師在內心其實是個設計者,他們每到一個地方第一件事,就是先把一切鏟平然後創造偉大的事物。我們對修補改進和種種花床的漸進式革新不會感覺興奮。

程式師總想把舊程式丟掉重新開始,其中的原因很微妙。他們會認為舊的程式是一團亂,不過下面這有趣的觀察指出他們可能是錯的。他們會認為舊程式一團亂的直正原因是一個很基本的程式設計原理:

讀程式比寫程式困難。

這就是程式再使用如此困難的原因。這也說明為何團隊中每個人都喜歡用不同的函數把字串切成字串陣列。他們自己寫自己的函數,因為這樣比去弄懂舊程式更簡單而有趣。

Columbus_Ave_Barber_Shop.jpg

依據這個原則推論,你可以詢問任何一個現役程式師正在用的程式碼。幾乎每一個人都會告訴你:「這真是一團亂,我真想把它丟掉重新開始。」

為什麼會說是一團亂呢?

「嗯,」他們說:「看看這個函數。有兩頁那麼長耶!這些東西都不屬於這裡的!我真不知道裡頭一半的API是叫來做啥的。」

在Borland新的Windows版試算表軟體推出前,該公司有意思的創辦人Philippe Kahnwas在媒體上到處吹噓,說些 Quattro Pro 是整個重寫的,所以比微軟 Excel 好上多少倍等等的鬼話。全新的原始碼哦!好像原始碼會生鏽一樣。

新程式碼比舊程式碼好的想法顯然是很荒唐的。舊程式碼已經被用過也被測試過很多問題都已被找出來並被修好。它並沒有什麼問題,不會因為在你的硬碟裡放久了就生出新的問題。你錯得離譜了,寶貝!軟體應該要像舊賓士一樣,光在放在車庫裡就會生鏽嗎?軟體應該要像泰迪熊那樣,不用全新的材料做就不好嗎?

回到那個兩頁長的函數吧。是的,我瞭解這只是個顯示某個視窗的簡單函數,不過卻多了很多怪東西而且沒有人知道為什麼。嗯,我會告訴你原因:它們是問題的修正。其中一個是南西在沒有 Internet Explorer 的電腦上安裝時寫的。另一個是對付記憶體不足時的問題。還有一個是要應付檔案放在軟磁上,使用者卻中途抽掉磁片的狀況。LoadLibrary 呼叫很難看,不過卻能讓程式在舊版 Windows 95 上也可以執行。

裡面每個問題都是在真實世界使用好幾個星期之後才發現的。而程式師可能也花了好幾天才在實驗室重現並予以修正。問題看起來很多,可是解決方法可能只有一行程式,甚至可能只有幾個字元,可是光兩個字元的背後有著許多的時間和心血。

當你把程式碼丟掉從頭重寫時,其實是把這所有的知識都丟掉了。這所有已修正的問題,好幾年的寫程式的成果。

你會讓出市場領導地位。你會把兩三年的時間當禮物送給競爭者。相信我,軟體的一年可是很的。

你會讓自己陷入一個極端危險的位置,到時候會有很多年都只能發行舊版程式,完全無法因應市場需求的新功能而改變策略,因為你沒有可以發行的程式。這段時期最好還是把公司收起來算了。

你會浪費大量的資金去撰寫已有的程式。

Columbus_Ave.jpg

有代替的方案嗎?大家都同意 Netscape 的舊程式似乎真的非常糟。嗯,或許它真的很糟,不過你知道嗎?它還是能在世界上數不清的電腦系統上運作的還不錯。

當程式師照他們一貫的作風,說他們的程式是團神聖的垃圾時,其實裡頭會包含三種錯誤的理由。

首先是架構上的問題。程式碼並沒有被正確地安排。網路連線的程式碼會在莫名奇妙的地方自己顯示對話盒;而這應該是由使用介面來處理才對。你可以小心的搬動程式碼,重構並修改介面,一次一個地解決這些問題。你可以找一個程式師小心處理好,再把所有修改一次放回版本管理系統,就不會影響到其他人。即使很重大的架構修改,都不必丟掉程式碼就可完成。我們花了好幾個月重整 Juno 專案的架構:只是把東西搬來搬去,把程式碼清理乾淨,建立合理的基礎類別,並且在模組間建立明確的介面。不過我們非常小心的處理現有的程式碼庫,結果沒有產生新問題也不必把還能用的程式丟掉。

程式師認為程式碼一團糟的第二個原因是效率不好。謠傳 Netscape 的成像程式很慢。不過這只牽涉整個專案的一小部份,你可以最佳化甚至重寫這一小部份,並不需要把所有程式都重寫。在最佳化速度時,抓到 1% 的工作重點可以得到 99% 的效果。

第三個理由是說程式碼他X的醜。某個我做過的案子真的有一個叫 FuckedString 的資料類型。另一個案子則是在開始時在成員變數名字前加底線 '_',後來卻改用比較標準的 'm_'。結果一半的函數是用 '_' 開頭而另一半是用 'm_' 開頭,看起來很醜。坦白地說,這種問題用 Emacs 的巨集功能五分鐘就解決了,不需要從頭開始。

你一定要記住,在要從頭重新開始時,完全沒有理由相信這次會做得比第一次好。首先你的程式團隊根本不可能和當初相同,所以並不會真的有「更多的經驗」。你其實只會把大部份的舊錯重新再犯一次,另外再多加一些舊版本沒有的新問題。

Lincoln_Center_Trees.jpg

在面對大型商業應用程式時,做了就丟掉是很危險的舊咒語。如果你只是寫程式做做實驗,想到更好的演算法時大可把上星期寫的函數丟掉,這是很正常的。想藉重構讓某個類別更容易使用,這也不會有任何問題,不過把整個程式都丟掉是個危險的愚行。如果 Netscape 真的運用軟體業經驗成熟地管理,就不會把自己害得這麼慘了。

一些回饋意見 ,包括某位很資深的前 Netscape 工程師的回應。另外 Seth Gordon 寫了一封電郵給我,針對閱讀他人的原始碼提供一些很好的技巧

這些網頁的內容為表達個人意見。
All contents Copyright © 1999-2006 by Joel Spolsky. All Rights Reserved.