sifue's blog

プログラマな二児の父の日常

イングリッシュ記法(名前に情報を追加する)は、誰もが行うべき重要な変数命名法

リーダブルコードを読み終えました。

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)

Java, JavaScript, PHPがメインな自分としては、過去に読んだEffective JavaJavaScript: The Good Parts、Clean Code、リファクタリング、プログラミング作法と基本的に同じ情報ではあったのですが、ここ最近のトレンドを取り込み、薄い本としてまとめているというところに非常に価値のある本でした。


その中でも一番のお気に入りは、「2.4 名前に情報を追加する」の項で書かれているハンガリアン記法と区別してイングリッシュ記法を提唱している以下の部分です。

これってハンガリアン記法なの?

ハンガリアン記法というのは、Microsoft社で広く使われていた命名規則だ。すべての変数名の接頭辞に「型」をつける。例えばこんな感じだ。

変数名 意味
pLast あるデータ構造の最後の要素を指すポインタ(p)
pszBuffer ゼロ終端(z)の文字列(s)バッファを指すポインタ(p)
cch 文字(ch)のカウント(c)
mpcopx カラーポインタ(pco)からX軸のポインタ(px)を指すマップ(m)

これも「名前に属性を追加」しているけれど、もっと厳密で規律のあるシステムだ。
一方、僕達が提唱しているのは、もっと大まかで規律のゆるいシステムだ。必要な時にだけ変数の大切な属性を見つけ出して、それを読みやすくして名前に追加する。これをハンガリアンならぬ「イングリッシュ記法」と呼んでもいいだろう。


この項では、変数名を

var start = (new Date()).getTime();

ではなく

var start_ms = (new Date()).getTime();

と書いたりして、変数名に属性を追加しわかりやすくしようということを言っています。


載っていた例としては

状況 変数名 改善後
passwordはプレインテキストなので、処理をする前に暗号化すべきである。 password plaintext_password
ユーザーが入力したcommentは表示する前にエスケープする必要がある。 comment unescaped_comment
htmlの文字コードUTF-8に変えた。 html html_utf8
入力されたdataをURLエンコードした。 data data_urlenc

といったものです。


このイングリッシュ記法は本当に重要で、変数をわかりやすくする他、変数名にあえて属性を入れることで変数の意図しない使い回しを避けさせる効果もあります。

var start = new Date();
if('ms' === type){
    start = start.getTime();
}else if('array' === type){
    start = [start];
}else if('sec' === type){
    start = start / 1000;
}else if('string' === type){
    start = "" + start;
}

// ... この数百行程度の別なコード

// TODO 1年後、startを使った処理を他人が書く。バグらないだろうか?

こういうコードが本当に多いのも難点ですが...、もしこのstartという変数がstart_msやstart_arrayだとすれば、さすがにミリ秒や配列以外のものを代入しようとは思いませんし、また後でこの変数を利用する人が余計な型チェックや状態チェック、特にsecとmsの判定などをせずに、安心して変数をつかうことができます。


このようにイングリッシュ記法には、余計なコードを排除し、わかりやすくなってバグを減らせるという素晴らしい効果があります。しかもエディタの入力補完があるので、総コーディングタイプ数はそんなに変わりません。


あとこれは前職の先輩に教えてもらったテクニックなのですが、選別に使いたい属性を先にしておくと入力補完機能のあるエディタのあるEclipsevimemacsでは非常に良い副作用があります。

var buttonTitle = null;
var buttonTextArea = null;
var buttonCombobox = null;
var labalTitle = null;
var labalTextArea = null;
var labalCombobox = null;
var titles = null;
var mapCombboxContent = null;

大抵コーディングする場合には、そこに書くべき変数の型というのは決まっていることが多いです。 この場合はtitを押して入力補完を実行するとすぐにタイトルの配列titlesが取れます。
これが、もしボタンやラベルまでtitleが最初に付く変数になっていると、後でボタンなのかラベルなのか配列なのかを候補の中から選ばなくてはいけなくなってしまいます。


実装の内容にもよりますが、属性をつけるのを前にするか後にするかでコーディングスピードを変えることができる、というのもこのイングリッシュ記法のメリットだと思います。この辺も考えながら実装するとより、楽な実装ができるのではないかと思います。
ぜひ、イングリッシュ記法を実践してみてください。では楽しい開発を!

// 2012/07/21 変更 最後の例がシステムハンガリアンを強制するような内容であったのでJavaScriptで書き直し