我曾出現在《The Old New Thing》上
我算是個相當謙虛的人,所以大多數人都不知道我這個極為厲害的事蹟:Raymond Chen(雷蒙德·陳)曾提及我於經典的 Windows 開發部落格《The Old New Thing》上。
沒有,他既沒有指名道姓,也沒有提供任何能辨識出我的資訊,但就憑我如此低調地看待這項驚人的成就,我還是值得被肯定。

2009 年,雷蒙德·陳提及我於《The Old New Thing》的一篇文章中。
我想解決的問題
雷蒙德·陳在文章中稱我是「一位客戶(a customer)」,但當時我其實是他的 Microsoft 同事。那時我 23 歲,到 Microsoft 擔任開發人員快要滿兩年,那是我大學畢業後的第一份工作。
我當時負責BitLocker,也就是 Windows 中負責加密磁碟機的功能。我們正要開始 Windows 8 的開發,而我的專案是要改善 BitLocker 的設定體驗。
BitLocker 有許多可讓系統管理員透過組織層級設定(在 Windows 的說法中即Group Policy)來調整的選項。IT 管理員可以在整個組織內強制執行像「所有人的 BitLocker 密碼片語至少要有 12 個字元」這樣的規則,然後 BitLocker 就會強制使用者建立至少 12 個字元的密碼片語。

透過 Windows 群組原則編輯器檢視的 BitLocker 設定選項
BitLocker 設定上的麻煩之一是錯誤訊息很含糊。如果你嘗試設定一條要求密碼片語至少要有 1000 個字元的規則,BitLocker 會丟出類似「不行,太長了」這樣的錯誤,卻不會告訴你上限是多少。
在 Microsoft,C++ 程式碼中不能直接包含錯誤訊息,因為在地化團隊必須將所有面向使用者的文字翻譯成其他語言。因此,所有面向使用者的文字都放在看起來像這樣的 .mc 檔案中:
SymbolicName=ERROR_BITLOCKER_PASSPHRASE_MINIMUM_TOO_LONG
The BitLocker minimum passphrase length is too high.
.
SymbolicName=...
然後在 C++ 程式碼的某處,我們會有像這樣的檢查:
#define MAX_PASSPHRASE_MINIMUM 20
UINT32 minimumPassphraseLength = ReadGroupPolicy(GP_BITLOCKER_MINIMUM_PASSPHRASE_LENGTH);
if (minimumPassphraseLength > MAX_PASSPHRASE_MINIMUM) {
ShowError(ERROR_BITLOCKER_PASSPHRASE_MINIMUM_TOO_LONG);
}
我想要修改 BitLocker 的錯誤訊息,讓它向使用者提供關於錯誤原因的具體資訊。因此,與其讓使用者看到這樣的訊息:
BitLocker 密碼片語長度下限過高。
我希望使用者看到的是這樣的訊息:
BitLocker 密碼片語長度下限不可超過 20。
我不想把 C++ 程式碼中的數值 20 直接複製到 .mc 檔案中,因為如果我們之後更改了 MAX_PASSPHRASE_MINIMUM 的數值,.mc 檔案就會不同步,導致錯誤訊息變得不正確。
雷蒙德·陳是如何牽扯進來的
我對處理 .mc 檔案的 Message Compiler(訊息編譯器)工具不太了解。我找不到任何在 .mc 檔案中參照 C++ 數值的範例,但我覺得一定有辦法可以做到。
我在公司內部的郵件論壇上發問,詢問我是否可以把 .mc 檔案寫成這樣:
SymbolicName=ERROR_BITLOCKER_PASSPHRASE_MINIMUM_TOO_LONG
The BitLocker minimum passphrase length cannot exceed ${MAX_PASSPHRASE_MINIMUM}.
雷蒙德·陳經常在這些郵件論壇上發文。即使在 2009 年,他也已經在 Microsoft 待了非常久,對所有與 Windows 開發相關的事物都有百科全書般的知識。他的回覆既有幫助又具權威性,但如果你問問題前沒做足功課,語氣就會有點刻薄。
如果我沒記錯,雷蒙德·陳在我的討論串中簡短地回覆說:「又沒有法律規定你不能用 preprocessor(前置處理器),」並附上一個用前置處理器指令產生 .mc 檔案的範例。
我花了一段時間才搞懂他想表達什麼。我根本不知道可以叫 C++ 編譯器只執行前置處理的步驟。
浪費雷蒙德·陳的時間
這個故事可恥的地方在於,儘管我得到了偉大的雷蒙德·陳的建議,我卻臨陣退縮,沒有採用。
在雷蒙德·陳的部落格文章中,他展示了只要在 Makefile 中改幾行,就能讓你的原始檔從 .mcp 檔變成 .mc 檔,有多麼簡單。輕而易舉!
Windows 的建置系統比 Makefile 複雜了無數倍。我已經不記得它長什麼樣子了,只記得我覺得它既可怕又令人困惑。
更糟的是,如果你把建置弄壞了,可能要到隔天早上收到電子郵件通知你破壞了每日建置(nightly build),才會發現,而現在有數十甚至數百人因為你而拿不到當天的 Windows 建置版本。
所以,我有兩個選擇。我可以當第一個在建置系統中嘗試新做法的人,冒著得花上一、兩週來修復非預期問題的風險。或者,我可以假裝自己從未有過要在 BitLocker 錯誤訊息中加入具體數字的想法,轉而專注於其他讓設定變得更簡單的方法。
我選擇了後者。
直到今天,我還是不會解這個問題
當時,我還記得自己心想:「哇,我竟然不知道可以這樣用 C preprocessor,真笨。」
大多數時候,當我回頭看多年前曾讓我苦惱的軟體問題時,現在的我會覺得解決方案顯而易見。通常,我甚至能想到更好的解法。
但 16 年後的今天,雷蒙德·陳那個對非 C/C++ 檔案執行 C preprocessor 的解法,仍然讓人感到出乎意料。如果我擁有現在所有的專業經驗,卻唯獨沒有這段關於雷蒙德·陳的記憶,而你叫我再解一次這個問題,我還是會跟 2009 年時一樣卡關。
不同的是,現在的我不會因為不知道怎麼解決這個問題而覺得自己很笨。我現在認為這是 Microsoft 內部工具的弱點。在 Microsoft,在他們的旗艦產品上,怎麼會沒有一個標準的方法,讓開發人員能在錯誤訊息和 C++ 程式碼中同時參照常數值?
身為軟體工程師,有些問題雖然令人不快,但你會咬緊牙關不斷練習,直到變得更擅長。至於其他問題,你則會透過謹慎選擇工作和專案來避開。
搞懂艱澀難懂的建置系統就是我選擇避開的問題之一,而我對此甘之如飴。除了當我使用 Nix 的時候例外。
隨機一篇部落格