2012-03-26 6 views
0

オブジェクトを返さなければならないメソッド(たとえばデータベースレイヤー)があり、要求されたオブジェクトに関する情報を入力として受け取ったとします。方法設計の決定;いつ例外をスローするのですか?

通常の場合、メソッドはオブジェクトを返す必要があります。しかし、メソッドの前提条件が呼び出し元によって満たされない場合はどうなりますか。私は(メソッドのコードライター)呼び出し元にどのように通知する必要がありますか?

は、例えば、私がDBからユーザーに関する情報を返す必要がありますケースを取る、と私は、入力として、ユーザ名とパスワードを取ります。通常の場合、私はUserオブジェクトを返すべきです。しかし、ユーザー名とパスワードがヌルで、パスワードが一致しない場合、パスワードが短すぎる場合はどうすればよいですか? 通常は例外がスローされましたが、ここには - When to throw an exception?というのが悪い考えです。 UserにerrorDetailフィールドを設定するか、checkInputDataメソッドまたはgetErrorStatusメソッドを作成する必要があります...

+0

メソッドの契約に合致しないパラメータなど、例外的な(予期しない)何かが発生したときに例外(...ドラムロール...)をスローします。 –

+0

DBから既存のユーザーを取得することは、契約で指定することはできません。この情報をメソッドの呼び出し側に返す必要がありますか? – m3th0dman

答えて

1

この場合、例外をスローするのは完全に妥当と聞こえます。この方法は、1つのことと1つのことを実行するだけで、単にデータベースからユーザーレコードを取得しようとしています。前提条件がうまくいかない場合は、諦めてください。データベースのエラーが発生した場合は、あきらめてください。ユーザーが見つからない場合は、放棄してください。呼び出しコードがその結果を処理するようにします。

例外は、メソッドに対して完全に許容される終了パスです。

前提条件の場合、それを修正するのは方法の責任ではありません。これは呼び出し側コードの責任です。だから、ArgumentExceptionを何らかの形で投げ、呼び出しコードがそれに対処するようにしてください。データベースエラーの場合は

、どちらかそれをキャッチし、それに応じて処理するアプリケーションのためのカスタム例外(InfrastructureFailed例外のようなものを)投げます。基本的に、アプリケーションには技術的な問題があることをユーザーに伝える必要があり、後でもう一度試してください。

ユーザーが見つからない場合は、ログインに失敗したように見えます。 SecurityExceptionの何らかのものを投げ、呼び出しが失敗したことをユーザーに通知して呼び出し元のアプリケーションに処理させます。 (具体的な例はありません。たとえば、ユーザー名は問題ないがパスワードは悪いとユーザーに伝えないでください。悪意のあるユーザーには、必要以上に多くの情報が与えられます。 more)

パスワードが短すぎる場合もあります。私は、それがこの時点までに検証されるべきものだと思います。この場合、メソッドの入力チェックの対象となります。したがって、前提条件は失敗し、メソッドはデータベースに到達しようとすることさえありません。しかし、 "パスワードが短すぎる"とは、ログインプロンプトでユーザーに知らせるのは良いエラーではないでしょう。むしろ、それは彼らがを作成しようとするときのためにパスワードを作成するためです。

あなたがしてはいけないことは、nullまたは空のユーザーオブジェクトまたはそのようなものです。これは、エラーがあるかどうかをチェックするために、呼び出しコードにonusを置きます。例外は、呼び出しコードにエラーを通知するための完全に有効な方法です。返される「マジックオブジェクト」は、コード内の他の「マジックストリング」とまったく同じですが、メソッドから漏れて他のコードに流入するため、悪化します。

これはもちろん、必ずしも完全なルールではありません。それはアプリケーションの構造に依存します。たとえば、これがWebサービスまたは他の種類の要求/応答システムである場合、障害を示す標準的な応答オブジェクトが必要な場合があります。それは、しかし、メソッドの周りにいくつかのアプリケーションのコンテキストを想定しています。その場合は、おそらくで、は複数の方法を扱っているはずです。内部のメソッド(ドメインロジックメソッド)は例外をスローし、外側のもの(アプリケーションのUX対応メソッド)は例外をキャッチし、UIに対して適切な非null応答を作成します。

どのようにを処理するかは、ですが、例外はアプリケーションの論理構造に依存します。しかし、を投げてをキャッチすると、キャッチは例外です(「キャッチ」は意味的に「ハンドリング」と同じではありません)。

+0

精巧な答えをありがとう。私はこれについて別の質問を開く必要があるかどうかわかりません:CRUD操作をしなければならないとし、あなたが(例外を除いて)あなたが言及したようにそれを行う読み取り操作。理論的に無効にすべき他の3つの操作はどうでしょうか?例外をスローして一貫性を持たせるか、エラーの可能性に関する情報(またはOKステータス)を保持するオブジェクトを返すべきですか? – m3th0dman

+0

@ m3th0dman:あなたが何を意味するのか分かりません。単一のトランザクションでこれらの操作をすべて実行していますか?そうであれば、部分的に完了した結果(未知の状態に残す)がないようにエラーがあれば、トランザクションを中止する必要があります。また、Unit Of Workパターンを調べることもできます。 – David

+0

autoCommitフラグが真であり、各操作が単一のトランザクションで実行されると仮定します。 – m3th0dman

0

何らかのセンチネル値を返すのは意味がありますか?もしそうなら、それを使うことを検討してください。それ以外の場合は、例外をスローしないでください。

+0

センチネル値を返すのは意味がありません。例外を投げることは私がやることですが、ユーザーを返すために無効なパスワードが与えられた場合に例外を投げることは悪い考えです。 – m3th0dman

+0

@ m3th0dmanあなたが読むすべてを信じてはいけません。 – Marcin

0

ユーザ(エラーの場合はnull)、成功フラグ(エラーの場合はfalse)、検証メッセージとしての文字列のリストの両方を含むオブジェクトを返します(エラーの場合はリストなぜそれが失敗したのか)。それが本当にユーザーオブジェクトのプロパティではありませんので、ユーザーオブジェクトにErrorDetailはフィールドを追加する

は意味がありません。これはメソッドからのこの戻りデータの一部です。このパスは、特定のメソッドでのみ使用されるmuddlesプロパティを持つオブジェクトにつながります。

+0

したがって、フィールドとしてユーザーを保持するラッパークラス、および最終的なエラーに関するその他の情報を作成しますか?あなたが強く型付けされた言語を持っていて、異なる型の要素の配列を返すのに適していないとします。 – m3th0dman

+0

ええと...私は、このメソッドから返されるデータを表すラッパークラスを作成します。ユーザーオブジェクト、成功フラグ、およびメッセージ文字列です。どの言語で作業していますか?私はそれのようなものをサポートしない言語で働いたことはありません。 – Trent

+0

例外をスローするのではなく、このアプローチの利点の1つは、複数のメッセージをユーザーに返すことができることです。 (つまり、郵便番号が無効で、ユーザー名は既に取得済みです) – Trent

関連する問題