4

NullObjectPatternは、 「安全な」 (中立的な) 動作を意図しています

アイデアは、何もしないオブジェクトを作成することです(ただし、NullPointerExceptionもスローしません)

たとえば、次のように定義されたクラス:

class Employee {
    private String name;
    private int age;
    public String getName(){ return name; }
    public int getAge()    { return age;  }
}  

このコードでは NullPointerException が発生します。

 class Other {
      Employee oscar;

      String theName = oscar.getName(); // NPE

 }

NOPが言うことは、次のようなオブジェクトを持つことができるということです:

 class NullEmployee extends Employee {
      public static final  Employee instance = new NullEmployee(); 
      public String getName(){ return ""; }
      public int getAge()    { return 0;  }
 }

そして、それをデフォルト値として使用します。

 Employee oscar = NullEmployee.instance;

作成するクラスごとにコードを繰り返す必要がある場合、問題は発生します。解決策は、それを作成するためのツールを用意することです。

そのようなツールを作成したり、それを使用したりすることは、実行可能/合理的/有用でしょうか (存在する場合)?

おそらく、AOP または DI を使用すると、デフォルト値が自動的に使用される可能性があります。

4

6 に答える 6

3

私にとって、Null Object パターンは偽薬のように感じます。実オブジェクトと null オブジェクトはまったく異なる意味を持つ場合がありますが、動作は非常に似ています。偽薬と同じように、null オブジェクトは何も問題がないと信じ込ませますが、何か非常に間違っている可能性があります。

早い段階で失敗し、頻繁に失敗することは良い習慣だと思います。最終的には、実際のオブジェクトと null オブジェクトをどこかで区別する必要があり、その時点では、nullポインターをチェックするのと同じです。

ウィキペディアの記事から:

動作する既定の実装に対するこのアプローチの利点は、Null オブジェクトが非常に予測可能であり、副作用がないことです。つまり、何もしませ

問題点も指摘しません。null オブジェクトがアプリケーション全体を移動するとどうなるかを考えてみてください。その後、ある時点で、アプリケーションはオブジェクトから特定の動作を期待しますが、null オブジェクトの実装では実現できません。その時点で、アプリケーションがクラッシュするか、無効な状態になる可能性があります。null オブジェクトの起源を追跡するのは非常に困難です。nullポインターは最初に例外をスローし、問題の原因に直接注意を向けます。

ウィキペディアの記事が示す唯一の例は、の代わりに空のコレクションですnull。これは非常に良い方法ですが、単一のインスタンスではなく、オブジェクトのコレクションを扱っているため、null オブジェクト パターンのお粗末な例です。

要するに、すべてのクラスに対して null オブジェクトの実装を作成することは可能だと確信していますが、それをしないことを強くお勧めします。

于 2010-07-19T18:55:32.043 に答える
2

エラー状態をレイヤーの下にプッシュするように頼んでいるだけだと思います。

アプリケーションがオブジェクトを要求し、それが null の場合、問題がないことを願うだけでなく、その状態に対処する必要があります。オブジェクトが null の場合、それを使用しようとするとエラーが発生します。では、コードの残りの部分ですべてのエラー チェックを強制する必要はありません。

于 2010-07-16T15:10:08.183 に答える
2

これが良い考えかどうかはわかりません。「nullObject」は便利で、場合によっては完全に理にかなっていますが、すべてのクラスにこれを使用するのはやり過ぎです。特に、これによりバグ (または分析のギャップ) の診断が非常に難しくなる可能性があるためです。

また、新しいオブジェクトを返す 3rd part ライブラリはどうですか? これらの前にある種の「インターフェース」を配置して、null を返す場合に適切なフレーバーの nullObject を代用しますか?

これを自動化しようとしているとのことですが、適切な値を返すために実際の設計上の決定が必要になる場合はありませんか? つまり、Image オブジェクトがあり、"ImageType" (.gif、.jpg などの列挙型) を返すとします。

この場合、ImageNullObject は... "IMAGETYPE.GIF" を返す必要があります。「イメージタイプ.UNKNOWN」? ヌル?

于 2010-07-16T15:07:31.283 に答える
0

テストを除いて、私は一般的にこのタイプの概念をSlopのコーディングと呼んでいます。これはフェイルファストの反対であり、コーディングしていない状態を見つける可能性を延期します。

ここでの主なポイントは、オブジェクトがメソッドのコントラクトにない値を返すことができるのはなぜですか?メソッドのコントラクトを設計およびコーディングしたときに、nullを返すことができるかできないかを言いましたね。したがって、nullを返すことができる場合、それは重要です。nullを返すことができない場合、それは重要です。

また、使用しているオブジェクト参照がnullになる可能性がある場合、それは重要な値であり、そのオブジェクトのメソッドにアクセスする可能性のあるコードに浸ってはいけません。

その上、取得する機会があるたびにfinal / constant / invariant変数を使用します(少なくともオブジェクト指向言語では、正しい状態を保証できるコンストラクターの背後でデータを分離します)。不変オブジェクトがその変数を正しく設定している場合、それらの変数が無効な値を返すことは不可能です。

緊急パッチとテストを除いて、「コードを理解していないので、これは正しく機能していないと思いますが、理解しようとは思わない」以外は、この種のコーディングの言い訳は正直にわかりません。 -これは、IMO、エンジニアの正当な言い訳ではありません。

于 2010-07-22T21:58:55.130 に答える
0

私が見たいのは、コンパイラーが静的に定義された型でnullオブジェクトの動作を定義できるようにすることです。たとえば、「Foo」がクラス「bar」の場合:

クラスバー
  整数としての薄暗い値
  整数としての関数Boz()
    戻り値
  サブ終了
  Sub Nothing.Bar()As Integer
    リターン-9
  サブ終了
エンドクラス

Foo.Bar()を評価しようとすると、Fooがnullでない場合、または-9の場合にFoo.Valueが生成されます。拡張メソッドを使用してそのような機能を実現することもできますが、それは少し厄介なようです。

于 2010-12-14T04:31:15.787 に答える
0

機能的なnull オブジェクトを自動生成するのは難しいと思います。(もちろん、シェルを作成してから、実装自体に入力することもできます)。

簡単な例として - を返すメソッドの null 機能は何intですか? -1、0、またはその他の値を返す必要がありますか? 文字列を返すものはどうですか - 繰り返しますがnull""正しい選択ですか? 他のクラスを返すメソッドの場合 - それが独自のクラスの 1 つである場合、おそらくそのクラスに Null オブジェクトを使用できますが、どのようにアクセスしますか? おそらく、作成するすべてのクラスに、null オブジェクトのアクセサーを備えた何らかのインターフェイスを実装させることができますが、それは価値があるでしょうか?

を返すメソッドであってもvoid、null 機能が単純に返されるとは限りません。たとえば、一部のクラスは、クラスの不変条件を保持するために、独自のことを行った場合 (この場合ノーオペレーション)、親/デリゲート オブジェクトでメソッドを呼び出す必要がある場合があります。

したがって、基本的には、「null」動作を実装する場合でも、この動作が何であるかを推測できる必要があります。これは、ツールがそれ自体で実行するには高度すぎると思います。おそらく、すべてのメソッドに のような注釈を付け@NullReturns(-1)て、ツールにこれらをピックアップさせて null オブジェクトの実装を形成させることもできますが、それでもすべての状況をカバーするわけではなく、すべての機能を注釈。

于 2010-07-16T15:09:47.653 に答える