いまさらリーダブルコードまとめ (第7章)


はじめに

チーム内リーダブルコード輪読会の第7章。
第5・6章はこちら

第7章 制御フローを読みやすくする

どんな内容?

  • 結果的に同じ処理になるとしても、他の人が見てより読みやすい方の書き方を選択しよう
  • 「読みやすい方」とは、以下のようなもの。
    • 読み手にとって直感的(一般的な慣例に従っている)
    • 読み手の脳(記憶)への負荷が小さい

読んだ感想

 コードの書き手にとって、条件式の順番やネストの深さというのはそこまで気にならない。
なぜならば、今自分が書いたばかりで、多少複雑なコードでもすぐに理解できるから
ただ、それはあくまでも「自分は読める」というだけなので、コードレビューに出すときは今一度自分のコードを見返して「このコードは本当に読みやすいのか?」と振り返ってみた方がいい。
 あと、「既存のコードに手を加えるとき、条件式が複雑になったりネストが深くなりやすい」という点も印象的だった。
日々の開発では、「既存のAというfunctionにαという条件を追加してほしい」というような"小さい修正"が良くあるが、そういうときに何も考えずに条件追加するとコードがどんどん複雑化していってしまうので、意識付けする観点としては非常に重要だと感じた。
 この章で述べられているようなアンチパターンに対処することで、結果的にレビューが短く済むようになりそう。

例を挙げて議論してみよう

条件式、if-elseの並び順

7-1
boolean isAdult(int age) {
  if(20 > age) {
    return false;
  }

  return true;
}

リファクタリングポイント

  • 評価対象の引数を条件式の左辺にした方がいい
  • 「20歳未満かどうか」よりも「20歳以上かどうか」の条件式にしたほうがいい

do-whileを書き直す

7-2
String result = null;
int index = 0;

do {
    result = fetchFromDB(index);
    index++;
} while(result != null);

リファクタリングポイント

  • while(true)とbreakを組み合わせる
  • もしindexに仕様上の上限があるなら、for文に書き換える

関数内で早くreturnする(Guard節)

7-3
boolean hasA(String input) {
  String target = input;
  if(target == null) {
    target = "";
  }

  boolean result = target.contains("A");

  return result;
}

リファクタリングポイント

  • inputがnullだったらreturn falseする
    • その場合、targetという一時変数は不要になる

ネストを減らす

7-4
if (checkA) {
  doSomething(true);
  if (checkB) {
    doAnother(true);
  }
} else {
  doSomething(false);
}

リファクタリングポイント

  • if(checkA){}else{}いらなくて、doSomething(checkA)でいいのでは。

補記

輪読会メンバーのメイン使用言語がJavaなので、Stream APIとかOptionalにも言及されて、「そもそもnullチェックのifや、Listを処理するためのループは自前で記述する必要だいぶ減るよね」という話に。