書籍「リーダブルコード」 2章 まとめ

2章

名前に情報を詰め込む

プログラミングにおける命名(変数や関数など)は、なるべく多くの情報を詰め込むようにする。

「名前は短いコメント」

具体的には、以下のようなことを意識して命名を行なう。

明確な単語を選ぶ

例えば「getPage」という関数名からは、どこからページを取得するのか分からない。仮にネット上から取得するのであれば、「downloadPage」の方がより明確。

汎用的な名前を避ける

例えば「tmp」「retval」「foo」などの、どこにでもあり、意図が明確に伝わらないような名前。

tmp

一時的に値を保持するという意味合いで使われることが多く、適切に扱われている場面もある。

例 (左 > 右のとき、値を入れ替える)

if left > right:
    tmp = right
    right = left
    left = tmp

この場合は、以下のような理由から問題が無いと言える。

  • tmpの生存期間がたったの3行
  • 値の一時保持以外の役割がない

但し、関数の引数や、長期に渡る値の保持に用いるのは不適切である。

retval

retvalは関数の返り値を表す変数名として使われがち。

例 (配列の2乗の合計を返す関数)

def euclidean_norm(nums):
    retval = 0.0
    for value in nums:
        retval += value * value
    return retval

この場合、「retval」だけでは情報が不足しているため、「sum_squares」という変数名の方がより明確である。

ループイテレータ

「i」「j」「k」などは、ループイテレータとして使う分には問題ない。但し、複数のイテレータが存在する場合、以下のようにすることで情報がより明確になる。

clubs[ci].members[mi] == users[ui]
#各要素の頭文字と組み合わせている

抽象的な名前より具体的な名前

変数や関数などの構成要素の名前は、抽象的なものではなく具体的なものにする。

例えば「--run_localy」というコマンドオプションが存在したとする。

  • デバッグ情報を印字する機能を持つが、その分遅くなる
  • ローカル環境のみで使用、リモートではパフォーマンスを阻害するため未使用

しかしこの場合は、「--extra_logging」(ログの追加)という名前の方が明確である。なぜなら以下のような問題があるから。

  • ローカルで動かす時に使用されるのは分かるが、どんな機能を持っているか分からない
  • リモートでデバッグ情報を表示したい時、リモートなのに「localy」という矛盾が発生する
  • ローカルでパフォーマンステストしたいときは利用されない
名前に情報を追加
単位

値などを保持する場合、単位情報を追加する。

元の引数 単位を追加
delay delay_secs
size size_mb
limit max_speed
angle degrees_cw
重要な情報

セキュリティの問題や、データの形式などの情報も追加した方がいい。

状況 変数名 状況を追加した変数名
プレインテキストのパスワード(暗号化が必要) password plaintext_password
エスケープ未処理のコメント comment unescaped_comment
utf8に変換されたhtml html html_utf8
URLエンコードされたデータ data data_urlenc

ただし、全ての変数に適用するのではなく、間違えたらバグになりそうな部分にのみ使うべきである。

変数の長さの決め方

命名時は「長い名前を避ける」という暗黙的な制約がある。

スコープが小さければ短くてもいい

スコープ(名前が見えるコードの行数)が小さければ、わざわざ多くの情報を詰め込む必要はない。

def debug():
    m = userMail()
    print m

要するに、全体でコードを理解するために十分な要素があればいい

但し、クラスのメンバや引数などのスコープの広い変数には、相応に情報を含まなければならない。

def debug(m):
    print m

これだとmの意味が分からない。 あくまで「必要な情報を含んだ上」で、名前が長くなるのは問題無い。

頭文字と省略形

名前を省略する場合は、プロジェクト固有の省略形は避け、新しくプロジェクトに参加したメンバーでも理解できるような命名を行なう。

例えば、クラス名「BackEndManager」を「BEManager」と表記しても、新しいメンバーは理解できないだろう。

(誰もが知っているような「String」を「str」、「document」を「doc」などは問題ないと言える)

不要な単語は削る

特定の単語を削除しても、情報が損なわれない場合は削除すべき。

変換元 変換後
convertToString toString
doServelLoop servalLoop

名前のフォーマットで情報を伝える

エンティティごとに命名法則を変えることで、区別がしやすくなる。

class LogReader{
    public:
        void OpenFile(string local_file);

    private:
        int offset_;
        DISALLOW_COPY_AND_ASSIGN(LogReader);
}