6

最近、Null Object デザイン パターンに出会いました。同僚は、コード全体で発生する null ポインター チェックをなくすために使用できると言っています。

たとえば、DAO クラスが Customer に関する情報を (CustomerVO という値オブジェクトで) 返すとします。私のメイン クラスは、firstName と emailId を抽出し、顧客に電子メールを送信することになっています。

...
CustomerVO custVO = CustomerDAO.getCustomer(customerID);
if(custVO != null) { // imp, otherwise we may get null ptr exception in next line
     sendEmail(custVO.getFirstName(), custVO.getEmailID());
}
...

これは非常に単純な例ですが、このような null チェックは、値オブジェクトの複雑さに基づいてコード全体に急速に広がる可能性があります。

null チェックには 2 つの問題があります。コードが醜く読みにくくなる傾向があります。経験の浅い開発者は、実際には例外をスローするはずなのに、不必要な null チェックを行います。たとえば、上記のコードでは、getCustomer() 自体から例外をスローする方が適切です。これは、指定された CustID の顧客情報が見つからない場合、CustID が無効であることを示しているためです。

さて、null オブジェクト パターンに戻りますが、「null」CustomerVO オブジェクトを使用して null チェックを非表示にすることはできますか?

CustomerVO {
   String firstName = "";
   String emailID = ""; 
}

それは理にかなっていますか?どう思いますか?

また、アプリでの null チェックを最小限に抑えるために従うことは何ですか。

4

5 に答える 5

3

null オブジェクト パターンには用途がありますが、ここでチェックを行う必要があります。そうしないとsendEmail()、空の文字列の電子メール アドレスに送信しようとします (または、チェックを にプッシュしますsendEmail()。簡単に確認できますnull)。

ここで null オブジェクト パターンが本当に役立つのは、CustomerVOクラスがsendEmail()メソッドを実装した場合です。の契約により、参照が返されないことgetCustomer()が保証されるため、呼び出しを単純に連鎖させることができます。null

CustomerDAO.getCustomer(customerID).sendEmail();

その場合、sendEmail()メソッドは、特別な 'null オブジェクト' に作用するように求められていることを確認し、単に何もしません (または適切なことは何でも)。

于 2010-10-17T06:09:22.033 に答える
2

この場合、null オブジェクトは不適切である可能性があります。これは、デフォルトでは実際には例外が隠されている可能性があるためです。他のアクティビティを実行するために安全な null があるかどうかを確認する必要がある場合は、null パターンでは何も得られません。

あなたが述べたように、多くの新しい開発者は、プログラムの停止よりも悪い例外状況からコードを保護することに時間を費やしています。

于 2010-10-17T06:07:18.177 に答える
1

一般的なパターンであるこのタイプのコードに問題があります。実際に行っていることを分解する場合は、nullチェックはまったく必要ありません。ここでの問題は、私の見解では、SRPに違反しているということです。

この方法CustomerVO custVO = CustomerDAO.getCustomer(customerID);は2つのことを行います。

最初に顧客が存在する場合は顧客を返し、次にそのような顧客がいない場合はnullを返します。これらは2つの異なる操作であり、そのようにコーディングする必要があります。

より良いアプローチは次のとおりです。

bool customerExists = CustomerDAO.exists(customerID);

if (customerExists)
{
  CustomerVO custVO = CustomerDAO.getCustomer(customerID);
  sendEmail(custVO.getFirstName(), custVO.getEmailID());
}
else
{
   // Do whatever is appropriate if there is no such customer.
}

}

したがって、メソッドを2つに分割します。1つは要求されたオブジェクトが存在するかどうかをチェックし、もう1つは実際にオブジェクトを取得します。例外は必要なく、設計とセマンティクスは非常に明確です(私の見解では、does-not-exist-returns-nullパターンではそうではありません)。さらに、このアプローチでは、要求された顧客が存在しない場合、CustomerDAO.getCustomer(customerID)メソッドはをスローします。ArgumentException結局のところ、あなたはaを要求しましたが、Customer1つはありません。

さらに、私の見解では、メソッドはを返す必要はありませんnullNull明示的に、「正解が何であるかわかりません。返す値がありません」。 Null意味ではありません、それは意味の欠如です。自問してみてください。「なぜ、実際には起こらないはずの何かを返すのですか?あなたのメソッドは明らかにGetCustomer戻るはずです。Customerあなたが戻った場合null、あなたは単にコールチェーンをバックアップするために何をすべきかという責任を押し進め、契約を破っています。意味のあるデフォルトがある場合はそれを使用しますが、ここで例外をスローすると、正しい設計が何であるかについて少し難しく考える可能性があります。

于 2012-05-15T15:53:44.443 に答える
1

getCustomer顧客が見つからない場合、null を返すのではなく、メソッドで例外をスローする必要がありますか?

もちろん、その答えは場合によるということです。顧客 ID が存在しないというケースはほとんどないのでしょうか? つまり、例外的な状況ですか?その場合、例外が適切です。

ただし、データ アクセス レイヤーでは、何かが存在しないことはよくあることです。その場合、不測の例外的な状況ではないので、投げないほうがよいでしょう。

「空のフィールドを持つnull以外のオブジェクトを返す」は、おそらくそれ以上ではありません。返されたオブジェクトが「有効」であるかどうかを、null チェックよりもおそらく悪いチェック コードを追加せずにどうやって知るのでしょうか?

したがって、フェッチされているものが存在しないことが通常の状態である可能性がある場合は、null チェック パターンがおそらく最適です。予期しないものである場合は、データ アクセス メソッドで NotFound 例外をスローする方がよいでしょう。

于 2010-10-17T06:19:05.487 に答える
0

名前は NULL オブジェクト デザイン パターンであり、NULL チェック デザイン パターンではありません。null オブジェクトは、オブジェクトが存在しないことを意味します。これは、COLLABORATION で動作するオブジェクトがある場合に使用する必要があります。あなたの場合、NULLチェックで問題ないオブジェクトの存在をチェックしています。

NULL デザイン パターンは、NULL 例外処理を置き換えるものではありません。これは NULL デザイン パターンの副次的な利点の 1 つですが、デフォルトの動作を提供することを意図しています。

NULL チェックを NULL 設計パターン オブジェクトに置き換えないでください。アプリケーションにサイレント ディフェクトが発生する可能性があるためです。

NULL 設計パターンの DO と Dont の詳細については、以下の記事を参照してください。

http://www.codeproject.com/Articles/1042674/NULL-Object-Design-Pattern

于 2015-10-30T07:50:45.410 に答える