Readable Codeメモ:メソッド名や変数名を正しく選ぶ
読みやすさの基本定理とは
コードは他の人が最短時間で理解できるように書かなければいけない。
第二章:名前に情報を詰め込む
1. 明確な単語を選ぶ
メソッド名や変数名は曖昧な単語を使うより、類語辞典を使って、カラフルな単語を選んだ方良い。
例:
- GetPage -> FetchPage, DownloadPage
- Stop() -> Kill(), Resume(), Pause()
- sendの類語: deliver, dispatch, announce, distribute, route
- findの類語: search, extract, locate, recover
- startの類語: launch, create, begin, open
- makeの類語: create, set up, build, generate, compose, add, new
2. tmpやretvalなど汎用的な名前を避ける
entityの値や目的を表す名前を選ぶ。
ループイテレータに関しては、通常はi, j, kなどを使うが、
複雑な場合は club_i, members_iか, 短縮でclubs[ci], members[mi]で使う。
3. 抽象的な名前より具体的な名前を使う
disallow_evil_constructorsよりは、もっと明確的に、disallow_copy_and_assignを使った方が良い ServerCanStart()より、CanListenOnPort()の方が明確的。
4. 名前に大切な情報を追加する
例:
- 16進数の文字列を持つ変数名:
hex_id - 値の単位を入れる:
- ミリ秒を表す変数名に
_msつける - これからエスケープ必要な変数名に
raw_をつける size→size_mb,limit→max_kbps
- ミリ秒を表す変数名に
- 危険や注意を喚起する重要な属性を入れる
untrustedUrl,unsafeMessageBody,plaintext_password,unescaped_commenthtml_utf8:htmlの文字コードをUTF-8に変えたdata_urlenc: 入力されたdataをURLエンコードした
5. 名前の長さを決める:スコープが小さければ短い名前でもいい
6. 名前のフォーマットで情報を使える
例:
- クラス名はCamelCase形式, 変数名はlower_separated形式
- HTMLのidの区切り文字はアンダースコア
id=”middle_column” - classの区切り文字はハイフン、
class=”main-content”
第3章:誤解されない名前
1. 例:filter()
1
results = Database.all_objects.filter(”year ≤ 2011”)
resultsは2011以前のオブジェクトなのか、2011年以降なのか、 ちょっと曖昧で、もっと明確にするなら、select()か、exclude()にする
2. 例:Clip(text, length)
段落の内容を切り抜く関数 Clip(text, length) 最後からlength文字を削除するか(remove)、最大length文字まで切り詰めるか(truncate)、また曖昧。 もしTruncate(text, length)にするなら、lengthはmax_lengthにした方良い
さらに、lengthはバイト数か、文字数か、単語数か、これも明確にする 改善後:Truncate(text, max_chars)
3. 限界値を含めるときはmin/ max使う
4. 範囲を指定するときはfirst, last使う
5. 包含・排他的範囲にはbegin/end使う
6. Boolean値の名前
ブール値の変数名は is, has, can, shouldなどをつける
※rubyだと、末尾に?を付ける方法がある。
read_password = ture -> need_password, user_is_authenticated
否定形を避ける:
disable_ssl = false -> use_ssl = true
7. ユーザーの期待に合わせる
単語を別の意味で使っていたとしても、ユーザーが先入観を持っているため、誤解を招いてしまうことがある。
例えば、get()やsize()など軽量なメソッドとして期待されている。
- 例:
getMean()
ここのgetMean()は過去のデータを全てイテレートして、その場で平均値を計算するメソッド。
getで始まるメソッドは通常なら軽量アクセスという規約があるけど、ここで使うメソッドは大量計算コストがかかる。
その計算コストがかかることを知らないメンバーだと、思わずにgetMean()を呼び出してしまう可能性がある。 そういう誤解を避けるため、computeMean()を使った方良い。
- 例:
list::size()
1
2
3
4
void ShrinkList(list<Node>& list, int max_size) {
while (list.size() > max_size) {
FreeNode(list.back());
list.pop_back();
ここのlist.size()はLinked Listのノード数を事前計算せずに順番にカウントしているので、 計算量はO(n)になっている。
それでShrinkList()全体の計算量はO($n^2$)になっている。
元々size()という名前は暗黙の計算量はO(1)なので、誤解されないようにするため、
この場合は、countSize()やcountElement()にした方が良い。