かつて『The Old New Thing』に登場したことがある
私はわりと謙虚な人間なので、あまり知られていないのですが、実はとてつもなく自慢できることがあります。Raymond Chenが、Windows開発の古典的なブログ『The Old New Thing』で私のことを取り上げてくれたのです。
いえ、名前を出してくれたわけでも、個人を特定できるような形で触れてくれたわけでもありません。でも、この輝かしい功績についてほとんど自慢していないこと自体、称賛に値すると思っています。

2009年、Raymond Chenがある回の『The Old New Thing』で私のことに触れました。
解決しようとしていた問題
記事の中でRaymondは私のことを「ある顧客」と表現していますが、実際は当時同じMicrosoftで働く同僚でした。私は23歳で、大学を卒業してMicrosoftで開発者として働き始めてから、もうすぐ2年になろうという時期でした。
私が担当していたのは、Windowsでドライブを暗号化する機能であるBitLockerでした。当時はWindows 8の開発が始まったばかりで、私のプロジェクトはBitLockerの設定体験を改善することでした。
BitLockerには、管理者が組織レベルの設定(Windowsの用語でいうGroup Policy)を通じて構成できる、数多くの設定項目がありました。たとえばIT管理者は「組織内の全員のBitLockerパスフレーズは12文字以上でなければならない」といったルールを組織全体に適用でき、そうするとBitLockerはユーザーに12文字以上のパスフレーズの作成を強制するのです。

WindowsのGroup Policyエディターから見た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のエラーメッセージを、なぜエラーが起きたのかを具体的に伝えるものに変えたいと思いました。つまり、こう表示されるのではなく、
The BitLocker minimum passphrase length is too high.
ユーザーにはこう見えるようにしたかったのです。
The BitLocker minimum passphrase length cannot exceed 20.
C++コードにある20という値をそのまま.mcファイルにコピーしたくはありませんでした。後でMAX_PASSPHRASE_MINIMUMの値を変更したときに、.mcファイル側と食い違って、エラーメッセージが間違ったものになってしまうからです。
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年の時点でも、彼はすでに長くMicrosoftに在籍し、Windows開発に関することなら何でも知っている百科事典のような存在でした。彼の返信はいつも的確で権威がありましたが、質問する前に十分調べていないと思われると、皮肉っぽくなることもありました。
記憶が正しければ、Raymondは私のスレッドにそっけなく「プリプロセッサを使ってはいけないなんて決まりはない」とだけ返信し、プリプロセッサのコマンドで.mcファイルを生成する例を示してくれました。
彼が何を言おうとしているのかを理解するのにも、しばらく時間がかかりました。C++コンパイラにプリプロセスのステップだけを実行させることができるなんて、知らなかったのです。
Raymond Chenの時間を無駄にした話
この話で恥ずかしいのは、偉大なRaymond Chenからアドバイスをもらったにもかかわらず、結局それを使うのをやめてしまったことです。
Raymond Chenのブログ記事では、Makefileを数行書き換えて、ソースファイルを.mcファイルではなく.mcpファイルにするだけでよいと、簡単に説明されていました。実に簡単そうです。
しかしWindowsのビルドシステムは、Makefileの比ではないほど無限に複雑でした。詳細はもう覚えていませんが、とにかく恐ろしくて混乱させられるものだったということだけは覚えています。
さらに悪いことに、ビルドを壊してしまっても、翌朝「ナイトリービルドを壊しました」というメールが届くまで気づかないこともありました。あなたのせいで、その日のWindowsのビルドが何十人、何百人もの手元に届かなくなってしまうのです。
ですから私には選択肢がありました。ビルドシステムで誰もやったことのない新しいことを最初に試し、予期せぬ問題の対応に1週間や2週間を費やすリスクを負うか。それとも、BitLockerのエラーメッセージに具体的な数値を入れるというアイデア自体なかったことにして、設定を簡単にする別の方法に集中するかです。
私は後者を選びました。
今でも解決方法は分からないままです
当時は「こんなふうにCプリプロセッサを使えるなんて知らなかったなんて、自分はなんて馬鹿なんだ」と思ったことを覚えています。
たいていの場合、何年も前に悩んだソフトウェアの問題を振り返ると、今なら解決策はもっと明らかに見えます。たいていは、もっと良い解決策を思いつくことができます。
しかし16年経った今でも、C/C++以外のファイルにCプリプロセッサをかけるというRaymondの解決策は、やはり意外に感じられます。もしRaymond Chenのこの記憶だけを除いた今までのすべての経験を持った状態で、同じ問題をもう一度解けと言われても、2009年と同じくらい苦労すると思います。
違うのは、今はこの問題を解けなかったからといって自分を馬鹿だとは思わないことです。今ではこれはMicrosoftの社内ツールの弱点だったのだと思っています。Microsoftの看板製品で、なぜエラーメッセージとC++コードの両方で定数値を参照する標準的な方法がなかったのでしょうか。
ソフトウェアエンジニアとして、嫌だと感じる問題でも、歯を食いしばって練習を重ね、上達するまで頑張るべきものもあります。一方で、仕事やプロジェクトを慎重に選ぶことで、ただ避ければよい問題もあります。
難解なビルドシステムを理解することは、私が避けてきた問題の一つですが、それでよいと思っています。Nixを使うとき以外は。
記事をランダムに読む