程式設計領域的帕麥爾斯頓勳爵 Lord Palmerston on Programming

作者:周思博 (Joel Spolsky)
譯:Paul May 梅普華
Wednesday, December 11, 2002
屬於 Joel on Software, https://www.joelonsoftware.com/2002/12/11/lord-palmerston-on-programming/

曾經一度如果讀過 Peter Norton 的一本書,就能完全瞭解在 IBM-PC上 寫程式所需的全部知識。在過去 20 年間,全世界的程式師很努力地在 IBM-PC 上建立層層的抽象機制,讓程式更容易撰寫而且功能更強大。

不過抽象滲漏法則表示,即使他們建立了這些理應讓程式更易設計的抽象機制,做個偉大的程式師所需的各種知識還是一直在增加。

要真正地精通某個程式設計領域需要好幾年的工夫。當然也有很多出色的青少年學了一星期 Delphi,再學一星期 Python 然後再學一個星期的 Perl,就自認已經精通了。不過他們根本不知道自己差得有多遠。

我打從 ASP 和 VBScript 剛出來就在用了。VBScript 是世界上最微不足道的程式語言,而 ASP 程式設計大概只要上五堂課會了,而且其中只有兩堂是會經常用到的。可是直到現在,我才感覺自已知道架構一個 ASP/VBScript 應用程式的最佳作法,我才終於覺得自己知道資料庫存取程式最適當的位置,用 ADO 取得 recordset 的最佳作法,分離 HTML 和程式碼的最佳方式等等。另外我也終於會用正規表示式,不再每次都重寫一次字串操作函數。另外我上星期才學會如何取得不在記憶體中的 COM 物件,這樣就就可以不需整個 web 伺服器重開就能重新編譯。

Fog Creek 太小了養不起專家,所以當我要為 FogBUGZ(我們用 ASP/VBScript 製作的產品)寫一個真正好的安裝程式時,我得拿出數年 C++/MFC 和 Windows API 的經驗,再用我還不錯的Corel PhotoPaint 技巧做出放在精靈角落的圖片。另外為了讓 FogBUGZ 能無誤地使用 Unicode,我還得用 C++ 和 ATL 寫一個小小的 ActiveX 元件,這裡頭有著數年的 C++ 和 COM 經驗,還有當初實作 CityDesk 時學了一週左右的字元編碼知識。

所以當我們遇到某個只有 NT 4.0 才發生的怪問題時,我只花了三分鐘就解決了,因為我知道如何使用 VMWare,而且我有一套用 VMWare 灌的乾淨 NT 4.0 機器,另外我也知道如何用Visual C++ 做遠端除錯,還知道可以由 EAX 暫存器知道函數的回傳值。完全沒接觸過這些東西的人要抓同一個問題,恐怕得花一個小時或更多的時間,不過我已經知道了很多很多「東西」,那些基本上是從1982年拿到我第一台 IBM-PC 和那本 Norton 書時就開始學的東西。

有漏洞的抽象表示我們面對一個直線上升的學習曲線:你可以用一星期學到每天工作所需知識的 90%。不過其他 10% 可能得要好幾年才能補齊。有些人會說:「不管你要我做什麼,我都可以拿本書來就學會了。」真正有經驗的程式師超越這種人的地方就在這裡。如果你正在建立一個團隊,當然可以找一堆經驗較少的程式師用抽象工具製作出一大堆程式碼,不過如果少了經驗老到的人去做真正困難的事情,這個團隊是做不起來的。

程式設計有很多不同的世界,每個世界都需要大量的知識才能真正的精通。以下是我個人最熟的三個領域:

  • MFC/C++/Windows
  • VBScript/ASP
  • Visual Basic

