1

問題:

オブジェクトが初期化されていないために失敗しているコードがあります。このバグの解決策は、検出されたときに簡単に修正できます。しかし、私を驚かせたのは、私の手の込んだ例外処理がこの例外をキャッチしなかったことです。これは、例外がログに記録または処理されず、trycatchブロックに続くコードが実行されなかったことを意味します。try ... catchブロックはトランザクションの外部にあったため、問題はありませんでした。

この特定のケースでは、例外はバッチ(RunBaseBatch)ジョブ内にありました。ジョブは、いくつかの無関係な処理タスクを処理しました。例外条件が満たされると、ジョブは終了したため、他の無関係な処理タスクは呼び出されませんでした。

Dynamics AX 2009で「オブジェクトが初期化されていません」という例外をキャッチできるかどうか誰かが知っていますか?AXで特定の例外をキャッチできない可能性があるという投稿を読みましたが、そうではないことを願っています(参照:https ://community.dynamics.com/product/ax/f/33/p/ 16352 / 23700.aspx#23700)。

コード例: 問題を再現する単純なコードを次に示します。

server static void main(Args args)
{
    Array   arr;
    ;
    info ("debug: before try...catch");
    try
    {
//        ttsbegin;       // enable/disable to test with transactions
//        arr = new Array(Types::String);     // Enabling this line will prevent the exception
          arr.exists(3);
//        ttscommit;      // enable/disable to test with transactions
    }
    catch (Exception::Internal)  // This exception handler was the Magic Sauce!!
    {
        info ("debug: catch (Exception::Internal)");
    }
    catch (Exception::Error)
    {
        info ("debug: catch (Exception::Error)");
    }
    catch
    {
        info ("debug: catch");
    }
    info ("debug: after try...catch");
}

UPDATE 2013-01-29 この質問がもっと見られるまで、私は答えを受け入れるのを待っています。これまでの回答ありがとうございます。

私が挙げた例は単純なものでした。このタイプのバグは、既知の場合は簡単に修正できます。そして、防御的なプログラミングは常に良い考えです。

ただし、現実の世界では、バグが発生したコードは非常に複雑でした。エラーは、サブクラスのオーバーロードされたメソッドの数レベルの深さで発生しました。これは、特定のシナリオで、オーバーロードされたメソッドがスーパークラスのメンバー変数の保護された値を破損したときに発生しました。ここでバグがコードで発生しましたが、スーパークラスがメンバー変数を再度使用しようとするまでバグは現れませんでした。バグが検出され、追跡されたときに、バグは簡単に修正されました。

防御的に、はい、使用するたびにすべての保護されたメンバー変数をチェックできますが、それはパフォーマンス、コードの可読性、実用性などに影響を及ぼし始めます。そのため、言語は例外処理を提供します。

ここでの問題は、これらのタイプのバグをどのようにキャッチして、コードをより堅牢で防弾にすることができるかということです。ほとんどの開発環境(C、C ++、C#、Javaなど)では、トップレベルのtry ... catchを使用して、予期しないすべての例外をキャッチ、ログ記録、およびクリーンアップできます。したがって、コードは他の無関係なタスクで処理を続行できます。このバグが発生してもシステム全体が完全に停止することはないため、AXはある程度継続しています。ただし、AX / X ++に欠陥があると思われるため、このジョブのキャッチ後のコードは実行されていません。

「オブジェクトが初期化されていません」という例外(実際にはすべての例外)をキャッチして処理を続行するための革新的なソリューションまたは回避策が存在する場合は、それを探しています。

4

3 に答える 3

3

従来の意味でそれを「捕まえる」ことはできませんが、それが起こるのを避けることはできます。オブジェクトから何かを実行する前に、オブジェクトが存在するかどうかをテストするだけです。

if(object)
{
    // Exists; Execute statements with object here
}
else 
{
    // Doesn't exist
}

これが機能するのは、オブジェクトが初期化されていない場合、オブジェクトがnullとして変換されるためです。(Null == 0)== false

オブジェクトが初期化されると、null以外の値になります。(!Null!= 0)== true

お役に立てば幸いです。

于 2013-01-25T20:19:12.767 に答える
2

少し詳しく説明すると、リンク先の投稿に記載されているように、オブジェクトが初期化されていませんというエラーをキャッチすることはできません。ただし、制御していない変数に対して関数を実行する前に、簡単なチェックを追加することでコードを「修正」できます(たとえば、関数の引数として配列型を要求していて、関数がクラス外から呼び出されます)。

    try
    {
          if (arr)
              arr.exists(3);
    }

if(arr)ステートメントは、オブジェクトがまだインスタンス化されていない場合に処理をスキップするのに十分であり、エラーを効果的にバイパスします。ただし、これによってエラーがチェーンのさらに上にスローされることはありません。本当に必要な場合は、キャッチできる別のエラーをスローさせることができますが、それは明らかに理想的とは言えません。

この場合、RunBaseBatchクラスは変更したいものではない可能性があるため、問題のメソッドを呼び出してテストでこれらのエラーを見つける前に、問題の原因となっているオブジェクトが正しく定義されていることを確認することをお勧めします。

于 2013-01-24T13:58:26.463 に答える
2

できますが、すべきではありません。このような振る舞いは、ほぼ間違いなくコードの悪い設計であり、将来的には必然的にさらに多くの問題が発生します。

この場合、コードを防御的にする必要があります。オブジェクトを使用する前に、オブジェクトがインスタンス化されていることを確認してください。それ以外の場合は、catchコードを期待どおりの動作で使用していますが、意味がありません。

2013/02/18を編集

説明しているような複雑なシナリオでは、通常、ソリューションを完全に制御することは非常に困難です。AXでは、try..catchステートメントは非常に単純化されており、非常に広範囲の状況では実際には必要ありません(Java、C#、...が常に推奨される場合とは異なります)。

この単純化は、例外処理に時間を浪費する必要がないため、AX開発のほとんどすべての状況で役立ちます。それらを上げるだけで、InfoLogはシンプルで信頼できる方法でそれらを処理します。

大きな問題は、このコントロールが本当に必要な場合に発生します...実際にそれを強制する方法がない場合。これが本当に標準的な問題なのか、それとも製品チームがそのように機能すると考えているのかはわかりませんが、この場合は常にAXで問題が発生します。特定の問題をキャッチする必要がある場合は、例外をキャッチすることがさらに創造的になるため、例外を防ぐために非常に創造的かつ防御的である必要があります...

お役に立てれば :)

于 2013-01-28T11:01:03.230 に答える