10

WCFサービスで障害をスローするタイミングとスローしないタイミングについて、同僚と話し合っています。

1つの意見は、何らかのエラーのためにサービス操作が機能しなかった場合にのみ障害をスローするというものです。そのため、何かが無効な状態になっている可能性があります。だから、いくつかの例:

  • ValidateMember(文字列名、文字列パスワード、文字列国)->検証自体を実行できなかったため、必須パラメーターが渡されない場合、エラーがスローされます。->データベースがダウンしたなどの内部エラーが発生した場合はエラーをスローします->他のすべての場合には、検証の結果を指定するステータスコントラクトを返します(MemberValidated、WrongPassword、MemberNotKnown、...)

  • GetMember(int memberId)->何かがダウンしている場合にのみ障害をスローし、他のすべての場合はメンバーを返すか、見つからない場合はnullを返します

もう1つの意見は、GetMemberがメンバーを見つけられない場合、またはValidateMemberの場合はパスワードが間違っている場合にも、フォールトをスローする必要があるというものです。

どう思いますか?

4

5 に答える 5

12

これについての私の見解...

失敗の原因は3つあります。

  1. サービスコードが例外をスローしました。たとえば、データベースエラー、コードの論理エラーなどです。これはあなたのせいです。
  2. クライアントコードは、ドキュメントに従ってサービスを適切に使用できませんでした。たとえば、必要なフラグ値が設定されていない、IDを渡すことができませんでした。これはクライアントソフトウェア開発者の責任です。
  3. エンドユーザーが画面に愚かなことを入力しました。たとえば、生年月日がない、給与がマイナスなどです。これはエンドユーザーの責任です。

実際の障害契約を障害の各原因にどのようにマッピングするかは、あなた次第です。たとえば、次のようにします。

  • 原因1と2の場合、クライアントコードが知る必要があるのは、サービスが失敗したことだけです。一意のエラーIDのみを含む非常に単純な「致命的なエラー」フォールトコントラクトを定義します。エラーの完全な詳細はサーバーに記録されます。
  • 原因3の場合、エンドユーザーは自分が何を間違えたかを正確に知る必要があります。画面に表示するクライアントコードのわかりやすいエラーメッセージのコレクションを含む「検証エラー」フォールトコントラクトを定義します。

原因3にはMicrosoftEntLibクラスを借用し、例外シールドを使用して原因1と2を宣言的に処理します。それは非常に単純なコードになります。

明確にするために:

サービス内では、次の3つの原因を処理します。

  1. 予期しない例外がサービスコードでスローされます。トップレベルでキャッチします(実際には例外シールドがキャッチしますが、原則は同じです)。FaultException<ServiceFault>詳細をログに記録してから、エラーIDのみを含むをクライアントにスローします。
  2. 入力データを検証し、意図的に例外をスローします。通常はArgumentExceptionですが、適切なタイプであれば問題ありません。一度スローされると、クライアントに同じように見せたいので、(1)とまったく同じように処理されます。
  3. 入力データを検証し、意図的に例外をスローします。今回はFaultException<ValidationFault>です。これをラップされていない状態で通過させるように例外シールドを構成しているため、クライアントではそうではFaultException<ValidationFault>ないように見えますFaultException<ServiceFault>

最終結果:

  • サービス内にキャッチブロックはまったくありません(きれいなコード)。
  • FaultException<ValidationFault>クライアントは、ユーザーにメッセージを表示したい場合にのみキャッチする必要があります。サービスの致命的なエラーは一般にクライアントの致命的なエラーも意味するため、を含む他のすべての例外タイプFaultException<ServiceFault>は、クライアントのグローバルエラーハンドラによって致命的なエラーとして処理されます。
于 2010-12-14T16:59:51.557 に答える
3

それは一般的な日常的な失敗であり、障害を投げることは間違いです。ソフトウェアは、間違ったパスワードの入力などの日常的な項目を処理するように作成する必要があります。障害処理は、プログラムの通常の設計の一部とは見なされない例外的な障害に対するものです。

