リーダブルコードを読んだメモ
はじめに
リーダブルコードを読んだので,印象的だった部分のメモを残します. この本は非常に読みやすく,スラスラと読めます. 読んでみて,今まで自分が書いていたコードがどれだけスマートではないのかがわかりました.そして,今後のコーディングをどのように改善すればよいか,書き方,考え方を知ることができました. ただし,読んでいるうちは「ふむふむ」と思っていても,それが実践に活かせるかというと,そこにはギャップがあると思います. 当然ですが,定着を図る必要がありそうです.
3 章 誤解されない名前
3.3 - 3.5
限界値を含めるときは min と max を使う
範囲を指定するときは,first と last を使う
- 例)
print integer range(start=2, stop=4)
これは[2,3]なのか[2,3,4]なのかわからない
print integer range(first=2, last=4)
これは,[2,3,4]となり,包含を表すことができる.
- 包含/排他的範囲には begin と end を使う
- 例)
print integer range(begin=2, end=4)
これは,[2,3]となり,包含/排他的範囲を表すことができる.
7 章 制御フローを読みやすくする
7.2 if/else ブロックの並び順
条件は否定形よりも肯定形を使う.
if (!debug)
ではなく,if (debug)
を使う.単純な条件を先に書く. if と else が同じ画面に表示されるので見やすい.
関心を引く条件や目立つ条件を先に書く.
- 3 についての例)
if (!url.HasQueryParameter("expand_all")) {
response.Render(items);
....
} else {
for (int i = 0; i< items.size(); i++;) {
items[i].Expand();
}
....
}
例における if 文では,url のパラメータとしてexpand_all
を持っていない場合を,else 文ではexpand_all
がある場合をそれぞれ表している.
expand_all
は読み手にとって関心を惹く変数および条件であるので,これを先に処理したほうが読みやすくなる.
- 例)
if (url.HasQueryParameter("expand_all")) {
for (int i = 0; i< items.size(); i++;) {
items[i].Expand();
} else {
response.Render(items);
....
}
....
}
8 章 巨大な式を分割する
8.1 説明変数 8.2 要約変数
- 式を表す変数を説明変数と呼ぶ
- 例)
if line.split(':')[0].strip() == "root":
...
説明変数を使うと以下のようになる.
- 例)
username = line.split(':')[0].strip()
if username == "root":
...
- 大きなコードの塊を小さな名前を置き換え,管理は把握を簡単にする変数を要約変数と呼ぶ
- 例)
if (request.user.id == document.owner_id) {
//ユーザはこの文章を編集できる
}
if (request.user.id == document.owner.id) {
//文書は読み取り専用
}
要約変数を使うと以下のようになる.
- 例)
final booean user_owns_document = (request.user.id == document.owner_id);
if (user_owns_document) {
//ユーザはこの文章を編集できる
}
if (!user_owns_document) {
//文書は読み取り専用
}
9 章 変数と読みやすさ
9.1 変数を削除する-制御フロー変数を削除する- 9.2 変数スコープを縮める 9.3 変数は一度だけ書き込む
- flag のようなプログラムの実行を制御するためだけの変数を制御フロー変数と呼ぶ
- 例)
boolean done = false;
while (/* 条件 */ && !done) {
...
if (...) {
done = true;
continue;
}
}
done のような制御フロー変数は様々な場所で設定され,プログラムに関係するデータは含まれていない.
以下のように改善できる.
- 例)
while (/* 条件 */) {
...
if (...) {
break;
}
}
- C++の if 文のスコープ
PaymentInfo* info = database.ReadPaymentInfo();
if (info) {
cout << "User paid: "<< info->amount() << endl;
}
...
変数 info は,関数スコープ内にあるので,またいつどこで使われるかを考えながらコードを読まなければならない.
以下のようにすることで,スコープを過ぎた info を考える必要がなくなる.
- 例)
if (PaymentInfo* info = database.ReadPaymentInfo()) {
cout << "User paid: "<< info->amount() << endl;
}
- 変数は一度だけ書き込む
変数の値が何度も変更されると,コードを追いかけにくいので変数は一度だけ書き込むことを意識する. C++の const などを積極的に利用する.
10 章 無関係の下位問題を抽出する
- 関数やコードブロックをみて「このコードの高レベルの目標は何か?」と自問する
- コードの各行に対して「高レベルの目標に直接的に効果があるのか? あるいは無関係の下位問題を解決しているのか?」と自問する.
- 無関係の下位問題を解決しているコードが相当量あれば,それらを抽出して別の関数にする.