『リーダブルコード』を読みました。(2)

タグ: | 投稿日: 投稿者:

こんにちは、ニタです。
『リーダブルコード』まとめ、第2回目は変数や関数などの名前について書いていきたいと思います。

良い名前とは?

コードを書いていて、変数名や関数名を決める時、どのように決めていますか?書いているコードの役割、処理の内容を考慮したり、その時の気分だったりでしょうか。

その時の気分で決めるのは、お薦めできませんが、ここでも「理解しやすいコード」を意識した名前付け、「良い名前」が大事になってくると思います。

良い名前とは、変数で言えば、変数の目的や値の内容(実際の値ではなく)がわかり、誤解されないものを指すと思います。

「名は体を表す」と言いますし。
では、良い名前付けには、どういった事を気をつけていけば良いのでしょうか。

明確な単語を選ぶ

曖昧な意味を持つ単語、色々な意味に捉えられる単語は避けたほうが良いでしょう。

ユーザー情報を登録する関数名で、setUserData()に比べてinsertUserData()の方が分かりやすいと思います。SQLのINSERT文で慣れ親しんでいるのもありますし、set…だと何にsetするのか明確ではないと思います。
セッションに登録するのなら、setを使ってsetSession()のような名前だと良いと思います。

また、処理内容の重たさも考慮した名前を選ぶのも重要になってくると思います。
他の人が書いたコードを読んでいて、関数の名前で、その関数が何をしているかおおよそ予想がつく場合もあるでしょう。 

ですが、たまに、よく見かけるgetXXX()のような関数名で、数100行にも渡り、DBの色んなテーブルや外部サービスからデータを取得し計算し…と、複雑かつ時間のかかる処理が書かれている場合もあります。 

get…から始まる関数名は、いろんなコードで見かけるし、これまで何度も書いたことのある関数名だと思いませんか?

なので、getXXX()は「処理が軽そうなイメージ」が持たれるため、前述のような重たい処理の関数の場合は、名前だけでは推測しにくい、普段慣れ親しんでいないような単語を選ぶのが良いと思います。
computeXXX()とかcombineXXX()のようなものに変えてみると、気を引きやすいのではないでしょうか。
もちろん、軽い処理であれば、getXXX()などの慣れ親しんだ単語を使うのは、分かりやすいし良いと思います。

 

他の意味と間違わられないように、状況に合わせた単語選びを

明確な単語を選ぶとしても、1つの動作に対し英単語も結構な数があります。 類語辞典や翻訳サイトや辞典サイトなどで調べて、見栄えの良い単語を使ってみると、他の関数と差別化が図れると思います。

ただし、やり過ぎには注意しましょう。
phpのexplode()とsplit()は、返り値は同じですが、処理方法、引数の内容は異なります。 この2つの関数の違いを名前だけでは判断が出来ません。

また、単語選びを横着して、他の意味に間違われるような単語を選びがちになるケースもあります。
面倒だからと、filter()なんて名前にした場合、何を取捨選択する関数なのかパッと見分かりません。
select(選択)するのかもしれないし、逆にexclude(除外)するのかもしれません。

 

名前に情報がないもの、汎用的な名前は避ける(※ただし状況を選ぶ)

名前だけである程度内容や変数の値が分かるように、いちいち考え、調べて命名している時間がない場合もあるでしょう。
そんな時やってしまいがちなのが、$tmp,$returnなどの汎用的な変数名だと思います。
気持ちはわかるのですが、やはり名前に情報を持たないものは避けた方が良いです。
後から困るのは自分だし、他の人が読んだ時理解するのに時間がかかるでしょう。

ただし、以下の場合は例外として使用してもいいと思います。

  • 使用期間が短く、他に渡されたり何度も書き換えられない。
  • この変数には他の役割がない、他の処理で使えないと分かる場合。

これらに該当しないが、どうしても使いたい場合は、それ相応の理由をコメントなどに明記しておくべきでしょう。

ただし、「時間がない」「適切な名前が思い浮かばない」といった理由は、改修時や他の人がそのコードを読む時に困るので、やめましょう。バグの温床です。

また、ループ処理のイテレータに、i,j,kなどを使用していると思いますが、ループが複数ネストする場合やループが長い場合、どれがどのループのイテレータなのかi,j,kだけでは分かりにくくなりませんか?
そのような場合は、category_i,users_i,orders_iというように、説明的な変数名を使用すると分かりやすいと思います。

 

