0

私はあなたのフィードバックを聞くことに興味があります。最近、次の方法で実装されたJavaコードをいくつか見ました。

Object1 SomeMethod(String key) {
    Object1 object1 = null;
    List<Object1> objectList = getAllRecordsWithKeyFromDatabase(key);
    if (!objectList.isEmpty()) {
        object1 = objectList.get(0);
    }
    return object1;
}

void AnotherMethod() {
    ...
    Object1 object1 = SomeMethod(key);
    if (object1 == null) {
        // throw exception
    }
    // continue working
}

コンテキストなしでnullが返されるときはいつでも、私は常に心配しています。むしろ、SomeMethodからの応答をより明確にし、リファクタリングを検討していました。SomeMethodから例外をスローすると、これを行う方法が提供される可能性があります。それは状況に応じて発生し、障害が発生した時点で発生します。

nullが常に「見つからない」と等しいと仮定する代わりに、SomeMethodがAnotherMethodに「データベースに何も見つかりませんでした」と通知できる別の方法があるかどうか疑問に思っています。NullObjectを使用できると思いましたが、データが見つからなかった場合に、AnotherMethodが「作業を継続する」ことを回避する方法がわかりません。

コードをどのようにリファクタリングしますか?

4

3 に答える 3

2

SomeMethod場合によってはnullを返す可能性が あることを明確に文書化することを除いて、問題はありません。

ただし、nullを見つけることが明らかに例外的なケースである場合は、例外をスローすることが正しいアプローチです。チェックされた例外を宣言するように変更AnotherMethodすると、そのメソッドのユーザーにとって意図がはるかに明確になります。このようなもの:

void AnotherMethod() throws SomethingBadHappenedException {
  //snip
}
于 2011-04-21T17:50:59.450 に答える
2

Nullオブジェクトはすべてを終わらせるわけではありません。場合によっては適切ですが(Collections.emptyXXX()はこの良い例です)、場合によっては何かと何も区別する必要があります。何も返さないことが有効な状態である場合は、nullを返す必要があります。

例外は、例外的な場合、つまり通常の状況では発生しないはずの場合です。例外のキャッチと処理は、nullのチェックよりもはるかに困難です。

于 2011-04-21T17:52:48.080 に答える
0

私はかつて、クエリ結果が非常に自然にコレクションであるプロジェクトに取り組んでいました。ただし、コレクションを空にする必要がある特殊なケースがありました。コレクションに要素が1つだけ含まれている必要があるその他の場合。

これらのクエリは、データベースからの障害が発生することがあるオブジェクトに対して実行されていました。

最終的に収束したアプローチは、結果を(ArrayListなどではなく)独自の型にラップして返すことでした。説明する:

public interface Results<T> implements Iterable<T> {
  Collection<T> all();
  Iterator<T> iterator();
  /**
   * @return one value from the result, or null if the result is empty.
   */
  T ifAny();

  /**
   * @return one value from the result.
   */
  T one() throws EmptyResultException;

  /**
   * @return if the result is empty, returns null, 
   *         if the result has one value, returns the value,
   *         if the result has more than one value, throws.
   */
  T unique() throws MultiValueResultException;

  /**
   * @return the value if the result has exactly one; throws otherwise
   */
  T exact() throws NoExactResultException;
}

セマンティクスが重要な場合は、同様のアプローチを使用できます。

public final class Result<T> {
  private static final Object NON = new Object();

  private final Object _value;

  public Result(T value) {
    if (value == null) {
      throw ...
    }
    _value = value;
  }

  public T get() {
    return (_value == NON) ? null : (T) _value;
  }

  public T use() {
    if (_value == NON) {
      throw ...
    }
    return (T) _value;
  }
}

Scalaイディオムは、同様の効果を出すためにOptionを使用することに注意してください。そのサイドトピックに関する多くのリンクの1つは次のとおりです:http://www.codecommit.com/blog/scala/the-option-pattern

于 2011-04-21T18:15:03.653 に答える