6

try...catch私は自分のJSクラスのメソッドの中に入れていました:

var MyConstructor = function() {
    this.init = function() {
        try {
            // the method code...
        } catch(error) {
            // the error manager log actions
        }
    };
    // other methods, with the same try/catch usage
};

このようにして、コード インターフェイスを比較的シンプルに保つことで、コード内のエラーはすべてキャッチされ、ログに記録/管理されると考えました。

var myInstance = new MyConstructor();

代わりに、スクリプトごとに 1 つのグローバル catch ブロックで十分でしょうか? 可能性のある (または注目に値する) エラーをスローするように気をつけていると、アプリで発生するすべてのエラーを知るだけで十分なように思えます。

// no try...catch inside the classes, but only a global try...catch per script:
try {
    var myInstance = new MyConstructor();
} catch(error) {
    /*
        log in the needed environment
        (e.g. client-side, via console, or to the server...)
    */
}

Stackoverflow のスレッドと、JavaScript エラー管理に関するオンラインの注目すべきリソースを検索して読みました。
このフェーズでは、エラーを管理してユーザー インターフェイスの適切な動作を実現するよりも、すべてのエラーを見つける最善の方法を見つけることに関心があります。
それは正しいアプローチではありませんか?私はどんな提案にもオープンです。

4

2 に答える 2

2

経験則として、「誰が問題を論理的に処理すべきか」を自問する必要があります。それに固執します。

重要なことは、コードを書くときは、実際にはコードの断片と部分がどのように相互作用するかを記述したコントラクトを書くということです。たとえば、 MyConstructor インスタンスを作成すると、なぜ失敗するのでしょうか? それが生成されるとき、どのような約束がなされますか? 最も重要なことは、誰が失敗に対処する必要があるかということです。

いくつかの例

Carたとえば、クラスがあり、のインスタンスがCarメソッドを持っているとしましょうdrive(x)

あなたが右drive(x)Car移動場所を呼び出すと。x

drive(x)たとえば、Carがすでに画面の端にある場合、またはCar燃料がない場合、アクションは失敗する可能性があります。

drive「車は x 桁右に移動する」と定義しました。これは、車がドライブ アクションを完了できることを期待しており、完了できないことは論理的に例外であることを意味します。この場合、例外を処理するのはドライブの呼び出し元であり、車自体ではないことは明らかです。これは、車が運転している環境を知る必要がないためです。さらに良いことに、電話をかけた人は、車を端から離れたり、燃料なしで運転しようとしたりしないでください。

別のケースでは

同じ例Environmentで、車を含むクラスがあり、moveCars()内部に含まれるロジックに従って環境内のすべての車を移動するメソッドがあるとします。Environmentすべての移動ロジックを含むことを期待するプログラムによって使用されます。moveCars()車が衝突しないことを保証するアルゴリズムを使用しています。

メソッドで考えていなかったエッジケースmoveCars()、または何らかの仮定のために発生しないと想定されているエッジケースがある可能性がありますが、環境へのユーザーは、例外が発生したときに処理する必要があることを意味するすべての移動ロジックが含まれていることを期待しています。それ自体で。

それで、一般的な戦略は何ですか?

コードを実行しているコンポーネントの責任に基づいて、例外を処理する必要があります。

于 2013-01-14T11:12:49.960 に答える
1

この質問は、実際には JavaScript に限定されません。例外キャッチの適切な粒度は、例外を持つ可能性のあるモジュールと関数の適切な粒度に依存します。適切に設計されたモジュールまたは関数は、適切に定義されたコントラクト ( DbC ) にバインドする必要があります。コントラクトが明示的に確立されている限り、例外処理の問題ははるかに簡単になります。

契約に関する 3 つの重要な質問は次のとおりです。 契約は何を期待しているか。契約保証とは何ですか?契約は何を維持しますか?たとえば、関数が をdivide(a, b)返すとしますa / bbこの関数は、それが非ゼロ (前提条件) であることを想定しています。b がたまたまゼロの場合、この関数は例外をキャッチする代わりに例外をスローする必要があります。契約の一部である引数を渡すことの有効性を保証するのはcallerの責任だからです。それ以外は、関数で発生する可能性のある他のすべてのエラーは内部でキャッチする必要があります。それはそれ自体の責任だからです。契約の他の部分として、dividedivideb 掛けた値(商) を返すことを約束します (これはpostconditionaと呼ばれます)。

例外処理は複雑になる場合があります。関数 (またはモジュール) は、その責任範囲内であれば例外をキャッチすることを選択するか、それが義務を超えている場合はキャッチしないことを選択するか、最初に例外をキャッチして処理し、例外をラップした後に呼び出し元に再スローすることを選択できます。呼び出し元層の例外として。

要約すると、例外処理はスタンドアロンの問題ではなく、システム全体の設計の一部です。設計者が複雑なシステムを比較的単純なモジュールに合理的に分割し、それぞれが優れた抽象化/インターフェイスと明確に定義された契約/責任を持っている場合、例外を処理する方法と場所は一目瞭然です。

于 2013-01-14T12:09:25.710 に答える