10

ユーティリティにユーザーIDを与え、そのユーザーにメールを送信するコードがあります。

emailUtil.sendEmail(userId, "foo");

public void sendEmail(String userId, String message) throws MailException {
    /* ... logic that could throw a MailException */
}

MailExceptionメールアドレスの問題、メールテンプレートの問題など、さまざまな理由でスローされる可能性があります。

私の質問はこれです:これらの例外のすべてに対して新しい例外タイプを作成してから個別に処理しますか、それとも1つのMailExceptionを作成してから例外に何か(説明テキストではなくコンピューターで読み取り可能なもの)を格納しますか?実際に起こったことに基づいて、さまざまなことを行います。

編集:明確にするために、例外はログなどではなく、コードがログにどのように反応するかに関係しています。メールの例を続けるために、メールを送信するときに、メールアドレスがないために失敗したり、有効なメールアドレスがないために失敗したり、失敗したりする可能性があるとします。

私のコードは、これらの問題のそれぞれに対して異なる反応を示したいと思います(主に、クライアントに返されるメッセージを変更しますが、実際のロジックも変更します)。

これらの問題のそれぞれに例外を実装するか、コードに問題の種類を区別させる内部的なもの(列挙型)を持つ1つの包括的な例外を用意するのが最善でしょうか。

4

11 に答える 11

10

私のコードでは、ほとんどの例外がUIレイヤーに浸透し、ユーザーへのメッセージを表示する(そしてログに書き込む)例外ハンドラーによってキャッチされることがわかりました。結局のところ、これは予期しない例外です。

時々、私は特定の例外をキャッチしたいです(あなたがしたいと思うように)。ただし、これはややまれであり、例外を使用してロジックを制御していることを示していることに気付くでしょう。これは非効率的(低速)であり、しばしば眉をひそめます。

したがって、この例を使用して、電子メールサーバーが構成されていないときに特別なロジックを実行する場合は、次のようなメソッドをemailUtilオブジェクトに追加することをお勧めします。

public bool isEmailConfigured()

...特定の例外を探す代わりに、最初にそれを呼び出します。

例外が発生した場合、それは実際には状況が完全に予期せず、コードがそれを処理できないことを意味します-したがって、あなたができる最善のことはそれをユーザーに報告する(またはログに書き込むか再起動する)ことです

例外階層とエラーコード付き例外の比較については、通常、後者を行います。まったく新しいクラスではなく、新しいエラー定数を定義する必要がある場合は、新しい例外を追加する方が簡単です。ただし、プロジェクト全体で一貫性を保つように努める限り、それはそれほど重要ではありません。

于 2008-08-22T03:07:02.260 に答える
8

私は通常、一般的な例外から始めて、必要に応じてそれをサブクラス化します。必要に応じて、一般的な例外(およびすべてのサブクラス化された例外)を常にキャッチできますが、特定の例外もキャッチできます。

Java-APIの例はIOExceptionで、FileNotFoundExceptionやEOFException(およびその他多数)などのサブクラスがあります。

このようにして、両方の利点を得ることができます。次のようなスロー句はありません。

throws SpecificException1, SpecificException2, SpecificException3 ...

一般

throws GeneralException

十分です。ただし、特別な状況に対して特別な反応を示したい場合は、いつでも特定の例外をキャッチできます。

于 2008-09-26T09:55:04.287 に答える
2

返された例外に基づいて何をすべきかをCODEに決定させる必要がある場合は、共通の基本型をサブクラス化する適切な名前の例外を作成する必要があることがわかりました。渡されたメッセージは「人間の目のみ」と見なされるべきであり、決定を下すには脆弱すぎます。コンパイラに作業を任せてください!

チェックされた例外を認識しないメカニズムを介してこれを上位層に渡す必要がある場合は、RuntimeException(MailDomainException)の適切な名前付きサブクラスでラップできます。これは、上位に追いつくことができ、元の原因が処理されます。

于 2009-01-11T19:28:08.840 に答える
2

@ Chris.Lively

あなたはあなたがあなたの例外で、あるいは「ステータスコード」でさえメッセージを渡すことができることを知っています。ここで車輪の再発明をしています。

于 2008-08-22T04:46:00.120 に答える
1

例外を使用する代わりに、実行に問題がある可能性のあるメソッドからステータスオブジェクトのリストを返す傾向があります。ステータスオブジェクトには、重大度の列挙型(情報、警告、エラーなど)が含まれ、「電子メールアドレス」などのステータスオブジェクト名と「不適切な形式の電子メールアドレス」などのユーザーが読み取り可能なメッセージが含まれます。

次に、呼び出し元のコードは、UIまでフィルタリングするものと、それ自体を処理するものを決定します。

個人的には、通常のコードソリューションを実装できない場合は例外だと思います。パフォーマンスの低下と処理の制限は、私には少し多すぎます。

ステータスオブジェクトのリストを使用するもう1つの理由は、複数のエラー(検証中など)の識別がはるかに簡単になることです。結局のところ、先に進む前に処理する必要がある例外を1つだけスローできます。

