第9章 制御フローを読みやすくする
- 条件やループなどの制御フローはできるだけ「自然」にする。コードの読み手が立ち止まったり読み返したりしないように書く
条件式の引数の並び順
左側 | 右側 |
---|---|
調査対象。変化する | 比較対象。あまり変化しない |
if/elseブロックの並び順
- 条件は否定式よりも肯定式を使う。if(!debug)ではなく、if(debug)を使う
- 単純な条件を先に書く。ifとelseが同じ画面に表示されるので見やすい
- 関心を引く条件や目立つ条件を先書く。否定形の条件であっても単純に関心や注意を引く場合もある。先に書いてもいい
三項演算子
- 行数を短くするよりも、他人が理解するのにかかる時間を短くする
- 基本的にはif/elseを使おう、三項演算子はそれによって簡潔になるときだけ使う。(条件が簡単なとき)
do/whileループを避ける
do/whileループの欠点:
- コードブロックを再実行する条件が下にあるのでコードを2回読むことになってしまう。
- 内部にあるcontinue文が紛らわしい
関数から早く返す
関数で複数のreturn文よりもクリーンアップコードのイディオム(javaなら、try...finally)を使う
ネストを浅くする
- 変更するときにはコードを新鮮な目で見る。一歩下がって全体見る
- 早めに返してネストを削除する。特に「ガード節」(関数の上部で単純な条件を先に処理するもの)が便利だ。
- ループ内部のネストを削除する
巨大な式を分割する
巨大な式は飲み込みやすい大きさぬ分割する
説明変数
式を表す変数を使えばいい:
説明変数使ってない場合:
if line.split(':')[0].strip() == "root":
...
usernameは説明変数として使う場合:
username = line.split(':')[0].strip();
if username == "root":
...
要約変数
式を説明する必要ない場合でも、大きなコードの塊を小さな名前に置き換えて、管理や把握を簡単にする変数は要約変数と呼ぶ。
ド・モルガンの法則を使う
- not (a or b or c) = (not a) and (not b) and (not c)
- not (a and b and c) = (not a) or (not b) or (not c)
- ド・モルガンの法則を使って否定形減らせる
- 例:
- if(!(file_exists && !is_protected))
=> if(!file_exists || is_protected))
- if(!(file_exists && !is_protected))
- 例:
短絡評価の悪用
ブール演算子は短絡評価を行うものが多く、便利だけど、悪用すると複雑なロジックになってしまう。
他人見やすいため、短い「頭がいい」コードに気をつけます。
巨大な文を分割する
式の分割と同じような文を分割する。
何回も登場してる長い文は要約変数として関数の最上部に抽出すればいい
利点:
- タイプミスを減らす
- 横幅が縮まるので読みやすい
- クラス名を変更することになれば、一箇所を変更すればいい
式を簡潔にするもう1つの創造的な方法ーーマクロ
マクロを頻繁に使えと言ってるわけじゃない。
利点:簡潔で読みやすい
欠点:見つけにくいバグが潜り込んでしまう可能性ある
変数と読みやすさ
変数を削除する
コードが読みやすくならない変数を削除:
- 役に立たない一時変数
- 中間結果(タスクはできるだけ早く完了するほうがいい)
- 制御フロー変数(時差のプログラムに関係のあるデータは含まれない)
変数のスコープを縮める
- 変数のことが見えるコード行数をできるだけ減らす
- グローパル変数を避ける
- メンバ変数(ミニグローパル)「格下げ」
- 定義の位置を下げる(変数を定義は変数を使う直前に移動すればいい)
- 言語によってスコープの決め方は違う
変数は一度だけ書き込む
- 変数を操作する場所が増えると、現在値の判断が難しくなるので変数の変更箇所はできるだけ少なくしたほうがいい。