6

私は、guavaライブラリがnullをチェックするための単純なワンライナーをどのように許可するかを本当に気に入っています。

public void methodWithNullCheck(String couldBeNull) {
    String definitelyNotNull = checkNotNull(couldBeNull);
    //...
}

悲しいことに、単純な引数チェックには、少なくとも2行のコードが必要です。

public void methodWithArgCheck(String couldBeEmpty) {
    checkArgument(!couldBeEmpty.isEmpty());
    String definitelyNotEmpty = couldBeEmpty;
    //...
}

ただし、引数のチェックを実行し、チェックが成功した場合に値を返すメソッドを追加することは可能です。以下は、チェックの例とその実装方法です。

public void methodWithEnhancedArgCheck(String couldBeEmpty) {
    String definitelyNotEmpty = EnhancedPreconditions.checkArgument(couldBeEmpty, !couldBeEmpty.isEmpty());
    //...
}

static class EnhancedPreconditions {
    public static <T> T checkArgument(T reference, boolean expression) {
        if (!expression) {
            throw new IllegalArgumentException();
        }

        return reference;
    }
}

私はちょうどそれが設計によるものであり、そのための機能要求を出す価値があるかどうか疑問に思っていました。

編集:@Nizet、ええ、メソッドのチェックインは不器用かもしれません。ただし、コンストラクターでnullをチェックすることは非常に見栄えがよく、NPEのデバッグに費やす時間を大幅に節約できます。

public class SomeClassWithDependency {

    private final SomeDependency someDependency;

    public SomeClassWithDependency(SomeDependency someDependency) {
        this.someDependency = checkNotNull(someDependency);
    }

    //...

編集:私は副作用と一貫性の推論について彼に同意するので、ニゼットの答えを受け入れます。また、Xaerxessのコメントを見ると、他の開発者の間でも混乱を引き起こしているように見えます。

4

3 に答える 3

24

引数を返す最大の理由checkNotNullは、次のようにコンストラクターで使用できるようにするためです。

public Foo(Bar bar) {
  this.bar = checkNotNull(bar);
}

checkArgumentしかし、似たようなことをしない主な理由は、とにかく引数を個別に渡す必要があることです。特に、より複雑な前提条件チェックでは、それだけの価値はないようです。独自の行。何かワンライナーになることができるからといって、それが読みやすさを向上させなければ、それがそうであるべきであるという意味ではありません。

于 2012-07-29T14:05:54.663 に答える
2

私が理解したことがないのはcheckNotNull()、そもそもなぜその引数を返すのかということです。

public void foo(String bar) {
    Preconditions.checkNotNull(bar);
    // here, you're sure that bar is not null. 
    // No need to use another variable or to reassign bar to the result 
    // of checkNotNull()
}

上記のように、私は個人的にの結果を無視しcheckNotNull()ます。そしてこれは、voidを返す他のチェックと物事を一致させます。

私が見る唯一の利点は、あなたがそのようなことをすることができるということです、しかし私はそれが2つの別々の行でそれをするより読みにくいと思います:

public String trim(String bar) {
    return Preconditions.checkNotNull(bar).trim();
}

つまり、APIに一貫性がないことには同意しますが、すべてのメソッドでvoidを返すことをお勧めします。メソッドには副作用があるか、何かを返す必要がありますが、一般的に両方を行うことは避けてください。ここで、このメソッドの目的は、例外をスローするという副作用をもたらすことです。

編集:

あなたの例は確かに、引数を返すことがなぜ有用であるかについてのより有効な説明です。しかし、私は、この1行でチェックして割り当てる可能性よりも、一貫性とクリーンさを優先していました。

于 2012-07-29T12:48:04.280 に答える
1

代わりに、valid4jをhamcrest-matchersで使用できます(Maven Centralではorg.valid4j:valid4jとして見つかります)

前提条件と事後条件の場合:

import static org.valid4j.Assertive.*;

this.myField = require(argument, notNullValue());
this.myInteger = require(x, greaterThan(0));
...
return ensure(result, isValid());

入力検証の場合:

import static org.valid4j.Validation.*;


validate(argument, isValid(), otherwiseThrowing(InvalidException.class));

リンク:

于 2014-11-30T23:40:05.543 に答える