3

Person をデータベースに格納できる Web アプリケーションがあるとします。すべての人は一意の電子メール アドレス (またはユーザー名など) を持っている必要があります。ユーザーが既に存在する電子メール アドレスを持つユーザーを追加しようとすると、エラー メッセージが表示されたフォームが返されます (通常の検証エラーの場合と同様)。

この種のエラーは、サービス レイヤーからコントローラー、そしてビューにどのように発生するのが最も一般的でしょうか? サービス メソッドは、コントローラーがキャッチするために例外をスローする必要がありますか、それとも値または何らかの結果オブジェクトを返す必要がありますか?

最終的にサービス レイヤーを使用して Web サービスを生成したい場合、これによって処理方法が変わりますか?

ベスト プラクティスやサンプル アプリケーションへの提案やリンクをいただければ幸いです。

4

6 に答える 6

3

これを行うには、基本的に 2 つの方法があります。例外と、ビジネス ルール検証の結果を返すことです。それぞれの方法には長所と短所がありますが、基本的には次のとおりです。

例外:

  • 一度に 1 つの失敗した結果のみを返すことができます
  • 例外は簡単に実装でき、ビジネス ロジックを複雑にすることはありません。条件をチェックしてビジネス例外をスローするだけです。
  • 例外はブロック ルールに対してのみ機能します
  • 開いているトランザクションは簡単にロールバックできます

ビジネス ルールの検証:

  • 複数のビジネス ルールをチェックし、壊れたルールのリストをユーザーに返すことができます
  • 複数のルールは、メソッドからの戻り値の型を台無しにする傾向があるため、ロジックの流れを複雑にする可能性があります
  • 非ブロッキング情報ルールなど、より多くのシナリオを処理できます。

どちらのアプローチが適しているかはアプリケーションに大きく依存すると思いますので、簡単な答えはありません。長い間、私はビジネス ルールの例外をうまく使用していましたが、今では 2 番目のアプローチを活用する傾向があります。

于 2009-05-15T22:39:04.460 に答える
1

addPersonこれを処理する1つの方法は、ステータスコードを持つ操作の応答オブジェクトを作成することです。例えば:

class AddPersonResponse {
    private Person person;
    private AddPersonStatus status;
    private AddPersonFailureReason failureReason;
}

enum AddPersonStatus {
    SUCCESS, FAILURE
}

enum AddPersonFailureReason {
    DUPLICATE_EMAIL_ADDRESS,
    DUPLICATE_USER_NAME
}

ユーザーに送信するビューは、サービスによって返される応答オブジェクトにバインドして、適切なフィードバックを提供できます。

于 2009-05-15T22:10:47.693 に答える
1

例外をスローすることを選択すると思います。Exception クラスから派生したカスタム例外を作成できます。このようにして、クラスの「メッセージ」フィールドをエンドユーザー向けのメッセージとして使用しながら、ベースの「innerException」フィールドから実際の例外の詳細をログに記録することができます。このようにして、ベースの例外の説明の冗長性を維持しながら、メソッドが失敗した理由の醜い詳細をユーザーに隠すことを選択できます。

于 2009-05-15T22:17:09.443 に答える
1

この議論は古くからあり、さまざまなキャンプがあります。これについての私の見解は、明確なスタンドアロン機能を備えたバックエンド システムがある場合は、最初に API とすべてを使用してそれを開発し、次にビュー レイヤーからその API を使用する必要があるということです。この場合、レイヤリングが保証されます。1 つの例は、既に開発されたカスタム ソフトウェアに Web フロントエンドを記述していることです。

ただし、ほとんどの Web アプリケーションでは、単一の構成ソースを使用する方がはるかに簡単で簡単です。Django、RoR、JBoss Seam などはすべてこのアプローチを採用しています。それらは、すべての検証ロジックと制約が配置される一連のドメイン クラスを中心とする概念を使用します。モデル例外 (NoSuchObject など) はビュー例外 (404 Not Found) に直接マップされ、すべてフレームワークによって処理されます。このアプローチでは層がなく、主な考え方は、本当に必要になるまで層化を避けることです。Django のドキュメントは、このトピックに関する優れた情報源であり、Seam のドキュメントはより技術的ですが、より詳細でもあります。

一部のロジックを Web サービスとして公開するという決定は、完全なレイヤード ソリューションを構築するという決定を自動的に保証するものではありません。リファクタリングは簡単です。YAGNI および DRY ルールはここで説明します。

階層化は、情報をやり取りする際の問題の別の側面を実際に追加します。問題にうまく適合しない限り、使用しないでください。

于 2009-05-15T22:17:44.200 に答える
1

私は「検証エラーは例外である」というパターンの大ファンではないと言わざるを得ません。

私のモデルの Save() メソッドは、壊れたルールのリスト (または空のリスト) を作成して返すだけです。その後、ControllerBase (またはサービス層) の仕事は、それらの壊れたルールを適切に処理することです。

私の ControllerBase の場合、AddModelError を介して MVC 検証ハンドラーに 1 つずつ追加します。サービス層では、JSON の結果に「isValid」フラグを追加するようなものになります。

于 2009-05-15T22:28:09.820 に答える
0

Spring MVC で使用するアプローチは、Validator クラス内ですべての検証を実行することです。そのため、validate メソッド内からサービスのメソッドを呼び出して、電子メール アドレスが既に使用されているかどうかを確認します。重複している場合は、そのバインディングのエラーを Errors オブジェクトに追加して、フォームに表示します。Person オブジェクトが有効であれば、サービスに追加されたときに期待値がスローされることを心配する必要はありません。

于 2009-05-15T23:02:54.700 に答える