多段 if 文はプログラムの可読性を損いバグの温床となるため、多くのプログラマーがそれによって悶え苦しみ、日夜命を落としています。
今日は、そんな憎き多段 if 文をやっつける方法を考えたいと思います。
これを、素直に次のようにコーディングします。
code 1
// $condition1~5 には条件式が入るとします。つまり boolean が入ります。 // $goal に数値を入れているだけですが、実際にはここに具体的な処理を置きます。 $goal = 0; if ($condition1) { if ($condition2) { $goal = 1; } else { if ($condition4) { if ($condition5) { $goal = 1; } else { $goal = 2; } } else { $goal = 3; } } } else { if ($condition3) { $goal = 4; } else { if ($condition4) { if ($condition5) { $goal = 1; } else { $goal = 2; } } else { $goal = 3; } } }
多段 if 文の下地ができました。これを応用してネストを深くしていくとプログラマーを殺すことができます。
さらにコードの 7 ~ 15 行目と 21 ~ 29 行目が重複しています。
もし、条件4と条件5の間に新しい条件6が挿入される、つまり
・条件4が真のときに条件6の判定を行う
・条件6が真のときに条件5の判定を行う
という仕様変更が発生すると2カ所にまったく同じ修正が必要になり、プログラマーは死にます。
条件分岐を見るとついこのように書きたくなりますが、一寸ここでフローチャートを眺めてみると、だんだんと次のように見えてきます。
なんと、状態遷移図っぽくなりましたね!
while 文の中で状態を遷移させていき、それぞれの状態を switch-case 文で記述するような感じで、この図の処理を次のようにコーディングしてみましょう。
code 2
$state = 1; $goal = -1; while ($goal == -1) { switch ($state) { case 1: if ($condition1) { $state = 2; } else { $state = 3; } break; case 2: if ($condition2) { $goal = 1; } else { $state = 4; } break; case 3: if ($condition3) { $goal = 4; } else { $state = 4; } break; case 4: if ($condition4) { $state = 5; } else { $goal = 3; } break; case 5: if ($condition5) { $goal = 1; } else { $goal = 2; } break; default: $goal = 0; break; } }
それぞれの状態で条件の判定を行い、次に移るべき状態がある場合は $state に対応する値を代入し、ゴールに到達すれば $goal に値を代入してループを抜けます。
行数は増えましたが、シンプルな case 文によって構成されたコードになりネストが浅くなりました。また、条件4の重複もなくなりました。
条件4と条件5の間に条件6が挿入される場合は、$condition4 が true のときに $state に条件6を差す別の値を代入し、それに対応する case を書いてやればOKです。図でいうと矢印の行き先を変更するイメージです。
常にこの方法が適用できるわけではないかと思いますが、上手くいくこともあるんじゃないか、ということで。