例外!=エラー

何らかの理由で、多くのプログラマーは、例外とエラーはまったく同じものだと信じています。 誰かが常に例外をスローし、誰かがerrorHandlerを介してエラーを例外に変えます。 例外を使用してパフォーマンスを向上させようとする人もいます。 しかし、実際には、例外とエラーはまったく異なるメカニズムです。 あるメカニズムを別のメカニズムに置き換える必要はありません。 それらは異なる目的のために作成されます。



php5に例外が発生し、その後常に例外をスローするZendFrameworkが表示されたとき、理解できませんでした:なぜ例外がお気に入りのtrigger_error()よりも優れているのでしょうか? 私は長い間考え、同僚と話し合い、この問題を見つけました。 これで、trigger_error()を使用する場所と、新しい例外()をスローする場所が明確にわかりました。



2つの基本的な違いは何ですか?







間違い



エラーは修正できないものであり、報告できるのはログへの書き込み、開発者へのメール送信、ユーザーへの謝罪のみです。 たとえば、エンジンがデータベースに接続できない場合、これはエラーです。 それだけです ポイント。 このサイトはデータベースなしでは機能せず、私はそれについて何もできません。 したがって、ales_kaput()およびtrigger_error()を呼び出すと、errorHandlerから電子メールが送信され、訪問者に「ごめん、サイトがダウンしています」というメッセージが表示されます。



例外



例外は間違いではなく、何らかの形で処理する必要がある特別な状況です。 たとえば、電卓でゼロで除算しようとすると、電卓はフリーズせず、開発者にメッセージを送信せず、謝罪します。 このような状況は、通常のifで処理できます。 厳密に言えば、 例外は、実行のフローを制御できる言語構造です 。 これは、if、for、およびreturnと同等の構造です。 それだけです。 このメカニズムはこれ以上のものではありません。 フロー制御のみ。



主な目的は、カスケードに沿っ転送することです。 これを例で示します。カスケードで相互に呼び出す3つの関数があります。

<?php a(); function a() { b(); } function b() { c(99); } function c($x) { if ($x === 0) { //   , //      c()  b(), //   a()     } return 100 / $x; }
      
      







この問題は、例外メカニズムなしで解決できます。 たとえば、すべての関数に特別な型を強制的に返すことができます(経験豊富なpahapashnikの場合、PEAR_Errorを覚えておく必要があります) 。 簡単にするために、nullを使用します。



 <?php a(); function a() { echo 'a-begin'; $result = b(); if ($result === null) { echo '   '; return; } echo 'a-stop'; } function b() { echo 'b-begin'; $result = c(0); if ($result === null) { return null; } echo 'b-stop'; return true; } function c($x) { echo 'c-begin'; if ($x === 0) { return null; } echo 'c-stop'; return 100 / $x; }
      
      







仕事の結果:



はじめに

b-begin

c-begin

ゼロ除算は良くありません





タスクは完了しましたが、カスケードの上位の従属関数の作業結果をスローするように、中間関数b()を変更する必要がありました。 そして、5つまたは10の機能のカスケードがある場合はどうなりますか? 次に、すべての中間機能を変更する必要があります。 そして、例外がコンストラクターにある場合はどうなりますか? 松葉杖を代用しなければならないこと。



そして今、例外を使用したソリューション:

 a(); function a() { echo 'a-begin'; try { b(); echo 'a-stop'; } catch (Exception $e) { echo $e->getMessage(); } } function b() { echo 'b-begin'; c(0); echo 'b-stop'; } function c($x) { echo 'c-begin'; if ($x === 0) { throw new Exception('   '); } echo 'c-stop'; return 100 / $x; }
      
      





実行結果は同じになります。 関数b()は元の形のままで、そのままです。 これは、カスケードが長い場合に特に当てはまります。 また、$ eオブジェクトには、状況に関する追加情報が含まれる場合があります。



したがって、エラーと例外は、まったく異なる問題を解決するためのまったく異なるツールであることがわかります。

エラーは取り返しのつかない状況です。

例外-機能のカスケードを中断し、いくつかの情報を転送できます。 グローバルなreturnステートメントのようなもの。 カスケードがない場合は、ifまたはreturnを使用するだけです。



エラーは必ずしもエラーではありません



「Zend Frameworkを見てください-常に例外をスローします。 これらは最高の実践であり、同様に行う必要があります。 データベースに接続できなかった場合でも、例外をスローする必要があります。



この記事では、この誤解を払拭したいだけです。 Zendは本当に最高の実践的手法ですが、Zendのプログラマーは別のボートに乗って他のことをしています。 彼らと私との根本的な違いは、多くのプロジェクトで使用されるユニバーサルライブラリを書くことです。 そして、彼らは鐘楼から何が重大な間違いであり、何が修正可能であるかを言うことができません。



たとえば、プロジェクトに複数のMySQLサーバーがあり、そのうちの1つがクラッシュしたときにそれらを切り替えることができます。 したがって、ユニバーサルライブラリとしてのZend_Dbは例外をスローし、それをどう処理するかを自分で決定します。 例外は柔軟です-どのレベルでどのような状況をキャッチするかを決定します。 エラーメッセージを表示するか、方法がわかっている場合は状況を修正してください。 ユニバーサルライブラリを記述するときは、常にexceptionsをスローする必要があります。 これにより、ライブラリがより柔軟になります。



その結果、両方のメカニズムには独自の特性があり、最も重要なことは、独自の運命があり、これらの宛先がまったく交差していないことです。 エラー!=例外 。 パフォーマンスやエラーメッセージを改善するために例外を使用しないでください。 My_Custom_Exceptionクラスに修正ロジックを実装する必要はありません。 このクラスは空である必要があります。状況のタイプを判別し、必要なものだけをキャッチするために作成されます。 クラス名 'My_Custom_Exception'は、定数E _ ***(E_NOTICE、E_WARNING、...)の線形リストに類似したツリーのようなものです。



PHPでは、エラー処理メカニズムが長い間開発されてきましたが、これは非常に効果的です。 必要な場所でうまく使います。



All Articles