
2005-07-07
Microsoft の Charles Simonyi 氏は, "Excel" や "Word" 等の超有名アプリケーション開発者として知られるほか, Windows プログラミングではお馴染みの「ハンガリアン記法」の考案者としてもよく知られている1,2。
ハンガリアン記法の詳細については Doug Klunder 氏の "Hungarian Naming Conventions" が参考になる3。この文書の日付が 1988 年になっていることから,この頃には既にハンガリアン記法が Microsoft 社内において一定の地位を確立していたことが推察される。また, Charles Simonyi 氏の博士論文 "Meta-Programming: A Software Production Method" を参照してみると,この中にハンガリアン記法と酷似する命名法が登場してくる4。つまり,この段階で既に基本となる考えは固められていたということのようだ。それが, Excel, Word および Windows の台頭によって急速に広められたということなのだろうと思う。
それでは,「ハンガリアン記法」とは一体何なのだろうか? よく言われるのが「変数名の前に,その変数の型を表す接頭子を組み込む」という説明ではないかと思う。整数 (int) であれば "nSize", ポインタであれば "pObject" ……というような具合だ。
古来 Windows プログラミングの世界では,ハンガリアン記法が「作法」のひとつとして伝えられてきた。しかしこの手法は,その使用を巡って議論を呼ぶことが度々あった。どうしてもこの記法を受け入れることの出来ない人々が存在するようだ。
理由は色々ある5, 6。ひとつに,冗長である。変数の型は宣言時に明示されているし,コンパイラもそれを把握しているはずなのに,なぜそれを名前にも添えておく必要があるのか? ひとつに, Simonyi の記法は Intel/Windows 依存である。 "w" (word) が 16 bits とはどういうことか? ひとつに,修正のコストが高くなる。変数の型を変更したら,依存するソースを全部書き換えなければならないのか? ひとつに,抽象性を失わせる。ひとつに,名前が醜くなる。ひとつに, Intellisense があるのに今更必要なのか? 云々,云々……。
個人的には,ハンガリアン記法はどちらかと言えば不要なものであると考えていた。前出のような些細な問題が多く存在するほか,普段から命名に気を遣うようにしていれば,義務的に暗号のようなものを用いる必要は無いと考えているためだ。
しかし,先日の Joel Spolsky 氏のエッセイ "Making Wrong Code Look Wrong" は,世に広められたハンガリアン記法が実は誤解を含むものであり,その正しい意図を提示したうえで,必要性の再認識を促すものとなっていた7。
件の記事は,その多くの部分がハンガリアン記法とは直接関係の無い話題に費やされている。ここで最も強く主張されているのは,題名にも示されている通り「間違ったコードを間違いに見えるようにする」という書法の重要性についてだ。
「間違ったコードが間違いに見える」というのは,ごく当たり前のことのようにも感じられるかもしれない。しかし実際には,それらの間違いは様々な要因により隠されてしまい,あたかも「正しいコード」であるかのように見えてしまうことがある。例えば,以前 Raymond Chen 氏が指摘していた「例外処理を利用したコードから誤りを見つけ出すのは難しい」というような話題も,その一例として挙げることができる8。
件の Joel 氏の記事は,例として CGI プログラミングにおける文字列の扱い方について触れている。 CGI を不正な XSS (クロスサイト・スクリプティング)から守るには, Encode 関数を通すことによって出力文字列からタグを抜いておかなければならない。しかし, Encode 関数を通す前の「危険な文字列」と, Encode 関数を通した後の「安全な文字列」を判別する方法は,言語やクラスの機能としては用意されておらず,プログラマの注意力に頼ることになってしまう。プログラマが十分に注意深ければ良いものの,さもなくば「危険な文字列」をそのまま出力してしまい,結果として CGI に脆弱性を招き入れることになってしまうかもしれない。
そこで,「危険な文字列」には接頭子 "us" (unsafe) を与え,「安全な文字列」には接頭子 "s" を与えることにする。そうすれば,次のような文は危険であることが一目で分かるようになる。
ここで重要なのは,このような接頭子を与えることによって,コードの論理的な誤りを見た目から判別することが可能になったという点だ。 Joel 氏は,このように見た目から直感的に誤りを見つけられることの重要性を強調している。そして,その直感は適切なコーディング規約を用いることによって補助することができると指摘している。むしろ,そのような観点からコーディング規約を採択すべきであるというわけだ。
例えば「変数の宣言は1行に1つまで」というコーディング規約の下では,次のようなコードは不正なものであると感じられるようになると思う。
これはCの規約からすれば正当なコードだ。しかし,実際には論理的な誤りを抱えている可能性が非常に高い。
前出の safe/unsafe の例も,このような直感による危険の察知を可能とするものだ。命名に特殊な規則を適用することによって,言語やライブラリの上では多義的・曖昧 (ambiguous) になってしまう情報を,コード上に明示させることが可能となる。そうすれば,局所的にコードを観察するだけで,コンパイラには分からない理論的な誤りを見つけ出すことができるようになるというわけだ。
Joel Spolsky 氏によれば,前述のような考えに基づいて考案されたオリジナルのハンガリアン記法は,主に Microsoft のアプリケーション部門において用いられ,社内では「アプリ・ハンガリアン」 (Apps Hungarian) と呼ばれていたとされている。このような手法は,C言語のような手続き型言語においては特に有用であると考えられる。そこから,当時C言語で開発されていた Excel や Word の開発チームにおいて広く用いられるようになったということなのだろう。
しかし,この「有用なハンガリアン記法」は, Microsoft の Windows 開発チームへと伝えられる過程において,何故か変質してしまう。これが,氏呼ぶところの「システム・ハンガリアン」であり,ハンガリアン記法を悪名高くした要因と考えられる存在であるわけだ。
Windows 開発チームへと伝えられる際に変質してしまった理由としては, Simonyi 氏が「型」 (type) という語を用いていたことの影響が大きいと考えられる。本来 Simonyi 氏が意図していたのは,言語の仕様として存在する「型」ではなく,その変数が持つ「意味」や,その変数が利用される「用途」などのように,言語の仕様としては扱うことのできない付加的な情報を与えるというものだった。
Simonyi 氏が意図するところの「型」は,言語の仕様に依存するものではなく,むしろアプリケーションの仕様に依存する概念であると考えられる。そのため,その定義はアプリケーションによって様々に異なる。例えば, Excel であれば "rw" (列) や "col" (行)等の接頭子が用いられ, Word であれば "xl" (レイアウトからの相対的な水平座標)や "xw" (ウィンドウからの相対的な水平座標)等の接頭子が用いられてきた。 Doug Klunder 氏の解説を見てみても,「ベースタイプ」に関してはアプリケーション毎に定義され,それは明確に文書化されるべきである,というようなことが述べられている。
オリジナルのハンガリアン記法は,C言語のような手続き型言語においては特に有用なものであったと考えられる。これらの言語においては,オブジェクト側から妥当性の確認を行うことが難しいためだ。故に,人間の直感による妥当性の確認を容易にすることが重要な意味を持ってくると考えられる。ハンガリアン記法は,オブジェクトとしての情報を変数名の中に組み込むことによって,その情報を目に見える形にしようというアプローチだ。
これが,例えば C++ のような OOP 言語になるとどうだろうか? OOP 言語においては,必要に応じてオブジェクトへのアクセスを制限したり,用途に合わせて機能の特殊化を行ったりすることができる。これらの機構を適切に利用すれば,妥当性の確認をオブジェクト側に行わせることが可能となる。前出の「危険な文字列」「安全な文字列」の例で言えば,特殊化された文字列クラスに「危険」「安全」の情報を持たせ,相互変換を自動的に行わせるようにするのが理想的な解決法かもしれない。
しかし実際のプログラミング工程においては,全てのクラスが事細かに特殊化されるわけではない。例えば,前出の例にあった「列」や「行」を "ColIndex" クラスや "RowIndex" クラスのように特殊化して用意するだろうか? 場合によっては用意すべきであるかもしれない。しかし多くの場合は,列インデクスも行インデクスも同じ整数型で管理することになるだろう。現実的な見方をすれば,ある程度のコストを払ってまでそこを特殊化することに意味は無い。そのような場合には,やはり手続き型言語の場合と同じく,ハンガリアン記法のような手法が役に立つことだろう。
ハンガリアン記法を用いなくとも,変数の命名に十分な気を遣っていれば,同様の目的を達成することは可能だ。しかし命名の感覚というものは人によって差異が生じやすいし,簡潔にまとめるための工夫が無いとどうしても冗長になってしまう。つまり,ハンガリアン記法のように機械的に適用することのできるルールには運用上の利点があると考えることができる。
このように様々なメリットを挙げることはできるものの,結局は好みや主義・文化の問題から,ハンガリアン記法を利用しない理由は存在しうる。しかし,少なくとも個人的には,今回の件によってハンガリアン記法に対する見方が大きく変化したと考えている。それは,今後コーディング規約の制定を行う場面にあって,少なからぬ影響を与えることだろうと思う。