具体的な名前を使う

たまに、他の関数や変数との差別化を測りすぎて、抽象的な名前になってしまう場合もあるかもしれません。僕も前科があります(笑)。
WordPressのプラグインで、プラグインを有効化した時実行される関数をhelloRucy()、アンインストール時に実行される関数をgoodbyRucy()としてました。
開発当時は、自分が分かれば良いやと名づけたのですが、オープンソースのプラグインでそれは無いなと反省しています。
他の関数、変数と差別化を図る場合は、具体的な名前で考えたほうがいいでしょう。

 

プレフィックス、サフィックスなどを使用し、情報、属性を追加する。

コードが長くなっていって、変数名が一つの単語だけでは分かりにくくなる場合もあるでしょう。

例えば、$startの単位は何なのか?$limitは最大値なのか最小値なのか、単位は何なのか。
$startの場合、単位がミリ秒なら、$start_msというようにサフィックスをつけると分かりやすくなるでしょう。
$limitにしても、$max_page, $min_pageのように限界値を示すプレフィックスを付けると良いでしょう。

範囲を指定するような変数の場合は、$first_…, $last_…または、 $begin_…, $end_…などのプレフィックスに情報を追加して、分かりやすくなると思います。

その他にも、プレフィックスに属性を追加するとコードを追っていかなくても、変数の内容が分かる場合もあります。

  • パスワードを代入する変数$passwordの値が、暗号化前の平文の場合、$plain_passwordとする。
  • ブール値なら、is_…, has_…, can_…, should_…といったプレフィックスを付ける。この場合、肯定形の名前にすると、if文の条件分岐などが分かりやすくなる。

 

名前の長さを決める

具体的で、プレフィックスを追加していくと長い変数名、関数名になっていくでしょう。 打つのが面倒で、短い名前にする場合もあると思います。

ですが、cssで、padding-top:10pxの指定するクラス名「pt10」は、やはり理解するのに時間がかかります。
名前が短すぎると、型とか意味が名前から分からなくなり、バグの温床になります。
また、処理の中で長く使う(スコープが大きい)変数には、長く説明的な名前を付けると、コードを読み進めるときも分かりやすくなるでしょう。

しかし、長すぎる名前で省略しても分かる場合は、短くしても良いでしょう。
ConvertToString()という関数名で、Convertがなくても、ToStringだけでも文字列に変換する関数だとわかると思います。

さて、逐一これまで書いてきたことを実施していくと、時間ばかり取られるのでは?と思うでしょう。
名前を決めるのにも、長くなった変数名を打つのも時間がかかります。
全てに対して実施しなさいということではなく、「変数の意味を取り違えたらバグになりそうな箇所だけ」でもいいと思います。
つまり「変数の意味を理解してもらわないと困る場合」は、変数名をしっかり考えるべきということです。

 

プロジェクト、チーム固有のルール、省略形、頭文字は避ける。

名前の長さやプレフィックス、サフィックスなど命名規約を決めていくのは良いことですが、度が行き過ぎて、プロジェクト固有のルールになり過ぎないよう注意が必要です。
フレームワークを使用している場合(symfony 1.x系のコアクラスにはsfが先頭に付くlowerCamelで書かれています)や、共通認識としてある汎用的な省略形は例外だと思いますが。
また、フレームワークや言語固有の命名規則もあるので、それに則るのも良いでしょう。

 

まとめ

今回も長々と書いてしまいましたが、まとめると、こんな感じになります。

  • 明確な単語を選びを。
  • 汎用的な単語は避け、具体的な名前を使い、内容を詳細に説明する。※明確な理由があれば別
  • 変数名、関数名に重要な情報を追加する。
  • スコープの大きな変数には長い名前を付ける。
  • 独自命名規則は避ける。バグの温床。
  • 最善の名前は、誤解されない名前。

コード内の処理がしっかり動いていても、変数名、関数名がおざなりになっていると、いざメンテナンス、改修時に工数が取られる原因につながります。
多少面倒かと思いますが、気をつけていただければと思います。
それでは、また。

Share on Google+Tweet about this on TwitterShare on StumbleUponShare on Facebook

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>