#はじめに
コードを読みやすくする方法としては、コメントを適切につけること、ロジックを単純化すること、機能を分割することなど色々なものがありますが、今回は「名前の付け方」について自分が気をつけていることをまとめてみました。
当たり前すぎるものや、逆にあまり一般的でないものもあるかもしれませんが、「こんな方法もあるんだ」くらいの気持ちで読んでいただけると幸いです。
サンプルコードはPHPで書いていますが、内容は言語に依存するものではありません。
##ケースはそれぞれの言語の流儀に従う
多くの場合はキャメルケースもしくはスネークケースだと思いますが、基本的に使用する言語の流儀に合わせています。どちらでも良い場合、個人的にはスネークケースの方が読みやすいと感じますが、とにかく統一だけはしましょう。
$stake_case = "これはスネークケースです。";
$camelCase = "これはキャメルケース(正確にはローワーキャメルケース)です。";
$PascalCase = "これはパスカルケース(もしくはアッパーキャメルケース)です";
##変数名は使用される状況に合わせて具体性を決める
適切な変数名は使用される状況によって変わります。
例えばユーザーIDを処理するときに、プログラム内で扱うIDが他になければ
$id
で十分かもしれません。
しかし、他にもIDがある場合は、
$user_id
としないと、どのIDなのかわからないでしょう。
場合によっては削除予定のIDであることを明示するために
$user_id_to_delete
という名前が必要になることも考えられます。
##関数名は機能を明確に表すものにする
他力本願ですが、「うまくメソッド名を付けるための参考情報」などが参考になります。
使用する言語の組み込み関数を参考に名前を付けるのもよい方法ですが、PHPのようにあまり統一が取れていないものもありますね。
シンプルでわかりやすいのが一番ですが、変数に比べると入力する回数は少ないですし、関数名が長くてもエディタが補完してくれるので私は遠慮なく長い名前をつけています。
// 相対パスからURLを作成
function create_url_from_relative_path($base_path, $relative_path) {
// do something
}
ただし、名前の衝突を避けるために名前が長くなるのは好ましくないので、言語仕様として名前空間などを利用できるのであればそちらを利用しましょう。
##値を返す関数の名前は返り値を明確に表すものにする。また、返り値を受け取る変数の名前もそれに合わせる
以下の例では、 ユーザーIDを処理していることが明確になるように、変数名・関数名ともに user_id に何をするのか表す語句を付け加えたものを使用しています。
おそらくコメントがなくても何の処理をしているのかすぐに理解できると思います。
// ユーザー名から削除するユーザーのIDを取得
$user_id_to_delete = get_user_id($user_name);
##なるべく自然な英語になるよう心がける
日本人としては辛いところですが、やはり英語として自然な名前がベストだと思います。
例えば変数の場合、id_to_delete はこれから削除するID、deleted_id なら削除済みのIDというように、変数の性質を端的に表すことができるからです。
英語のフレーズが正しいかどうかを判定する方法の一つとして、Google検索を利用する方法があります。
例えば、挿入された値を格納する変数として
$inserted_value
が正しい英語かどうか自信がない場合、 "inserted value" (ダブルクォート も含む)でGoogle検索すると、約 18,500 件の結果が得られました(2018/1/27時点)。件数としては少なめですが、検索結果の文を読む限りは正しい表現と判断できます。
一方で、日本人が間違いやすい "regist data" (登録するの意である register の er を接尾語と間違いやすい)は約 1,020 件で、検索結果の文にも自然な文章があまりありません。大雑把に言うと5,000 件以下のものは怪しい気がします。
なお、"register data" は約 908,000 件がヒットしました。最近のGoogle検索は賢いので、"regist data"で検索してもまずこちらが先に表示されてしまいますね(「元の検索キーワード」で選ばないと"regist data"は表示されません)。
変数名・関数名に限らず使える方法なのでお試しください。
##配列やコレクション変数の名前は、複数形にするかサフィックスをつける
プログラミングを始めた頃、配列を value[]、 values[]、value_array[] のどれにするかで悩んだ覚えがあります。
言語にもよりますが、foreach系のループを考慮すると、複数形にするかサフィックスをつけるのが自然と思われます。
// 複数形
foreach ($values as $value) {
echo $value; // $valueの値を出力
}
// サフィックス
foreach ($data_list as $data) {
echo $data; // $dataの値を出力
}
複数形にしづらい名前もあったりするので複数形とサフィックスはどちらを使っても良いでしょう。サフィックスは _array や _list などをよく使っていますが、統一できればベターですね。
##変数の値が変わるときに同じ変数を使い回さない。
変数に処理を加えた後、同じ変数に再代入するケースはよくあると思います。
function ($str) {
$str = strtolower($str); // 文字列を小文字に変換して同じ変数に再代入
// do something...
}
単純なケースではこれでも問題ないですが、複雑な処理をする場合は後で見返したときに変換処理を見落として、変数の中身が自分の思っていたものと違ったりする場合があります。また、どのような変数処理なされたのかを確認しないと変数がどのような状態なのかわかりません。
ですので、面倒でも以下のように新たな変数を作成しています。
function ($str) {
$lowered_str = strtolower($str); // 小文字に変換したことが明確な名前の変数を新たに作成
// do something...
}
もちろん、新たな変数を作成するのに大きなコストがかかる場合や、変数処理のステップが多すぎていちいち別の名前を付けられないような場合は無理に新たな変数を作成する必要はないでしょう。
##冗長になっても中間変数を挟む
このように1行で書ける文であっても
// 新しい本を在庫に追加
add_books_to_stock(array_keys(get_new_books_list()));
このように中間変数を挟みます。
// 新しい本を在庫に追加
$new_books_list = get_new_books_list(); // 新しい本のリストを連想配列として取得
$book_id_list = array_keys($new_books_list); // 連想配列のキーがbook_id
add_books_to_stock($book_id_list); // book_idの配列を渡して在庫に追加
こうすることで、それぞれの関数が何を引数にして何を返しているのかが明確になります。
これは名前の付け方ではないですが、意図は同じなので含めてみました。
##関数に引数として渡す変数の名前と関数で定義されている引数の名前を合わせる
関数を先に定義する場合と変数が先にある場合がありますが、どちらの場合もできるだけ名前を揃えます。
// データベースからレコードを検索する関数を定義
function search_records($keyword, $date_from, $date_to) {
// ... 検索処理 ...
return $result;
}
// 関数で定義されている引数に合わせて変数名を定義
$keyword = "解いて覚えるC言語";
$date_from = "2018-01-01";
$date_to = "2018-01-31";
$found_records = search_records($keyword, $date_from, $date_to);
上記の例では完全に一致させていますが、そうでない場合も関連が用意に推測できる名前にするようにしましょう。
// データベースからレコードを検索する関数を定義
function search_records($keyword, $date_from, $date_to) {
// ... 検索処理 ...
return $result;
}
// 関数で定義されている引数との関連がわかりやすいように変数名を定義
$search_keyword = "苦しんで覚えるC言語";
$release_date_from = "2018-01-01";
$release_date_to = "2018-01-31";
$found_records = search_records($search_keyword, $release_date_from, $release_date_to);
##関数内で return する変数名は result とする。
統一する必要性はあまりないのですが、「この変数が返り値になる」というのが一目でわかるのと、名前を考える手間が省けるので私は result で統一しています。もちろん変数の性質から命名してもよいのですが、関数名をきちんとつけていればどのような値を返すのかはそちらでわかります。
##変数名や関数名が合わないと思ったら面倒くさがらずに変更する
変数や関数を使っている箇所を全て変更しないといけないのでついそのままにしてしまいがちですが、面倒でもその都度変更しています。習慣にできるかどうかが勝負のような気がします。
関数が複数のファイルで使われている場合などは作業の手間がエディタの機能に大きく依存するので、よい道具を使うことが大事です(私はSublime Text3を使用しています)。
##短すぎる変数名を避ける。
変数名を変更する場合は何らかの検索機能を用いることになりますが、変数名が短いと目的の変数ではない部分が検索に引っかかってしまいます。
また、単に長さだけではなく、他の変数名や構文、テキスト文字列の一部分になりやすい変数名も避けた方がよいでしょう。そういう意味では、PerlやPHPのように変数名の頭に$が必要な言語は若干有利だったりします。
なお、ループ変数などのように使用目的が明確で使用範囲も狭い場合は短い変数名で問題ありません。
#おわりに
いかがでしたでしょうか。ずいぶんと極端なものも含まれていたかと思います。
自分の書くコードがわかりやすいかどうかは別として、「コードレビューの極意。それは「自分のことは棚に上げる」こと!!」に触発されて書いてみました。
読みやすいコードを書くには、「リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)」が非常に参考になります。
多少なりとも名前の付け方のヒントになれば幸いです。