web-dev-qa-db-ja.com

NULL引数は悪い習慣ですか?

NULL引数をメソッドに渡すのは悪い習慣ですか、言い換えれば、NULL引数を有効な引数として許可するメソッド定義があるべきですか?.

1.すべての会社のリストを取得する2.フィルターに基づいて会社のリストを取得する2つの方法が必要だとします。

以下のような2つの方法があります

    List<Company> getAllCompaniesList();
    List<Company> getCompaniesList(Company companyFilter);

または、1つの方法を使用できます

    List<Company> getCompaniesList(Company companyFilter);

ここで2番目のケースでは、引数がNULLの場合、メソッドはすべての会社のリストを返します。

実際のグッドプラクティスの質問のほかに、以下で説明する後のアプローチに関するもう1つの問題があります。

Spring AOPを実装していますが、1のような引数をチェックしたいと思っています。引数はNULLですか? 2.コレクションのサイズは0ですか?

メソッドのようにnull引数をまったく持てないシナリオがいくつかあります

    void addBranches(int companyId, List<Branch>);

このチェックは、次のようなメソッドを定義することにより、SpringAOPを使用することで非常にうまく実行できます。

@Before(argNames="args", value="execution(* *)")
void beforeCall(JoinPoint joinPoint ,Object[] args )
{ 
           foreach(Object obj in args)
           {
                 if(obj == NULL)
                 {
                     throw new Exception("Argument NULL");
                 } 
           }   
}

しかし、私が直面している問題は、メソッドリストgetCompaniesList(Company companyFilter);について前述したように、単一のメソッドの複数の機能に対してNULL引数を受け入れる必要があるメソッドのいくつかを定義したためです。したがって、すべてのメソッドにAOPを均一に適用することはできず、メソッド名の一致の式もここでは役に立ちません。

さらに情報が必要な場合、または問題が十分に説明されていない場合は、お知らせください。

私の問題を読んで、それについて考えてくれてありがとう。

20
Maddy.Shik

オーバーロードされたメソッドが多すぎる場合は問題ありません。したがって、パラメータのすべての組み合わせを使用する代わりに、それらの一部をnullにすることができます。ただし、そうする場合は、これを明示的に文書化してください。

@param foo foo description. Can be null

あなたの場合、2つのメソッドがあります。最初のメソッドはnull引数を使用して2番目のメソッドを呼び出します。 APIをより使いやすくします。

オーバーロードを停止する場所とnull許容パラメーターへの依存を開始する場所に厳密な線はありません。それは好みの問題です。ただし、パラメータが最も多いメソッドでは、一部のパラメータをnull許容にすることができるため、これも文書化してください。


また、複数のコンストラクターパラメーターを処理するための推奨される方法は、ビルダーを使用することです。したがって、代わりに:

public Foo(String bar, String baz, int fooo, double barr, String asd);

各引数がオプションの場合、次のようにすることができます。

Foo foo = new FooBuilder().setBar(bar).setFooo(fooo).build();
18
Bozho

私は非常に単純なルールを使用します:

パブリックメソッドの引数または戻り値としてnullを許可しないでください。

オプション および 前提条件 またはAOPを使用してそのルールを適用します。この決定により、NPEや奇妙な動作の後、バグ修正にかかる時間を大幅に節約できました。

16
henning77

これは一般的な方法ですが、コードを明確にする方法がいくつかあります。ヌルチェックを回避したり、別の場所に移動したりすることもあります。 nullオブジェクトパターンを調べてください-それはまさにあなたが必要としているものかもしれません: http://en.m.wikipedia.org/wiki/Null_Object_pattern?wasRedirected=true

6
Tim Barrass

ルールは次のとおりです。シンプルなインターフェイス、複雑な実装。

APIに関する設計上の決定は、クライアントコードがAPIをどのように使用する可能性があるかを考慮して行う必要があります。あなたがどちらかを見ることを期待するならば

getAllCompaniesList(null);

または

if (companyFilter == null) {
    getAllCompaniesList();
} else {
    getAllCompaniesList(companyFilter);
}

その後、あなたはそれを間違っています。可能性のあるユースケースが、クライアントコードの記述時に、フィルターがある場合とない場合のいずれかである場合は、2つのエントリポイントを指定する必要があります。その決定が実行時まで行われない可能性が高い場合は、null引数を許可します。

3
Malvolio

実行可能な別のアプローチは、CompanyFilterを受け入れてtrueまたはfalseを返すcompanyIsIncluded(Company)メソッドを備えたCompanyインターフェイスを使用して、会社を含める必要があるかどうかを示すことです。 。 Companyは、companyIsIncludedメソッドの動作がequals()を反映するようにインターフェイスを実装できますが、companyIsIncluded()メソッドを持つシングルトンCompanyFilter.AllCompaniesを簡単に作成できます。常にtrueを返します。このアプローチを使用すると、null値を渡す必要はありません。AllComapniesシングルトンへの参照を渡すだけです。

0
supercat