I Once Appeared in The Old New Thing

Michael Lynch

我曾出現在《The Old New Thing》上

原文由 Michael Lynch 發布,訂閱此部落格

我算是個相當謙虛的人,所以大多數人都不知道我這個極為了不起的事蹟:Raymond Chen 曾在經典的 Windows 開發部落格《The Old New Thing》上提到過我

沒有啦,他既沒有指名道姓,也沒留下任何能認出我的線索,但光是我這麼少拿這項驚人成就來炫耀,就值得嘉許了。

2009 年,Raymond Chen 在《The Old New Thing》的一篇文章中提到過我

我想解決的問題

Raymond 在文章中稱我為「一位客戶」,但其實當時我是他在微軟的同事。那時我 23 歲,進微軟擔任開發人員快滿兩年,那是我大學畢業後的第一份工作。

我負責的是 BitLocker,也就是 Windows 用來加密磁碟機的功能。當時我們剛開始開發 Windows 8,而我的專案是要改善 BitLocker 的設定體驗。

BitLocker 有許多可供管理員透過組織層級設定(用 Windows 的術語來說就是群組原則)來調整的選項。IT 管理員可以在整個組織內強制執行像是「每個人的 BitLocker 密碼都必須至少 12 個字元」這樣的規則,接著 BitLocker 就會要求使用者建立至少 12 個字元的密碼。

透過 Windows 群組原則編輯器檢視 BitLocker 的設定選項

BitLocker 設定上一個令人頭痛的地方是錯誤訊息寫得很含糊。如果你試圖設定一條要求密碼至少要有 1000 個字元的規則,BitLocker 只會丟出類似「不行,太長了」這樣的錯誤,卻不會告訴你上限到底是多少。

在微軟,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

我不想把 20 這個數值從 C++ 程式碼複製到 .mc 檔案裡,因為如果之後我們改了 MAX_PASSPHRASE_MINIMUM 的數值,兩邊就會不同步,導致錯誤訊息變得不正確。

Raymond Chen 怎麼會牽扯進來

我對用來處理 .mc 檔案的 Message Compiler 工具並不熟。我找不到任何在 .mc 檔案中引用 C++ 數值的範例,但我總覺得一定有辦法做到。

我在公司內部的郵件論壇上發問,問能不能把 .mc 檔案寫成這樣:

SymbolicName=ERROR_BITLOCKER_PASSPHRASE_MINIMUM_TOO_LONG
The BitLocker minimum passphrase length cannot exceed ${MAX_PASSPHRASE_MINIMUM}.

Raymond Chen 經常在這些郵件論壇上發文。即使在 2009 年,他也已經在微軟待了非常久,對所有與 Windows 開發相關的事都瞭若指掌。他的回覆既有幫助又具權威性,但如果你發問前沒有做足功課,他也會毫不留情地挖苦你。

如果我沒記錯,Raymond 在我的討論串下簡短地回了一句:「又沒規定你不能用前置處理器,」並附上一個用前置處理器指令產生 .mc 檔案的範例。

我花了好一陣子才搞懂他到底想告訴我什麼。我根本不知道原來可以叫 C++ 編譯器只執行前置處理的步驟。

浪費 Raymond Chen 的時間

這個故事最丟臉的地方在於,雖然我得到了大神 Raymond Chen 的指點,我最後卻退縮了,沒敢照做。

在 Raymond Chen 的部落格文章中,他示範了只要在 Makefile 裡改幾行,就能把來源檔案從 .mc 檔換成 .mcp 檔。輕輕鬆鬆!

Windows 的建置系統比 Makefile 複雜了無數倍。我已經不記得它長什麼樣子,只記得當時覺得它既可怕又讓人困惑。

更糟的是,如果你搞砸了建置,可能要到隔天早上收到通知信,才會發現自己弄壞了夜間建置,導致數十甚至數百人因為你而拿不到當天的 Windows 建置版本。

所以,我有兩個選擇。我可以當第一個在建置系統裡嘗試新做法的人,冒著得花上一兩週去修補各種突發問題的風險。或者,我可以假裝自己從沒想過要在 BitLocker 的錯誤訊息裡加入具體數字,轉而專注於其他讓設定更簡單的方法。

我選擇了後者。

就算到今天,我還是不會解這個問題

當時我心想:「哇,我居然不知道可以這樣用 C 前置處理器,真笨。」

大多數時候,回頭看多年前讓我卡關的軟體問題,現在的解法會變得顯而易見。通常我還能想到更好的解法。

但 16 年後的今天,Raymond 那個對非 C/C++ 檔案執行 C 前置處理器的解法,依然讓我覺得出乎意料。就算我保有至今所有的專業經驗,唯獨抹去這段關於 Raymond Chen 的記憶,再叫我解一次同樣的問題,我大概還是會跟 2009 年一樣卡關。

不同的是,現在我不會因為不知道怎麼解這個問題而覺得自己笨。我現在認為這是微軟內部工具的缺陷。在微軟,在他們的旗艦產品上,怎麼會沒有一套標準做法,讓開發者能在錯誤訊息和 C++ 程式碼中同時引用同一個常數?

身為軟體工程師,有些問題雖然討厭,但你會咬牙練習直到變得更擅長。另一些問題,你則會透過謹慎挑選工作和專案來直接避開。

理解艱澀難懂的建置系統,就是我選擇避開的問題之一,而我對此完全可以接受。除了我在用 Nix 的時候

本文章由 muse-spark-1.2-contributor 進行翻譯

留言