たとえば、プログラムが常にデータベースにアクセスでき、データベースにアクセスできないという考えでプログラムが作成された場合、それは「修正」がソフトウェアの制限をはるかに超えている場合の問題です。フォールトをスローする必要があります。

障害処理は、プログラミング言語の構造全体でさまざまな論理フローを使用します。プログラミング問題の通常の処理を「終了」した場合にのみ使用することで、ソリューションでプログラミング言語の機能を次のように活用できるようになります。より自然に見えます。

于 2010-12-14T15:54:42.017 に答える
2

エラー処理と障害処理を分離することは良い習慣だと思います。エラーが発生した場合は、プログラムで対処する必要があります。障害処理は例外的な状況のために予約されています。2つを分離するためのガイドとして、このような場合を検討するときに、エラーは3種類(データとメッセージを処理する場合)のみであり、障害は1種類のみであることを覚えておくと便利です。エラータイプは、さまざまなタイプの検証に関連しています。

  1. メッセージの検証-メッセージの内容から、データが有効か無効かを判断できます。

    例:生年月日を意図したコンテンツ-データから、それが有効かどうかを判断できます。

  2. コンテキスト検証-システム状態と組み合わせたメッセージを参照することによってのみ、コンテンツが無効であると判断できます。

    例:会社に参加する有効な日付は、その人の生年月日よりも前です。

  3. システムに嘘をつく-後のメッセージが異常をスローしたときにのみ、メッセージがエラーであったと判断できます。

    例:保存されている有効な生年月日とその人の出生証明書の検査は、これが正しくないことを示しています。システムに対する嘘の修正には、通常、システム外での措置が必要です。たとえば、法的または懲戒処分を行う場合などです。

システムはすべてのクラスのエラーに対処する必要がありますが、3つの場合、これはアラートの発行に限定される可能性があります。

対照的に、障害(例外)の原因は1つだけです。それは、データの破損(データの切り捨てを含む)です。例:検証パラメーターは渡されません。

ここで適切なメカニズムは、障害または例外処理です。基本的に、問題を処理できるシステムの他の部分に問題を渡します(これが、未処理の障害の最終的な宛先が存在する理由です)。

于 2010-12-14T16:29:15.873 に答える
2

昔は、例外は例外的で予期しないものだけであるという規則がありました。それらを使いすぎたくない理由の1つは、それらが大量の計算能力を「消費」することでした。

ただし、例外を使用する場合は、コードの量を減らすことができます。ifelseステートメントをたくさん必要とせず、例外をバブルアップするだけです。

それはあなたのプロジェクトに依存します。最も重要なことは、プロジェクトの標準があり、誰もが同じようにそれを行うということです。

于 2010-12-14T17:46:45.097 に答える
1

私の意見では、メソッドが実行するはずのことを達成できない場合は常に例外/障害をスローする必要があります。したがって、検証ロジックは、検証を行うことができない場合を除いて(つまり、技術的な理由で)例外を発生させてはなりませんが、データが有効でないという理由だけで発生することはありません(その場合、検証コード/メッセージ、または呼び出し元がデータ)。

GetMemberのケースは、すべてセマンティックに関するものであるため、興味深いケースです。メソッドの名前は、IDを渡すことでメンバーを取得できることを示しています(たとえば、TryGetMemberメソッドと比較してください)。もちろん、IDが見つからない場合、またはデータベースが応答しない場合、メソッドは同じ例外をスローしないはずですが、このメソッドに渡された間違ったIDは、おそらくその呼び出しの前にどこかで問題が発生していることを示しています。ユーザーがインターフェース内からメンバーIDを直接入力できる場合を除きます。この場合、メソッドを呼び出す前に検証を行う必要があります。

パフォーマンスの問題についてよく耳にします。C#とtrow /catch1000例外を使用して簡単なテストを行いました。1KExeptionsの所要時間は23msです。これは、例外ごとに23µです。1秒あたり2000を超える例外を発生させる場合を除いて、パフォーマンスはもはや最初の議論ではないと思います。その場合、パフォーマンスが5%低下し、検討を開始できます。

私の謙虚な意見...

于 2010-12-14T17:07:00.883 に答える