http://www.objective-php.net/basic/exception
を読む限り、エラー時のメッセージをcatchブロックにまとめられるのがメリットのようですね
PHP に限らず、例外機構のメリットは大きく二つあります。
サブルーチンやメソッドで処理に失敗したときには、それをハンドリングする処理が必要です。
例外機構が無いプログラムでは、戻り値で判定するしかありませんでした。
$ret = func1(...); if ($ret != 0) { $msg = ... Logger::write($msg); exit(100); } $ret = func2(...); if ($ret != 0) { $msg = ... Logger::write($msg); exit(100); } $ret = func3(...); if ($ret != 0) { $msg = ... Logger::write($msg); exit(100); }
見て分かる通り、コードの大半をエラー処理が埋め尽くしています。
エラー時のメッセージを残して処理を終了するだけでこんな感じですから、RDB を扱う処理のように後始末が必要な場合には、本来の処理が読みにくくなり保守性が下がります。
/* 本来の処理の流れ */ func1(...); func2(...); func3(...);
特に対処しているエラーが滅多に出ないものだと何が大事なのかがよく分からなくなってしまいます。
これが関数が例外を送出するように作ると、以下のように記述することができます。
try { func1(...); func2(...); func3(...); } catch (Exception $e) { $msg = $e->getMessage(); Logger::write($msg); exit(100); }
コードの追いやすさの差は歴然です。
さらにもうひとつメリットがあってエラーを通知するメッセージの組み立てを隠ぺいできることです。
特に大規模な開発だと各処理の結合度を疎にすることがとても大切ですが、最初の例だとエラーメッセージの組み立て、つまりどのパラメータをどのように使っているかを想定しながらエラー処理を書いているわけで、関数内部の処理のロジック変更が呼び出しているコードにまで影響を与えるということになります。
例外機構を使った場合には、その処理も例外を送出する方に押し込める(隠ぺいする)ことができるのでモジュール間の結合度を疎に保ち変更があったときの影響度合いを減らすことができます。
もうひとつのリカバリ処理についてです。
例えば、データベースで複数のテーブルに一貫性が必要な更新をするときのことを想像してください。
全てのテーブルについて更新が成功した場合には最後に COMMIT 、ひとつでも失敗したら ROLLBACK です。
finally 節も含めて以下のようになります。
$db = new PDO(...); try { $db->beginTransaction(); /* ここにも複雑な処理が入る */ $pnn = $db->prepare('INSERT INTO ...'); $pnn->bindParam(...); $pnn->execute(); /* ここにも複雑な処理が入る */ $pnn = $db->prepare('INSERT INTO ...'); $pnn->bindParam(...); $pnn->execute(); ... $db->commit(); } catch (PDOException $e) { try { $db->rollBack(); } catch (Exception $e2) { // 多分何もできない } } finally { try { $db->close(); } catch (Exception $e3) { // 多分何もできない } }
DB への書き込みのパラメータを求めるために複雑な処理が入ったり、さらにサブルーチンで処理をされたりします。
その際に例外機構を使っておくと問題が起きたときの後始末(ここでは ROLLBACK )が抜けることがありません。
より確実な動作を例外機構が約束してくれます。
これは PHP に限らず例外機構を持つプログラム言語に共通して言えることです。