不正な形式の宛先アドレスとブロックしている言語を含む電子メールを送信するユーザーを想像してみてください。不正な形式の電子メール例外をスローし、それを修正して再送信した後、不正な言語の例外をスローしますか?ユーザーエクスペリエンスの観点からは、それらすべてを一度に処理するのがより良い方法です。

更新:回答を組み合わせる

@ジョナサン:私のポイントは、アクションを評価でき、この場合はメールを送信して、複数の失敗理由を送り返すことができるということでした。たとえば、「不正なメールアドレス」、「空白のメッセージタイトル」などです。

例外として、1つの問題を浸透させてから、ユーザーに再送信を求め、その時点で2番目の問題を見つけてもらうことに制限されます。これは本当に悪いUIデザインです。

車輪の再発明..おそらく。ただし、ほとんどのアプリケーションは、ユーザーに可能な限り最高の情報を提供するために、トランザクション全体を分析する必要があります。コンパイラが最初のエラーで停止した場合を想像してみてください。次に、エラーを修正し、コンパイルをもう一度押して、別のエラーで再び停止するようにします。お尻の痛み。私にとって、それはまさに例外をスローすることの問題であり、したがって私が別のメカニズムを使用すると言った理由です。

于 2008-08-22T04:35:53.297 に答える
1

それはあなたのアプリケーションが何をしているかに依存します。次のような場合に個別の例外をスローすることをお勧めします

  • アプリケーションは高可用性です
  • 電子メールの送信は特に重要です
  • アプリケーションの範囲は小さく、電子メールの送信はその大部分を占めています
  • アプリケーションはリモートのサイトにデプロイされ、デバッグ用のログのみを取得します
  • mailExceptionにカプセル化された例外の一部のサブセットから回復できますが、他のサブセットからは回復できません

ほとんどの場合、例外のテキストをログに記録するだけで、すでにかなり詳細な例外を詳細化するために時間を無駄にしないでください。

于 2008-08-22T03:00:04.850 に答える
1

上記を組み合わせていただくことで、より効果が上がると思います。

問題に応じて、さまざまな例外をスローできます。例: メールアドレスがありません = ArgumentException.

ただし、UI レイヤーでは、例外の種類と、必要に応じてメッセージを確認し、適切なメッセージをユーザーに表示できます。個人的には、特定の種類の例外 (私のアプリでは UserException) がスローされた場合にのみ、ユーザーに情報メッセージを表示する傾向があります。もちろん、正規表現で簡単にチェックできる不正な形式の電子メールのフィルターとしてではなく、非常にありそうもないシナリオによって例外が生成されていることを確認するために、可能な限りユーザー入力をスクラブして検証する必要があります。

また、ユーザー入力から例外をキャッチすることによるパフォーマンスへの影響についても心配しません。例外によるパフォーマンスの問題が発生するのは、例外がスローされてループなどに巻き込まれたときだけです。

于 2008-08-26T02:03:14.143 に答える
0

コードの実行を区別して例外を確認することはできますが、「catchexceptionType階層モード」または「if(...)else...例外コードモード」のどちらで実行してもかまいません。

しかし、ライブラリのように他の人が使用するソフトウェアを開発している場合は、独自の例外タイプを作成して、ソフトウェアが通常の例外以外の例外をスローする可能性があることを他の人に通知すると便利だと思います。それらを解決します。

ライブラリを使用し、そのメソッドが単に「例外」を起動するとき、私はいつも疑問に思います:この例外の原因は何ですか?、私のプログラムはどのように反応する必要がありますか? javadocではないか、例外が説明されていません。WellChossenExceptionTypeNameを使用すると、オーバーヘッドの魔女が多すぎるのを避けることができます。

于 2008-08-22T15:13:56.227 に答える
0

オブジェクト指向の方法ではありませんが、私は例外の種類が少ない傾向にあります。代わりに、例外を分類するカスタム例外に列挙型を配置します。ほとんどの場合、派生した Exception 型でオーバーライドまたはカスタマイズできるいくつかのメンバーを保持するカスタム ベース Exception があります。

数か月前、例外を国際化する方法についてのアイデアについてブログを書きました。上記のアイデアの一部が含まれています。

于 2008-08-22T05:42:56.410 に答える
0

例外をキャッチするコードが例外を区別する必要があるかどうか、または例外を使用してエラー ページに失敗するだけかどうかによって異なります。NullReference 例外とカスタム MailException をコール スタックの上位で区別する必要がある場合は、時間をかけてそれを記述します。しかし、ほとんどの場合、プログラマーは単に例外をキャッチオールとして使用して、Web ページにエラーをスローします。この場合、新しい例外を書くのに労力を浪費しているだけです。

于 2008-08-26T01:57:30.990 に答える
-1

私はただ通り過ぎるだろう

throw new exception("WhatCausedIt")

例外を処理したい場合は、「WhatCausedIt」の代わりにコードを渡し、switch ステートメントでさまざまな回答に反応することができます。

于 2008-08-22T05:48:25.447 に答える