9

次のような関数があるとしましょう。

public void saveBooking(/* some inputs */) {
    //save into database
}

データベースに保存する前に、さまざまな検証を行う必要があります。メインプログラムでできることは次のとおりです。

//do all the validations and do any necessary handling. Then...
saveBooking(/*inputs*/);

これにより、データベースに保存する前に、すべてのデータが必要なすべての検証に合格する必要があると確信しています。ただし、これは、関数saveBooking()が検証方法に密接に依存していることを意味します。電話をかけるたびにsaveBooking()、検証を呼び出すことを忘れないようにする必要があります。

または、すべての検証を関数自体の中に入れて、メソッドを呼び出すだけですべてが処理されるようにすることもできます。ただし、すべてのエラーを個別に処理するには、関数に例外をスローさせ、メインプログラムでキャッチする必要があります。次のようになります。

public void saveBooking(/* some inputs */) /* throws various exceptions */ {
    //various validations
    //save into database
}

//...and in the main program...
try{
    saveBooking(/*inputs*/);
}
catch(MyException1 e1){
    //do something
}
catch(MyException2 e2){
    //do something
}

これは、自分で複数の例外を作成する必要があることも意味します。良いことは、事前にどのような検証を行う必要があるかを心配する必要がないことです。

これらを使用すると、どれが最適なコード設計であるかわかりません。私は個人的には読みやすい最初の方法を好みますが、それはお互いに依存しすぎて、多くの場所でそれを使用する必要があるときに悪化します。ご意見をお聞かせください!

4

5 に答える 5

8

間違いなく、2番目のオプションよりも最初のオプションです。2番目は例外の乱用だと思います。例外は例外的な状況を対象としており、検証の失敗は「例外的」ではありません。

電話をかけるたびにsaveBooking()、検証を呼び出すことを忘れないようにする必要があります。

検証ロジックを別のメソッドに配置し、saveBooking()他の処理を行う前に検証メソッドを呼び出します。

public List<ValidationError> validateBooking(/* args */)
{
    // as @Jared Farrish suggests, return a list of validation errors
}

public boolean saveBooking(/* args */)
{
    List<ValidationError> errors = validateBooking(/* args */);

    if (errors.size() != 0) return false; // validation failed

    // save to the database

    return true;
}
于 2011-08-02T03:46:43.117 に答える
2

チェックは通常、関数自体の中で実行する必要があります。これにより、最初にデータを検証せずにデータを保存しようとする可能性がなくなります。関数内にこれらのチェックがないと、検証なしで保存しようとしているクライアントを見つけることができ、それが良いことになることはめったにありません。

ただし、これに例外を使用することに制限されているわけではありません。呼び出し元がチェックするために、ある種のエラーコードを返すだけです。私は通常、エラーが例外によって行われるのかリターンコードによって行われるのかを気にしませんが、これが例外の乱用であると見なす場合があります。

検証コードは、保存を行わずに独自のコードで呼び出したい場合があるため、おそらくまだ別の関数として残されています。(擬似コード)のようなもの:

def validateStuff():
    if stuff is not valid:
        return WTF
    return OK

def saveBookings():
    rc = validateStuff()
    if rc != OK:
        return rc;
    save the information
    return OK

saveBookingsI / Oエラーなどを処理するためだけに、呼び出しによって例外がキャッチされる可能性がありますが、絶対に必要というわけではありません。関数内でも例外をキャッチして、リターンコードに変換できます。

私は各関数から1つのレポート方法を好む傾向があるので、たとえば、リターンコードtry/catch チェックする必要はありません。

于 2011-08-02T03:52:39.803 に答える
1

挿入する前にすべてを検証することで、間違いなく正しいことを行っています。また、予期しない予期しないSQLExceptionを回避するために、挿入するすべてのものがデータベースの制約に適合するか、または満たすかどうかを検証する必要があります。トップへの道。

エラーの原因を説明するために、いくつかの属性を使用してカスタム例外を作成することをお勧めします。これにより、1種類の例外のキャッチについてのみ心配する必要があります。

さらに、検証をメソッド内に確実に配置するため、常に呼び出されます。

于 2011-08-02T03:48:24.977 に答える
0

3層のアプローチはかなり一般的であり、次の3つの層があります。

  • クライアントインターフェイス。これには、WebアプリケーションのJavaScript検証、またはGUIコントロールの基本的なSWT検証が含まれます。
  • ビジネスレイヤー。この層はビジネスルールを知っています。これは、通常、サーバー側の検証を配置する場所です。保存、変更などが必要なことはすべて、ビジネスレイヤーを介して行う必要があります(このようにして、常に検証を行い、データストアを気にする必要はありません)。
  • データレイヤー。このレイヤーは通常「ダム」です。保存、削除、選択など。ビジネス層がこの層に要求するものは何でも、単純にそれを行います。

これは非常に単純化されていますが、メンテナンスを容易にするために、さまざまなタイプのロジックを分離するための適切な方法を提供します。

于 2011-08-02T03:46:55.950 に答える
0

多くのコードを1か所にまとめることはお勧めできません。チェックされた例外をスローすることもお勧めできません。

于 2011-08-02T04:02:57.860 に答える