書籍「リーダブルコード」 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); }