0

例外に関する複数の情報をエンド ユーザーに提供する方法を探しています。例外を拡張する明らかな解決策は、コードのテキスト分散スループットで終わります。たとえば、

throw new MyException("Bad data", "The data you entered is incorrect", "http://www.example.com/moreinfo/baddata");

これはすぐに実行できなくなります。

次に、カタログ アプローチを検討しましたが、これは一元化されすぎており、例外がスローされるたびにあるファイルから別のファイルにジャンプする必要があります。現在、キーからより詳細な情報へのマッピングを含む静的な ErrorInfoMap クラスを使用したハイブリッド アプローチを検討しています。各クラスには、独自のエラー マッピングを含む静的セクションがあるため、上記の例外をスローするクラスを例として使用して、次のように変更します。

throw new MyException("Bad data");

クラスの一番下には次のようなものがあります。

static {
  ErrorInfoMap.put("Bad data", new ErrorInfo("The data you entered is incorrect", "http://www.example.com/moreinfo/baddata"));
  // Information for other exceptions thrown by this class goes here
}

これにより、必要に応じて例外ハンドラーが追加情報を取得できます。これはこの問題を解決する良い方法ですか、それともこれを処理するためのより良い方法はありますか?

4

3 に答える 3

0

ハイブリッド アプローチに代わる方法は、エラー マッピングを例外自体に配置することです。あなたが示した追加でMyException初期化されるときだけでなく、何を意味するかのデフォルト定義をオーバーライドまたは補足できるようにするためのコンストラクターの範囲も提供します。Bad dataErrorInfoMyExceptionBad data

于 2013-01-06T00:14:27.010 に答える
0

スーパークラスとして常に「MyException」を持ち、そのサブタイプとして特定のタイプのエラーを持つことができます。エラー メッセージに関しては、サブタイプで静的定数を使用して、さまざまなタイプのエラーを格納できます。

例えば

Exception    
    -> MyException
      -> BadDataException
      -> InvalidUserException

次のようにスローされます:

throw new BadDataException(BadDataException.DATA_TOO_LONG);
于 2013-01-06T00:18:49.003 に答える
0

「カタログアプローチ」が正確に何を意味するのかわかりませんが(参照またはより詳細な説明を提供できますか?)、提供した情報から、静的なErrorInfoMapが「あまりにも集中化され、例外がスローされるたびにあるファイルから別のファイルにジャンプすることが必要です。」

私には、何を達成する必要があるかに応じて、いくつかのオプションがあります。

  1. すべての例外に実行させたい繰り返し可能な動作をExceptionTemplate拡張して実行するルート クラスを作成します。Exceptionフォーマットされた toString() メソッドが良い例です。正確な目標によっては、次のように、例外にビルダー パターンを実装させたい場合があります。

    throw new BadDataException("Supplied data is not valid")
          .expected("a positive integer")
          .referenceUrl("http://www.example.com/moreinfo/baddata");
    
  2. 列挙型またはサブクラスが行う文字列型のソリューションは避けてください。実行時に新しい例外タイプを定義する必要がない場合 (もしそうなら、それは設計に深刻な問題があることを示す危険信号である必要があります)、例外を構築するために必要なすべての情報を含む列挙型を持っている場合:

    public class EnumException extends Exception {
        private EnumException() {} // prevent objects from being instantiated elsewhere
    
        public enum Type {
            BAD_DATA("Bad Data","Supplied data is not valid", "http://www.example.com/moreinfo/baddata"),
            MISSING_DATA("Missing Data","Required data not found", "http://www.example.com/moreinfo/missingdata");
    
            Type(String title, String genericMessage, String url) {
                // Store input
            }
    
            public EnumException exception() {
                // construct your exception
                return new EnumException();
            }
        }
    }
    

    次のようなもので呼び出すことができます:

    // note no `new` - the exception is returned by the enum
    throw EnumException.Type.BAD_DATA.exception().expected("a positive integer");
    

    これには、コンパイル時の型の安全性を確保できるという利点がありますが、さまざまな型の例外を 1 か所で柔軟に定義できます。

  3. 多くの例外を作成します。一連の例外を作成するだけで、どのような異議があるのか​​ 、まだ完全にはわかりません。「追加情報を提供する」方法を探していますが、「例外を拡張する明らかな解決策は、コードのテキスト分散スループットで終わる」と主張しています。これはあってはならないことです。Exception のすべてのサブクラスは、構築時にのみ提供できるものを除いて、すべての必要な情報を保持する必要があります。したがって、ボイラープレート/再利用可能な文字列は例外クラスに配置する必要があるため、「コード全体に分散するテキスト」は最小限にする必要があります。

    public class DocumentedException extends Exception
    {
        private String title;
        private String genericMessage;
        private String detailedMessage;
        private String url;
    
        // Generally avoid this long constructor, and define subclasses that only need detailedMessage
        public DocumentedException(String t, String g, String d, String u) {
            super(g + " - " + d); // sets the getMessage() return value to something sane
            title = t;
            genericMessage = g;
            detailedMessage = d;
            url = u;
        }
    
        public String toString() {
            return title.toUpperCase()+"\n"+
                genericMessage+"\n"+
                detailedMessage+"\n"+
                "More info on this error: "+url+"\n";
        }
    
        public static class BadData extends DocumentedException {
            public BadData(String details) {
                super("Bad Data", "Supplied data is not valid", details, "http://www.example.com/moreinfo/baddata");
            }
        }
    
        public static class MissingData extends DocumentedException {
            public MissingData(String details) {
                super("Missing Data", "Required data not found", details, "http://www.example.com/moreinfo/missingdata");
            }
        }
    }
    

    次に、次のように簡単に呼び出すことができます。

    throw new DocumentedException.BadData("Username cannot contain whitespace");
    

    もちろん、ユーザー名のエラーを定期的に警告する必要があると予想される場合は、追加のクラスを作成できます。

    public static class BadUsername extends BadData {
        public BadUsername() {
            super("Usernames can only contain letters, numbers, and underscores");
        }
    }
    

    繰り返しますが、目標は、アプリケーション全体で同じ文字列を繰り返し定義しないように、対処する必要があると予想されるすべてのケースを処理する例外の階層を明示的に定義することです。個人的には、上で使用した group-exceptions-into-inner-classes パターンが気に入っています。これにより、常に調べなければならない何百ものばかげたスタブ Java ファイルを作成することなく、エラーを非常に明確に示すことができます。すべての主要なパッケージには、そのパッケージに必要なすべての例外を定義する例外保持クラスが関連付けられている必要があります。

于 2013-01-06T18:34:53.443 に答える