2

私は 4 層システム (データベース、永続性、ビジネス、プレゼンテーション) を持っています。後の 3 つの層はすべて 1 つの JVM で実行されます。

ビジネス層とプレゼンテーション層の間でいくつかの例外処理の問題に直面しました。非常に単純化された例として、次のコードを検討してください。

public void process(String label) throws ValidationException {

    if(label == null) {
        // this is a custom exception that means that one of the arguments invalid
        throw new ValidationException("The label can not be null.");
     }

    if(label.length() != 8) {
        throw new ValidationException("The label has to be 8 letters long."); 
    }

    ... process ...
}

ここでの問題は、無効な引数がプレゼンテーションのせいなのかユーザーのせいなのか、ビジネス タイヤにはわからないことです。

  • ラベルがユーザーによって提供された場合、それはユーザーのせいであり、プレゼンテーションは検証例外のメッセージとともに「検証に失敗しました」というメッセージを表示する必要があります。
  • 一方、ラベルがユーザー向けのプレゼンテーションによって生成された場合、それはプレゼンテーションの障害 (おそらくバグ) であり、プレゼンテーションは「内部エラー」メッセージを表示する必要があります。
  • さらに、ラベルが null の場合、これは 100% プレゼンテーションの問題です。

ユーザー生成の引数とプレゼンテーション生成の引数が混在して渡されると、問題が発生します。この状況では、プレゼンテーションは例外の原因を知ることができません。ユーザーに詳細なメッセージを表示するだけです (ユーザーの過失であれば、ユーザーは原因を知ることができるため)。ただし、ユーザーに詳細なエラー メッセージを表示することは、ユーザーを混乱させるだけなので、プレゼンテーションに問題がある場合は受け入れられません。

このような状況で例外を処理するにはどうすればよいですか? 使用するパターンはありますか?

4

2 に答える 2

4

OOP の哲学から、データは自身の振る舞いを知っています。

問題を解決する方法はたくさんあります。

ここに1つのアイデアがあります:

  1. ユーザーが生成したエラーとユーザー以外が生成したエラーに対して異なる例外をスローします。ユーザーが生成したものである場合、プレゼンテーション層はそれをキャッチしてメッセージを表示します。そうでない場合、プレゼンテーション層は「内部エラー」または「申し訳ありません」などの一般的なメッセージを表示します。
  2. ビジネス層は、どれがどれであるかはわかりません。したがって、データは知る必要があります。あなたの例でlabelは、文字列にすることはできません。それはクラスになることができます。

一部のクラスですべての引数をラップする

class Label implements Validatable {
    String label;
    @Override
    public void validate() throws BaseValidationException {
         //Check conditions and throw the proper exceptions.
         //Label class should know which validations are user and 
         //Which are presentation and throw appropriate exceptions.
    }
}

すべての引数に対して個別のクラスを作成するのは面倒です。次のようなものがあります。

class Argument<E>  {
    E realArgument;
    Validator validator;
    public Argument(E value, Validator validator) {
        //implement
    }

}
interface Validator {
    public void validate() throws BaseValidationException;
}

これで、ラベル ( LabelValidator implements Validator) などの特別なバリデータと、他のものと同様の単純なバリデータを使用できるようNotNullValidatorになりました。これらは作成時に関連付けられます。

ビジネスロジックレイヤーでは、

void process(Argument<String> label) {
    if (label != null ) label.getValidator().validate();
    //continue.
}

プレゼンテーション層で

try {
    process(....)
} catch (UserException ex) (
   showMessage(ex.getMessage());
) catch (PresentationError ex) {
  log.fatal(ex.getMessage());
  showMessage("Pre-formatted internal error message");
} catch (Exception ex) { //Unknown exception
  log.fatal(ex.getMessage());
  showMessage("Pre-formatted internal error message");
}
于 2012-07-06T08:21:32.470 に答える
0

アプリケーションで生成されたラベルコードが安定化され、仕様を満たしたら、検証チェックに失敗することはありません。質問でカバーされていないユースケースがもっとあるはずです。

私が考えることができる1つの可能な解決策は次のとおりです。

ユーザー生成ラベルとアプリケーション生成ラベルをどのように区別しますか?

区別するメカニズムがない場合は、アプリで生成されたラベルに特別な文字シーケンスを追加することをお勧めします。

例えば ​​:

  • !@ _ Java
  • !@ _ Python

したがって、この「!@ _」はアプリケーションで生成されたラベルを示し、それに応じて検証関連の問題を処理するソリューションを設計できます。

また、ラベルが検証ステップに合格した場合は、いつでも「!@_」の部分を削除できます。

すべてのラベル生成は特定のコードからのみ行われることに注意してください(できれば静的ユーティリティメソッド)。

于 2012-07-06T07:23:25.607 に答える