2012-04-13 11 views
4

私は現在リファクタリングしようとしているいくつかのコードを持っています。大きなセットの例外には、すべての例外の共通コードと、特定の例外タイプごとに個別に処理する必要のある特定のコードがあります。私は各catchブロックの共通部分を取り除く方法を理解しようとしています。 1つのアイデアは、このようにすることです:例外の共通部分を一緒に処理する

try { 
    /* Stuff that may fail */ 
} catch(const std::exception &) { 
    /* do common part here */ 
    try { throw; } 
    catch(const exception1 &) { 
    /* do stuff for exception1 here */ 
    } 
    catch(const exception2 &) { 
    /* do stuff for exception2 here */ 
    } 
} 

しかし、これは私に多少醜い印象を与えます。

この一般的なロジックを除外するには良い方法がありますか、実際にはこの試みを完全に避ける理由はありますか?

答えて

3

try/catchはコードだけでまばらに表示されます。問題は、多くの場合、catch句で行われたアクションは、早期返却の場合にも行われるべきであるということです。

イディオムC++では、ほとんどの作業を取り除くcatch節でクリーンアップが必要な状況を避けるためにRAIIを広範囲に使用しています。

あなたのパターンはそれほど悪くはありませんそれ自体はです。しかし、この共通のものはおそらく自動的に処理される可能性があります。

私が遭遇したすべてのコードベースで、ほんの数回だけ私はcatch句の本物の使用を見ましたが、クラッチとして使用しないでください。

3

例外の大きなセットは、関数またはメソッドに共通のコードを移動

いくつかの共通コード

を有しています。各 catchからメソッドを呼び出します。他の複製を削除するのと同じように。 try .. catchの存在は違いはありません。


編集

しかし、あなたは「例外の大集合」について本当に懸念している場合は、本当の問題は、例外の大規模なセットを持っていることかもしれません。異なる例外はなぜ異なった取り扱いを必要とするのですか?例外は実際には例外のイベントにのみ使用されていますか?

+2

これは私が現在持っているものと非常によく似ています(コードではなく、質問にあります)。しかし、これは私が各例外でこのメソッドを呼び出すことを意味し、後で誰かが例外を追加し、コールの破損を確実に忘れてしまうことを意味します。このバグは、その状態が例外的で、非常にまれにしか扱われないので、長い間気づかれないかもしれません。したがって、後の開発者にとってこれをより安全に保つための良い方法を探しています。 – LiKao

+0

"誰かが後で例外を追加して呼び出しを忘れた場合"だが、その批判はあなたが使用している*スキームに適用されます:後のプログラマーが誤ってそれを変更する可能性があります。共通コードが関数に抽象化されている場合、後のプログラマーにとって、関数がすべての 'catch 'に対して呼び出されるべきであることは非常に明確です。 – Raedwald

+0

はい、どのスキームを間違って変更することも可能です。私の質問はしばしば間違っていることがいかに簡単かです。コードを他の場所と同じように追加するだけの場合は、コードを間違えないようにしてください。あなたが例外を追加することができる前に何か特別なものを見つけなければならない場合、おそらくこれが欠けてしまうかもしれません。あるケースでは、積極的に何かを忘れることによって物事を混乱させる場合、何かを積極的に変えるだけで物を壊すことができます。 2番目のケースは通常悪いIMHOです。 – LiKao

0

私は実際には共通コードを関数に移動するだけです。

ここ

は別の考えである。一般的には

try { 
    /* Stuff that may fail */ 
} catch(const std::exception & e) { 
    /* do common part here */ 
    if (const exception1 * e1 = dynamic_cast<const exception1*>(&e) { 
    /* do stuff for exception1 here */ 
    } else if (const exception2 * e2 = dynamic_cast<const exception2*>(&e) { 
    /* do stuff for exception2 here */ 
    } else 
    throw; 
} 
+0

どちらのソリューションも、非常に優れたコーディング方法です。多くの人々は例外処理を理解していないので、単純にしておきます。あなたの「特別な」取り扱いはよく理解されず、おそらく正しく維持されないでしょう。 –