多段 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です。図でいうと矢印の行き先を変更するイメージです。
常にこの方法が適用できるわけではないかと思いますが、上手くいくこともあるんじゃないか、ということで。
