else句を使わないのが良いコードなの?いや、そんなはずは・・・

「オブジェクト指向できていますか?」というスライドをみました。
私もオブジェクト指向についてはまだまだ発展途上なので大変勉強になりました。

オブジェクト指向に馴れていない人にとってはこのように極論かつ単純なルールを提示した方が頭の体操になってよいですね。
(1クラスにプロパティは何個まで、1メソッドでインデントは何階層まで、等)

さて、(オブジェクト指向とは関係ないかもしれませんが)if elseの書き方について次ような主張があったので気になりました。
「else句を使用しないこと」
if (条件) {
  return 20;
} else {
  return 30;
}
if (条件) 
  return 20;
return 30;
こうすれば確かにネストは浅くなりますが、いつも毎回こう書く方がよいのでしょうか?

elseを書いた方がよいケースもあるのではないか

条件の部分が特殊・例外的な場合は、確かにこの方がわかりやすいと思います。
例えば、スーパーマリオで、マリオの状態が「無敵・チビ・大きい」の3種類しかないとします。

敵に触れたときの挙動を関数として書きます。
(オブジェクト指向っぽくないかもしれませんが、本記事の主眼はif-elseの書き方です。)
function () {

    if (マリオ.is無敵モード) {
        敵.死ぬ();
        return ;
    }

    //以下、通常モードの場合のコードを書く


}

無敵モードは特殊な状態だから、これはよいと思います。

しかし、マリオが大きいか小さいかの条件分岐についてはどうでしょうか?
マリオの大小はどちらが特別というものではなく、どちらも通常の姿だと思うので、else句を書いた方がわかりやすいと思います。
function() {
  
    if (マリオ.is無敵モード) {
        敵.死ぬ();
        return;
    }

    if (マリオ.isチビ) {
        マリオ.死ぬ();
        return;
    } else {
        マリオ.チビになる();
        return;
    }

}

マーティン・ファウラーの「リファクタリング」本の主張

マーティン・ファウラーの名著「リファクタリング」という本があります。
この本の中で、早期リターンとif・elseについての記述があります。

第9章 条件記述の単純化 「ガード節による入れ子条件記述の置き換え」

特殊ケースに対してガード説を使う
double getPayAmount() {
   if (_isDead) return deadAmount();
   if (_isSeparated) return separatedAmount();
   if (_isRetired) return retiredAmount();
   return normalPayAmount();
}

条件記述は次の2つの形式に分類されます。
1つは、条件判定のいずれも正常条件であって、どちらのルートを取るかを判定するものです。
もう1つは、条件判定の結果の一方が正常条件で、それ以外は特殊条件である場合です。

もし、両方が正常処理ならば、ifとelseを持った条件記述を使うべきです
特殊条件では、条件をチェックしてその結果が真のときにはリターンします。

if-then-else構造が使われるときは、if部にもelse部にも同じウェイトが置かれています。
これが、プログラムの読み手に対して両方とも等しく起こり得ること、等しく重要であることを伝えます。

この主張にはかなり説得力があると思うのですがいかがでしょうか。

追記

サンプルコードがOOPとしておかしいという指摘がありましたので修正しました。
カテゴリ:

人気記事