基本上這全部都可以稱作 Windows 程式設計。沒錯,我也寫過 Unix 或 Java 的程式,不過很少就是了。我對 Windows 程式設計的專精不光是瞭解基本技術,也知道整個支援的整體結構。我敢宣稱對 Windows 程式設計很在行,是因為我也會 COM、ATL、C++、80x86 組合語言、Windows API、IDispatch (OLE Automation)、HTML、DOM、Internet Explorer 物件模式,Windows NT 以及 Windows 95 內部機制,LAN Manager 和NT網路以相關安全機制(ACE、ACL等等)、SQL及SQL Server、Jet和Access、JavaScript、XML,還有一些其他有關直角三角形斜邊的有趣事實。如果不能在 VB 裡用 StrConv 函數達成我的目的,我會為了用 C++ 和 ATL 呼叫 MLang函數而去寫一個 COM 控制元件,眼睛連眨都不會眨一下。我花了很多年才達到這種境界。

還有很多其他程式設計的世界。有開發 BEA Weblogic 的世界,裡頭的人要懂 J2EE、Oracle 還有各種我列不出來跟 Java 相關的東西。另外也有硬派的麥金塔開發者,他們懂的是CodeWarrior、MPW、由 System 6 到 OS/X 各版本的 Toolbox 程式設計、Cocoa、Carbon、甚至還有現在已經沒用的 OpenDoc 等過時的好東西。

不過只有極少數人能清楚一個以上的世界,因為要學的實在太多,除非在這些世界工作過幾年,否則是不會真的全部都懂。

不過你卻必須學會。

面試時因為沒有 Win32 或是 J2EE 或 Mac 程式設計經驗而被拒絕,大家都會覺得很生氣。 或者某些笨蛋面試官其實根本不知道 MSMQ,卻打電話問面試者是否具有「五年的 MSMQ 經驗」,也會讓人覺得很不爽。

如果你剛寫 Windows 程式不久,你可能認為 Win32 只不過是個程式庫,跟其他程式庫差不多,要用到時再去查書學著怎麼呼叫就好了。你可能會認為基本的程式設計(比如你的 C++ 專業技能)佔九成,所有 API 合起來算是只佔一成的小事,幾星期就可以惡補回來。對這些人我只能小聲地建議:時代已經變了。現在的比例是反過來的。

已經很少有人需要去做把位元組搬來搬去的低階 C 演算法了。現在我們大多數人都把全部時間花在呼叫API而不是搬移位元組。一個沒有 API 經驗的 C++ 程式高手,對用 API 寫程式的日常工作內容其實只知道大約一成而已。當經濟狀況好的時候這並不打緊。你還是會得到工作,而雇主會花錢讓你熟悉平台。不過當經濟不景氣時,每個工作都有 600 個人申請,雇主有本錢選擇已經精通該平台的程式師。比如說能列出四種 Visual Basic 中 FTP 檔案的方法,還能指出每種方法優缺點的人。

這所有的程式設計世界的表相都很多,因此常常引發毫無意義的論戰,爭執哪個世界比較好。某位匿名者在我的討論區寫了以下這段自以為是的意見:

「再說另一個讓我樂意留在『自由世界』的理由,言辭的自由(幾乎),以及免於屈從安裝程式和registry這種東西(還有很多,我只是舉兩個例子)的自由。」

我認為這個人真正要說的是,在 Linux 世界裡是不寫安裝程式的。嗯,我討厭讓你失望,不過你的世界也有些一樣麻煩的東西:imake、make、config 檔等玩意。另外當你完成應用程式之後,要發行時還得附上 20KB 的 INSTALL 檔案,裡頭全是些拿古怪裝有趣的指示,比如「你會需要 zlib」(那是什麼東西?)或是「這會要花一些時間,去拿一些 runt 吧。」 (我猜runt大概是某種糖果吧)。至於 registry 登錄檔,雖然你並沒有用一個有組織的大結構(hive)存各個名稱/值的組合,不過你有上千種不同的檔案格式,每種應用程式都各有一種,而且到處都有.rc和 foo.conf 檔案。另外想在 emacs 裡更改設定還得學寫 lisp 程式,而每個 shell 都要你學它獨有的 shell 腳本方言才能更改設定,還有其他其他其他。

