条件分岐のせいで可読性が落ちるとき
条件分岐があると読みにくくなるパターンは以下のどれかだと思います。
- 条件が何を意味しているのかわからない。
- 条件分岐が連発して、ネストが深くなりすぎている。
条件分岐があることによる、可読性の低下を救う方法
条件分岐を単純化するための方法はいくつかあります。
これに対して、条件分岐を単純化するための方法は
- 条件の意図を伝える
- 以下のいずれか、またはいくつか組み合わせてネストを解消する。
- アーリーリターン
- ガード節
- ポリモーフィズム
条件の意図を伝えるとは
まず、以下のコードを見てください。
if (isNobodyInTheOffice()
&& isOfficeHour()
&& isPhoneRinging()
&& person.isClosestToThePhone()) {
person.stopWorking();
person.getOffChair();
person.moveToByThePhone();
person.takeThePhone();
}
条件分岐の内容はメソッド名から内容がわかりやすいですが、条件分岐のところは非常にわかりにくいですね。
この理由は、条件が複数あること、意図がしていることがわからないことが挙げられると思います。(条件が複数なくても、意図がわからないと可読性が低い場合は後述)
上記のプログラムは、条件をメソッド化してしまい命名で意図をわかりやすくすると可読性が向上します。
if (shouldTakePhoneCall()) {
person.stopWorking();
person.getOffChair();
person.moveToByThePhone();
person.takeThePhone();
}
private boolean shouldTakePhoneCall() {
return isNobodyInTheOffice()
&& isOfficeHour()
&& isPhoneRinging()
&& person.isClosestToThePhone();
}
なので、処理の意図がわかりにくい場所ではメソッド化して、意図を命名に反映しましょう。
条件が複数なくても可読性が低い条件分岐
if (user.house.capacity < invitees) {
user.cancelPreparingHouse();
user.call(restaurantA);
}
特に >
<
といった演算子は脳内で処理するのに時間がかかるので、可読性は低くなります。
これも、メソッド化して意図を命名に与えれば解決します。
if (isCapacityOver(invitees)) {
....
}
private boolean isCapacityOver(int num) {
user.house.capacity < num;
}
アーリーリターンとガード節
以下のプログラムを見てください。
double getPayment() {
double result;
if (isDead) {
result = deadAmount();
} else {
if (isSeparated) {
result = separatedAmount();
} else {
if (isRetired) {
result = retireAmount();
} else {
result = normalAmount();
}
}
}
return result;
}
double getPayment() {
if (isDead) return deadAmount();
if (isSeparated) return separatedAmount();
if (isRetired) return retireAmount();
return normalAmount();
}
ガード節の考え方だと、if - else 構造が使われるべきなのは両者の処理が等しく起こりうる(重要な)時です。
そのため、上記のプログラムで言えば normalAmount();
が通常系で、それ以外のより少ない確率で発生する処理に関してはアーリーリターンを行うことで異常系であることを示しています。
こうすることで、コードを読むときにどこが一番重要な処理なのかが明示的になり、コードリーディングに強弱をつけられるので負担が減りますね。
また、構文も if (条件文) return 処理;
というふうに統一がとれているのでより読みやすいです。
ポリモーフィズム
to be continued...