2009-11-27 11 views
5

この目標を達成する典型的な方法は次のとおりです。メソッド入力パラメータに検証制約を配置するにはどうすればよいですか?

public void myContractualMethod(final String x, final Set<String> y) { 
    if ((x == null) || (x.isEmpty())) { 
     throw new IllegalArgumentException("x cannot be null or empty"); 
    } 
    if (y == null) { 
     throw new IllegalArgumentException("y cannot be null"); 
    } 
    // Now I can actually start writing purposeful 
    // code to accomplish the goal of this method 

このソリューションは醜いと思います。あなたのメソッドは、有効な入力パラメータの契約をチェックする定型コードですみやかに満たされ、メソッドの中心を不明瞭にします。

これは私が持っているものです:

public void myContractualMethod(@NotNull @NotEmpty final String x, @NotNull final Set<String> y) { 
    // Now I have a clean method body that isn't obscured by 
    // contract checking 

これらの注釈はJSR 303/Bean Validation Specのように見えますが、私はそれらを借用しています。残念ながら、彼らはこのように動作していないようです。インスタンス変数に注釈をつけ、バリデーターを通してオブジェクトを実行することを意図しています。

many Java design-by-contract frameworksのどれが私の「好き」の例に最も近い機能を提供していますか?スローされる例外は、(IllegalArgumentExceptionsのような)実行時例外でなければならないので、カプセル化は壊れません。

答えて

5

本格的な設計による契約メカニズムをお探しの場合は、Wikipedia page for DBCに掲載されているプロジェクトの一部をご覧ください。

しかし、もっと簡単なものをお探しの場合は、checkNotNull()メソッドを提供するGoogleのコレクションのPreconditionsクラスをご覧ください。だから、あなたはあなたが投稿コードを書き換えることができます。

public void myContractualMethod(final String x, final Set<String> y) { 
    checkNotNull(x); 
    checkArgument(!x.isEmpty()); 
    checkNotNull(y); 
} 
+0

前提条件.checkArgument(!x.isEmpty())。 –

+1

ああ、いつもライブラリ作成者を手元に持っていると便利です:) –

0

これは直接あなたの質問に答えていませんが、私はあなたの問題の一部は、あなたが検証を無理していることだと思います。たとえば、あなたが最初のテストを置き換えることができます:

if (x.isEmpty()) { 
    throw new IllegalArgumentException("x cannot be empty"); 
} 

xnullある場合NullPointerExceptionをスローするには、Javaに依存しています。特定のタイプの「あなたが私に不正なパラメータで電話した」状況のためにNPEがスローされると言うためには、単に「契約」を変更する必要があります。

0

Jaredは、DBCからJavaへのサポートを追加するさまざまなフレームワークを指摘しました。
JavaDoc(または、使用しているDocumentationframework、DoxygenがDBCタグをサポートしているもの)であなたの契約を文書化するだけです。
あなたのコードをあなたの議論の多くのスローとチェックで難読化することは、本当にあなたの読者に役立つ。ドキュメントはです。

+1

問題はあなたが無視するか、またはあなたが欠けている場合、前提条件の1つです。最高でも、NPEを得るかもしれません。なぜなら、最悪の場合、それがなぜ起こったのかわからないまま、いくつかのランダムな例外が発生することになります。 –

+0

@ Jared私は同意します。しかし、通常は良い方法はありません。重い枠組みを持ち込み、すべての学習と難読化のオーバーヘッドを取るか、それに固執してください。あなたが本当にDBCを使用したいのであれば、それをネイティブにサポートする言語を使用するのが最善です。 – pmr

2

私は、Eric Burkeの技術を見てきましたが、おおよそ次のようなものです。これは、静的なインポートの優雅な使用です。コードはとてもうまく読みます。

アイデアを得るには、Contractクラスがあります。ここでは最小ですが、必要に応じて簡単に記入することができます。

package net.codetojoy; 

public class Contract { 
    public static void isNotNull(Object obj) { 
     if (obj == null) throw new IllegalArgumentException("illegal null"); 
    } 
    public static void isNotEmpty(String s) { 
     if (s.isEmpty()) throw new IllegalArgumentException("illegal empty string"); 
    } 
} 

次に、使用例を示します。

package net.codetojoy; 

import static net.codetojoy.Contract.*; 

public class Example { 
    public void foo(String str) { 
     isNotNull(str); 
     isNotEmpty(str); 
     System.out.println("this is the string: " + str); 
    } 

    public static void main(String[] args) { 
     Example ex = new Example(); 
     ex.foo(""); 
    } 
} 

注:実験、there may be a bugは周りのデフォルトのパッケージでこれを行うことに注意してくださいfoo()方法は、静的な輸入品を示しています。私は確かにそれを試して脳細胞を失った。

+1

私は、NullPointerに対してIllegalArg例外を投げることに微妙な利点があることを忘れています。前者の場合、APIの作成者は明確に契約について何かを伝えています。 (つまり、あなたがバグを扱っているのか疑問に思っています) –

0

私は、パラメータアノテーション、リフレクション、および汎用バリデータークラスを使用して、アプリ全体の機能を作成します。例えば、次のようなクラスメソッドをコーディングすることができる:

クラスメソッドは "マークアップ" さ

.. MyMethodは(@NotNull列X、@notNullorZero文字列Y){

if (Validator.ifNotContractual(getParamDetails()) { 
    raiseException.. 
    or 
    return .. 
} 

}契約条件に注釈を付けること。反射を使用して、パラメータ、その値、および注釈を自動的に検出します。それをすべて静的クラスに送って検証し、結果を知らせます。

1

Java Argument Validationという小さなパッケージがPlain Javaとして実装されています。それにはいくつかの標準チェック/検証が付属しています。また、より具体的なバリデーションが必要な場合は、いくつかのヘルパーメソッドが付属しています。複数回のバリデーションを行うには、独自のインターフェイスでArgumentValidationインターフェイスを拡張し、ArgumentValidationImplクラスから継承する実装クラスを作成します。

+0

これは、いくつかの例があります。 http://java-arg-val.sourceforge.net/usage.html (このページの2つの例、およびJava Docの3つの例(特定のページの上部にある参照) – Verhagen

0

JSR-303は完全には機能しませんが、method-level validation extensionの提案があります。今はちょうど拡張機能の提案なので、JSR-303の実装はそれを無視してもかまいません。実装を見つけることはやや難解です。私はまだHibernate Validatorがそれをサポートしているとは思わないが、agimatec-validationは実験的なサポートを持っていると私は信じている。私はこの目的のためにどちらも使用していないので、彼らはどれくらいうまく働いているのか分かりません。私は誰かがそれを与える場合、私はしかし、見つけることに興味があるだろう。

関連する問題