0

これはEffective Javaからの引用です。

「可能であれば、下位層からの例外に対処する最善の方法は、下位層のメソッドが成功することを保証することによって、例外を回避することです。下位層に渡す前に上位レベルのメソッドのパラメーターの有効性を確認することで、これを実行できる場合があります。レイヤー。」

ハンドラーから下位レベルに伝搬される「AccessControlContext actx」というオブジェクトを考えてみましょう。「actx != null」という高レベルのチェックを行うことはできますが、低レベルでもう一度行う必要がありますか?

疑似コードの例:

class RestServlet {
   void verify Servlet(AccessControlContext actx) {
        // check made at higher level according to effective java
        if (actx == null) { throw exception; }  
        // do something
        Verify.checkAccessControl(actx); // calling lower leve
        // do something
    }
}

class Verify {
   static checkAccessControl(actx) {
        // DO I NEED NULL POINTER CHECK HERE AGAIN ?
   }
} 

質問はコメント内にネストされていますが、詳細に繰り返します。下位レベルでの冗長チェックにより、防御コーディングが保証されますが、冗長です。null を受け入れないことは Javadoc で詳しく説明されているかもしれませんが、それではバグのないコードを使用するという目的は解決されません。例外チェックを重複排除する必要がありますか?

注: これはランダムな例です。私の質問は、この例に固有のものではありません。例外をどれだけ複製するかを理解しようとする、より広範な質問です。

4

2 に答える 2

1

パラメータの検証に関しては、私の意見では、頻繁に行うことはできません。私が慣れ親しんでいる方法では、パラメーターはコードのすべてのレイヤーで検証されます。メソッドが null 値を処理できない場合 (たとえば、nullpointer につながる)、渡されたパラメーターが null でないことを確認するのはメソッド自体の責任である必要があります。パラメーターの値が正しくないと、レイヤーのさらに下にあるメソッドで同じことが起こり、例外が発生します。

私の見方では、不適切なパラメーターが例外を引き起こす場合、それが高レベルでのパラメーター検証からスローされた例外であろうと低レベルでのパラメーター検証からスローされた例外であろうと問題ではありません。検証がまったく行われなかった場合に発生する例外 (または、さらに悪いことに、例外がなく、誤った実行が発生した場合)。

各メソッドに入力の検証を任せることで、それが単なるパススルー メソッドであっても、既存のメソッドを呼び出す新しいメソッドが不正なパラメーターを渡さないようにすることができます。呼び出されているメソッドが高レベルまたは低レベルのメソッドであるかどうかに関係なく、例外です。

したがって、あなたの例では、両方の方法で入力を検証し、付随するテストで検証が正常に動作することを確認します。入力の検証もワンライナーと同じくらい簡単です。Apache Commons lang の Validate クラスを確認してください: http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons /lang/Validate.html

例えば:

import org.apache.commons.lang.Validate;
import org.apache.commons.lang.StringUtils;

public class Something {
   public void doSomething(final Integer someInt, final String someString) {
       Validate.notNull(someInt, "Can't proceed when someInt is null!");
       Validate.isTrue(!StringUtils.isEmpty(someString, "Can't proceed when someString is null or empty!");
       //do stuff
   }
}

検証が失敗した場合、IllegalArgumentException2 番目のパラメーターとして定義されたメッセージを持つ がスローされます。テストは次のようになります。

public class SomethingTest {

    private Something something;

    @Rule
    public ExpectedException expectedException = ExpectedException.none();

    @Before
    public void setup() {        
        something = new Something();
    }

    @Test
    public void doSomethingShouldFailIfSomeIntIsNull() {
        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage("someInt is null");

        something.doSomething(null, "hello");
   }

   @Test
   public void doSomethingShouldFailIfSomeStringIsEmpty() {
        expectedException.expect(IllegalArgumentException.class);
        expectedException.expectMessage("someString is null or empty");

        something.doSomething(123, "");
   }

   //more tests..
}
于 2013-08-15T20:59:32.757 に答える
0

このアプローチに満足できるかどうかはわかりませんがcheckAccessControl、多くの場所から呼び出された場合はどうなりますか? 各呼び出し元が null チェックを行うことに依存する必要があります。これは安全な方法ではありません。null チェックをcheckAccessControlメソッドに入れ、null が検出された場合はおそらく IllegalArgumentException をスローします。

したがって、私の広範なアプローチは、メソッドが提示される特定の値に依存している場合 (たとえば、パラメーターを null にすることはできません)、それを検証するのはメソッドの責任にすることです。

もちろん、(たとえば javadocs を介して) 呼び出し元に引数を検証するように依頼することはできますが、それを強制することはできません。

于 2013-08-15T20:54:23.273 に答える