【PHP】行き先の多い分岐に例外を埋め込んでおくと改修が捗る時がある

  • 2024年2月23日
  • PHP

 PHPで行き先の多い分岐を扱う際、未定義の分岐先(あるいは入ることのない分岐先)に例外を仕込んでおくと後の改修作業が少し楽になります。この記事ではその実装方法と例を紹介します。

 プログラムを書く過程で状態遷移など複数の分岐が生じる瞬間がしばしばあります。これはとにかく今コードを動かす目的だけならば、次のようにシンプルに書くことができます:

if($state === State::INIT){
   // 初期状態
} else if($state === State::ACTIVE) {
  // 活動状態
} else {
  // 終了状態
}

 このコードは期待通りに動作しますが、将来的に状態が増えた場合にこのコードが更新されないと新しい状態も終了状態とみなされてしまう危険性があります。そこで以下のように書くことで起きるやもしれない改修に備えます。

if($state === State::INIT){
   // 初期状態
} else if($state === State::ACTIVE) {
  // 活動状態
} else if($state === State::END) {
  // 終了状態
} else {
  throw new \LogicException('考慮されていないパターンです'); 
}

 この方法ではコード量が増えますが状態が増えた時に未改修の箇所に気づきやすくなります(TypeScriptの型機能とかがあれば静的解析で動かす前に気づけるようになる気もしますが)。経験則ですが、多くの分岐が存在する箇所では、更に分岐が増加し複雑になりやすいです。このため少々余分なコードでもこういったものを書いておくのは案外役に立ちます。

 上記の例はif文ですがswitchやmatchでもdefaultに例外を投げさせることで同様の効果を得ることができます。例えばswitchでは以下のように書けます。

switch ($state) {
    case State::INIT:
        // 初期状態
        break;
    case State::ACTIVE:
        // 活動状態
        break;
    case State::END:
        // 終了状態
        break;
    default:
        throw new \LogicException('考慮されていないパターンです');
}

 matchでは次のように書けます。

$result = match ($state) {
    State::INIT => // 初期状態の処理,
    State::ACTIVE => // 活動状態の処理,
    State::END => // 終了状態の処理,
    default => throw new \LogicException('考慮されていないパターンです'),
};

 とはいえ、実はmatchの方はこういったものを書かなくてもいい感じに動作してくれます。これはmatchではdefaultが未定義の状態で既存の条件に当てはまらない場合は Uncaught UnhandledMatchError: Unhandled match caseとエラーを投げてくれるためです。改修すべき部分が改修されていなくても、それがmatchの部分ならすぐ気づけるわけです。

 読みやすいコードという観点からは少し遠ざかったコードになりますが、コードを改造する際にどこをどう触ればいいのかという手がかりのために使わないフローについてのコードやコメントを書いておくのは結構役に立ちます。

>株式会社シーポイントラボ

株式会社シーポイントラボ

TEL:053-543-9889
営業時間:9:00~18:00(月〜金)
住所:〒432-8003
   静岡県浜松市中央区和地山3-1-7
   浜松イノベーションキューブ 315
※ご来社の際はインターホンで「316」をお呼びください

CTR IMG