只認識一個世界的人是很討人厭的。他們每次聽到其他世界的複雜狀況時,就會覺得自己的世界沒那麼複雜。不過事實上是一樣的。只是你已經很精通,所以視而不見。這些世界實在太大太複雜無法相互比較。帕麥爾斯頓勳爵(Lord Palmerston)說過:「什列斯威-好斯敦問題(Schleswig-Holstein Question)問題實在是太複雜了,整個歐洲也只有三個人瞭解。第一位是已經逝世的Prince Albert。第二位是某個瘋了的德國教授。第三位就是我,不過我已經完全忘掉了。」軟體的世界也是如此巨大複雜而多面相,以致當我看到某些其方面很聰明的人在網誌寫些像「微軟不懂作業系統」之類的空話時,不禁要坦白的說他們看起來很蠢。Windows 是由數百位程式師在十到廿年間所創造,具有數百個功能的幾百萬行程式。想像嘗試要概述這種龐然大物,卻連開始瞭解其中一大部份就沒有。我並不是在為微軟辯護,只是覺得這種源自極度無知的巨大模糊概括,是現在網路上最浪費時間的東西。

常來的讀者應該已經注意到我在思考要如何發展跨 Linux、Macintosh 和 Windows 平台的應用程式,又不必為 Linux 和 Macintosh 版本投入不成比例的成本。這時候你需要某種跨平台程式庫。

Java有這個野心,不過Sun並沒有真的把GUI弄通,不能做出真正感覺自然的應用程式。這就像星艦迷航記裡的太空異形透過望遠鏡觀察地球一樣,他們知道人類食物的外觀,卻不瞭解它的味道。Java 程式會在正確的地方畫出功能表,可是鍵盤操作和 Windows 程式完全不一樣,而且 Java 的分頁對話盒看起來有點恐怖。另外不管怎麼試都不能讓功能表列和 Excel 的一模一樣。為什麼會這樣呢?因為 Java 在抽象機制失敗時,並沒有提供很好的方法去將就使用平台原始的機制。當你用 AWT 寫程式時並不能取得視窗的 HWND,不能呼叫微軟的 API,當然也不能把 WM_PAINT 攔截起來自己畫。而 Sun 已經表示得很明白了,如果你這樣就就不夠純粹。你被污染了所以活該去死。

試圖用 Java 建立 GUI 的努力經過多次眾所周知的失敗之後(比如 Corel 的 Java Office suite 和 Netscape 的 Javagator),不少人學會要和這個世界保持距離。Eclipse運用平台原本的機制,從最底層開始建立了他們自己的視窗程式庫,這樣才能寫出使用觀感符合原平台感覺的 Java 程式。

Mozilla 的工程師決定用他們自己的發明 XUL 來處理跨平台問題。到目前為止令我印象深刻。Mozilla 終於做到用起來感覺對勁的境界。連我最喜歡的怪用法「用 Alt+Space N 把視窗縮到最小」都可以在 Mozilla 裡面使用;雖然花了很久不過他們還是做到了。

成立 Lotus 並創造 123 的 Mitch Kapor 決定下一個計劃要做一個叫 wxWindows 和 wxPython 的產品,目標也是跨平台支援。

哪一個比較好呢?是 XUL?是 Eclipse 的 SWT?還是 wxWindows 呢?我不知道。這些都是很龐大的世界,大到我根本無法實際去評估並找出答案。光是讀完教學並不夠。你必須自己去辛苦用個一兩年,才能真正知道它是的確夠好,還是怎麼試都無法讓做出感覺對勁的使用介面。不幸的是,大多數專案都必須在寫第一行程式之前決定要用哪個世界,而這正是資訊最少的時候。在前一個工作我們得面對某些很爛的架構,因為最早期的程式師利用該專案同時學寫 C++ 和 Windows 程式設計。有些最初期的程式碼是完全不懂事件驅動程式設計下寫出來的。核心的字串類別(我們當然有自己的字串類別)可以寫進教科書,用以示範 C++ 類別在設計上會犯的各種錯誤。最後終於把很多舊程式清理並重整乾淨,不過還是讓我們頭痛了好一陣子。

所以現在我會建議:至少要有一個對所用的語言、類別、API 以及平台有數年以上經驗的設計者,否則還是不要啟動專案吧。如果你可以選擇平台,就用你的團體最熟悉的吧,即使這個平台並不是最符合趨勢或看起來最有生產力也沒關係。另外在設計抽象機制或程式設計工具時,多做些努力讓它不會漏吧。

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