5

注: 例として C# を使用しますが、Java や他の多くの言語でも問題はほぼ同じです。

値オブジェクトを実装し ( M. Fowler による値オブジェクト パターンのように)、null 可能なフィールドがあるとします。

class MyValueObject
{   
    // Nullable field (with public access to keep the example short):
    public string MyField;
}

次に、Equals() をオーバーライドするときに、両方の値オブジェクトの MyField が null に設定されている場合をどのように処理しますか? それらは等しいかどうか?

C# では、次の理由から、それらを同等に扱うことは明らかです。

  1. これは、クラスの代わりに C# 構造体を使用し、Equals() をオーバーライドしない場合の Equals() の動作です。

  2. 次の式は true です。

    null == null
    object.ReferenceEquals(null, null)
    object.Equals(null, null)
    

ただし、SQL では (少なくとも SQL Server の方言では)、NULL = NULLは false ですが、NULL is NULLは true です。

O/R マッパー (私の場合は NHibernate) を使用する場合、どのような実装が期待されるのか疑問に思っています。「自然な」C# 等価セマンティクスを実装すると、O/R マッパーがそれらをデータベースにマップするときに悪影響が生じる可能性がありますか?

それとも、値オブジェクトで null 許容フィールドを許可するのは間違っているのでしょうか?

4

3 に答える 3

1

ORMはリレーショナル モデルを認識しているため、通常は SQL セマンティクスを使用してクエリを実行する方法を公開します。

たとえば、NHibernateis [not] nullは HQL とRestrictions.Is[Not]NullCriteria で演算子を提供します。

もちろん、これらのパラダイムが衝突する API があります: LINQ です。ほとんどの ORM は、null と比較するときに正しいことをしようとします (つまり、 で置き換えるis null) が、特に動作が明らかでない場合に、問題が発生することがあります。

于 2010-12-01T04:12:26.777 に答える
0

あなたには2つの問題があると思います:

MyValueObject1 つのインスタンスが別のインスタンスと等しいかどうかを知る必要があることです。

そして第二に、それが持続性にどのように変換されるべきか。

あなたの角度がそれらを互いに近づきすぎているように見えるので、これらを別々に見る必要があると思います.

nullいずれかの値の効果が不明な場合はMyField、(a) 以外の別のタイプを返しstringます。(b) 同様の(または同様の特殊なケースの実装)の派生物を返すstringようにします。(c) またはメソッドをオーバーライドして、これらのインスタンスが等しいとはどういう意味かを正確に指定します。EmptyStringEquals

ORM が特定の式 (を含むMyValueObject) を SQL に変換できない場合は、おそらく、永続化レイヤーでより困難な作業を行っても問題ありません (SQL 変換から比較を実行します - はい、パフォーマンスの問題はわかっていますが、そうではありませんドメインモデルをきれいに保つことを支持します。解決策は、「ドメイン モデルに最適なもの」から派生する必要があるようです。

@ジェームズ・アンダーソンは良い点を指摘しています。nullエラー状態と失敗状態のために予約します。スペシャルケースがますます適切だと思います。

于 2010-12-01T05:53:08.310 に答える
0

個人的には、(エラーのないコードで)null になる可能性がある場合、それらは等しいものとして扱われるべきだと思います。ただし、null であってはならない場合 (つまり、顧客の名前、または配達の住所) は、そもそも null になることはありません。

于 2010-12-01T02:26:32.487 に答える