# 十六、人員技能
我想想來談談我為CityDesk 3.0重寫的一段程序:檔案匯入程序。(廣告:CityDesk是本公 司出品的很容易用的內容管理產品。)
它的規格似乎和任何一段程序代碼一樣簡單。使用者用標準對話盒選擇一個檔案,然后程序 將該檔案復制到CityDesk的數據庫中。 結果卻變成「最后1%程序用掉90%時間」的最佳范例。最早一版的程序結構大概是這樣子的:
1. 開檔案
2. 把內容全部讀進來,放在一個大字節數組里
3. 把字節數組放在一個記錄中
效果不錯。大小合理的檔案幾乎是一瞬間就做好了。它有幾個小問題,我們一個一個來看。
當我把一個120MB的檔案丟進CityDesk時跑出第一個問題。通常人們不太會在網站上放個120 MB的檔案。事實上應該是少之又少才對。不過雖然少但還是有可能。程序可以用,不過等了 一分鐘而且畫面上完全沒有反應-程序就這樣定住不動,看起來好像完全當掉了。這顯然 并不太理想。
由使用接口的觀點來看,我真正要的是在長時間處理時出現一個進度棒之類的東西再加上一 個取消鈕。理想的狀況下,你可以在CityDesk里繼續其他操作,檔案復制的作業會在背景執 行。這有三種顯而易見的方法可以達成:
1. 只用一個線程,由該線程經常輪詢輸入事件
2. 啟用第二個線程,然后小心的進行同步
3. 啟用第二個行程,然后不必那么小心的進行同步
我的經驗是第一種作法行不通。要確定應用程序里所有程序代碼都能在復制檔案時安全的執 行,實在是太困難了。另外Eric S. Raymond也讓我相信,以解決方案來說線程通常不如單 獨的行程好:事實上多年的經驗顯示,多線程程序設計產生了很多額外的復雜性,而且會引 入全新種類的危險海森堡蟲(heisenbugs)。第三項似乎是個好答案,尤其當我們下層用的是 多用戶的數據庫,不用怕很多行程同時使用。所以我打算等感恩節休假結束就用第三種作法。
不過整體想想看就會發現,我們己經由讀文件寫作數據庫變成復雜許多的東西:啟動一個子 行程,讓它讀文件寫入數據庫,這個子行程還要有一個進度棒和取消鈕,最后還要某種機制 讓子行程通知母行程,檔案己經處理完可以顯示..其他的工作還包括將命令行參數傳給子行 程,確定窗口焦點的行為正確,還要能處理使用者在復制檔案時關機的狀況。我猜等把這些 都做好,大概要十倍的程序才能優雅地處理大檔案,而這可能只是用戶所看到的程序的百分 之一。
當然會有某類型的程序員出來爭論,說我用子行程的新架構比原本的差。這種作法「過度膨脹」(由于那些額外増加的程序代碼)。另外潛在的問題也比較多(一樣由于是多加的程序代 碼)。這個作法做太過頭了。這某種程度也表示Windows的確是個爛操作系統。他們會說這和 進度棒有什么關系?他們會嘲笑著說:只要按Ct「l+Z再重復打”Is -I”看看檔案大小有沒有 増加就好啦!
這個故事的教訓是修正一個1%的問題可能會用掉500%的工夫。這種狀況并不只軟件業會發生。 敢這樣講是因為我現在就在管理這些建筑工程。上星期我們的包商終于完成Fog Creek新辦 公室的最后修飾工程。內容包括在前門安裝閃亮的藍色壓克力,旁邊圍著鋁框,鋁框上每20 公分就鑲有一顆螺絲。如果你仔細看照片,會發現每片門都會被鋁框整個包住,當門關起來 時,兩片直框會并排在一起。雖然圖上看不出來,不過中間鋁條上的螺絲幾乎但沒有確實對 齊。差了大概有2公厘。負責這件事的木匠很小心的測量,不過裝鋁框時門是放在地上,并 不是等好門裝好再當場裝的。所以等到要把門裝上去時,才發現螺絲并沒有對齊。
這或許并不罕見;;我們辦公室里很多門的螺絲都沒有對的很好。問題是當洞鉆好之后,要重 新修正的代價貴得離譜。由于正確的螺絲位置離原來的洞只有幾公厘,所以不能直接在門上 再鉆一個,可能得把整個門換掉才能解決。這實在是很不值得。這正是另一個修正1%的問題 會用掉500%工夫的例子,而且這也解釋了為何這世上很多人造物都是99%好而非100%完美。 (不過建筑師倒是不斷吹墟,說某些亞歷桑那州的高貴金屋里每根螺絲都排得很整齊。)
這點出了軟件的一項特性,一項大部份人都視為工匠技藝的特性。當軟件是由真正的工匠制 作時,所有螺絲都會對得整整齊齊..當你做些很罕見的事時,應用程序會表現得很聰明。作 者會投入更多的工夫去正確處理特的狀況,而不光是讓主要的程序會動。即使要額外再花500% 的力氣去處理1%的狀況也在所不惜。
工匠技藝當然是非常昂貴的。唯一負擔得起的方法就是針對大量的客戶開發軟件。很抱 歉,不過保險公司開發的內部人事管理程序絕對不可能達到這種工藝的境界,因為就是沒有 足夠的使用者來分散額外的成本。不過就軟件包公司而言,這種工藝境界可以讓使用者高興 并提供長期的競爭優勢,所以我愿意花時間并正確地執行。請容忍我吧。
- 第一部分 位與字節:編程實踐點滴
- 一、語言的選擇
- 二、深入底層
- 三、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對策
- 四十五、請問,我可以使用連接程序嗎