【リーダブルコード】読みやすいフロー制御を作る
※ 下記のリンクにある本の韓国語版を読んで簡単に整理しました。
条件文の引数の順番
次の2つのコード、どちらが読みやすいだろうか?
if (member.count() >= 5) {
...
}
if (5 <= member.count()) {
...
}
または、以下のような比較:
while (loaded < total) {
...
}
while (total > loaded) {
...
}
ほとんどのプログラマーは前者の方が読みやすいと感じるはず。これは、より可変な値(質問される側)を左に、固定的な比較値を右に置くというルールに基づいている。
このルールは英語の語順とも一致する。
たとえば:
- 「あなたが少なくとも年収10万ドルあるなら」
- 「あなたが18歳以上であるなら」
といった言い方は自然だが、
- 「18があなたの年齢以下であるなら」
という言い方は不自然に感じる。言語感覚とプログラムの可読性は密接に関係している。
この原則は、例えば assertEquals(expected, actual) のようなテストライブラリでも見られる。
assertEquals(expected, actual);
ここでは、変化しうる値(実際値)が右側に、基準となる期待値が左側にある。
if / else ブロックの構造
以下のようなコードがあるとする:
if (a == b) {
// ロジックA
} else {
// ロジックB
}
これを以下のように書き換えることもできる:
if (a != b) {
// ロジックB
} else {
// ロジックA
}
この書き換えは、「否定を避け、肯定的な条件を先に書く」という原則に基づいている。
✔️ より読みやすい条件分岐の例
if (req.getParams().isReverse()) {
list.reverse();
} else {
// 通常の並びで表示
}
より読みやすく、意図がすぐに伝わる。否定形の条件は脳内で「反転」して解釈する必要があり、理解に余計な認知負荷がかかる。
✖️ 読みにくい例(否定条件)
if (!req.getParams().isReverse()) {
// 通常の並びで表示
} else {
list.reverse();
}
また、次のように否定が自然な場合もある:
if (!jwtToken.isPresent()) {
// 401 Unauthorized を返す
return;
}
// 続きの処理
ここでは否定条件が自然に見えるが、それでもできる限り直感的に理解できる構造を選びたい。
関数の途中で return する
public void login(String id, String pw) {
User userById = userRepository.findById(id);
if (userById == null) {
// IDが存在しない
return;
}
User userByPw = userRepository.findByIdAndPw(id, pw);
if (userByPw == null) {
// パスワードが間違っている
return;
}
// ログイン成功処理
}
関数の途中で return を使うと、ネストが減ってコードがフラットになり、読みやすくなる。
「関数は return を1つにすべきだ」と考える人もいるが、読みやすさやメンテナンス性を考えると、早期リターンはむしろ推奨される場面も多い。
第7章の感想
この章では、一見すると些細なスタイルの違いが、読みやすさやバグの予防に大きな影響を与えることを実感させられた。
- 条件式の順序
- 否定より肯定を優先する
- ネストを減らす return の活用
これらはコードの流れを読み手にとって自然なものに整える技術であり、
意識して取り入れることで、日々のコーディングが一段と洗練されていくと感じた。
Discussion