操練嚴格才好打仗

作者:周思博 (Joel Spolsky)
譯:Paul May 梅普華
Tuesday, November 20, 2001
屬於Joel on Software, http://www.joelonsoftware.com


我覺得VMWare實在是棒到不行。過去幾星期我們要讓CityDesk在各種32位元的Windows上都能動,這個程式幫助非常大。我安裝了幾十套虛擬機器,有單純的DOS分割 (作為安裝其他OS的起點)和各種NT 4.0的組合,還有中文和希伯來文的Win2K (雖然我們的程式是用英文也沒什麼特別的東西,還是在這些系統上找到各式各樣的問題),還有從1995年8月起發行五花八門的Win 95/98/Me版本,甚至還有包括一台主網域控制器的小型網路來測試FogBUGZ的安裝。

VMWare

要讓程式在五花八門的Windows系統上都能動是件大工程。這是Java等「寫一次程式,到處都可跑」系統的真正訴求。理論上如果用Java虛擬機器,辛苦的是要提供這所有平台相容性的VM供應商。可是實際上Java程式師都已學到,程式本身實在是太脆弱太敏感,達不到完美的效果。以前我用Java開發某個遊戲時就瞭解到,由於Java無法保證行程執行的時間(這種妥協似乎沒什麼問題,反正CPU排程基本上就是無法預測的),實際上會讓某些行程在麥克塔上永遠卡住,要等其他行程嘗試執行I/O才會繼續。這和我預期的不一樣而且也讓我的遊戲在麥金塔上不太刺激。(這是1996年的事。所以不要寫信告訴我要如何避開或修正,也不用解釋這個問題已經修好了。)

昨天遇到的「當日之蟲」就是個類似的整人例子。Michael用古老的Windows API GlobalAlloc配置了一些記憶體。然後呼叫另一個函數GlobalSize取得該記憶體的大小。在我們的開發系統上(Windows 2000),GlobalSize會傳回當初配置時相同的值。配置13個位元組,GlobalSize就會傳回13。

某個用Windows 98的使用者回報了一個問題:「複製貼上沒有作用」。就像上面的畫面所顯示,我裝了一套Windows Me VM還有VB6。在用除錯器逐行追蹤程式時,我注意到GlobalSize呼叫,回想起Win 95時代GlobalSize會傳回真實配置到的區塊大小,數字會比你要配置的而且通常是64的倍數。這就是問題所在。

現在,改變GlobalSize行為的微軟程式師可能認為自己並沒有破壞任何東西。GlobalSize函數的文件明白地寫著:「記憶體區塊的大小可能會大於比記憶體配置時要求的大小。」事實上微軟人可能認為,讓GlobalSize傳回所要求的大小是個無害的小小改進。很顯然的,舊程式碼並不會相信GlobalSize的傳回值,所以能不受影響繼續動。有什麼理由不改進這個函數呢?

並不是每個程式師在使用每個函數時都會細讀對應的每一行文件,另外只要程式會動了,就會去做其他事情。更何況文件裡並沒有把所有東西都寫得很清楚,像我這裡討論的這類細節就很少寫在文件裡。而這正是這類問題發生的原因。其實除了微軟人以外,全世界都已發現這個問題,看看WINE(譯註:一個Windows環境模擬器)程式師失敗的原因,當他們推出第二個網路瀏覽器時,突然間每個人都注意到原先賴以讓網頁顯示正常的某個問題不見了。另外IE6依照標準去處理表格中文字的<CENTER>行為,結果無數編HTML網頁的人都在哀嘆,因為他們的網頁用IE6來看都變成和婚禮喜帖一樣靠左對齊了。

我們要怎麼處理這種狗屎呢?Larry Wall說過一句很有名的話:「大家直覺上都知道,要電腦程式彼此溝通,最好的方法就是提供時要嚴格,接收時要寬鬆。」我認為HTML的演進已經證明這並不是什麼好主意。事實上API對於輸入參數愈嚴謹,程式愈有可能在奇怪的狀況上仍舊運作。Java的設計者就做得很對,他們決定Java的規格應該要清楚明確,不要讓編譯器開發者有任何選擇餘地(至少不要像C那樣無道理的寬鬆,連基本型別的大小都不定)。俄羅斯蘇沃洛夫元帥說得好:「操練嚴格才好打仗。」你希望你的編譯器和開發環境儘可能的嚴謹;你希望能讓GlobalSize傳回任意亂數,這樣才不會養成習慣去依賴一些某一天會消失不見的機制;你希望在中文Windows 2000上套用法國的區域設定,再搭配離譜的配色、DVORAK鍵盤、軌跡球、640x480 VGA顯示模式和大大醜醜的字型,然後拿來當開發環境,這樣才會記得在程式裡做所有對應的調整。這樣一來你的應用程式就會柔軔堅強,連有人小數點是用逗號而非句點這種蠢問題也能大笑面對。你的程式會用俄國口音說:哈哈哈,我都拿逗點來當早餐

總而言之,這是讓軟體在幾億台電腦上都能跑的方法。只在一台電腦或是在一個受控制的環境下開發程式是很簡單,不過你會變得軟弱無力。總有一天你要在第二台電腦上執行,然後你就會熬夜在那台電腦上安裝完整的開發環境,然後再查兩個小時之後,終於發現自己沒有考慮到安裝路徑裡可能出現空白字元,因為第一台電腦沒有這種情形。

可以指望的是,未來虛擬機器的概念(不管它是Java、.NET還是別的玩意)將會減少這種痛苦,不過時候還未到。現在我還是很高興能花十分鐘除錯,就能讓喜歡把Windows文字設成粉紅色或橙色的人都能正常執行我的程式。在一整年的開發時間裡,我們大概用了三星期去修正組態相關的問題。小小的代價卻讓潛在客戶群由美國版Windows 2000擴展到整個NT 4、95、98、Me、和XP家族,再加上全球各種語言版本。酷。

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