web-dev-qa-db-ja.com

値とエンティティオブジェクト(ドメインドリブンデザイン)

DDDを読み始めたばかりです。 Entity vs Valueオブジェクトの概念を完全に把握することはできません。ValueオブジェクトがEntityオブジェクトとして設計されている場合にシステムが直面する可能性のある問題(保守性、パフォーマンスなど)について説明してください。例は素晴らしいでしょう...

82
StackUnderflow

本質的な区別に還元すると、アイデンティティはエンティティにとって重要ですが、値オブジェクトにとっては重要ではありません。たとえば、誰かの名前は値オブジェクトです。 Customerエンティティは、顧客の名前(値オブジェクト)、List <Order> OrderHistory(エンティティのリスト)、およびおそらくデフォルトのアドレス(通常は値オブジェクト)で構成されます。顧客エンティティにはIDがあり、各注文にはIDがありますが、名前にはありません。一般に、とにかくオブジェクトモデル内では、アドレスのIDはおそらく重要ではありません。

通常、値オブジェクトは不変オブジェクトとして表すことができます。値オブジェクトの1つのプロパティを変更すると、本質的に古いオブジェクトが破棄され、新しいオブジェクトが作成されます。これは、コンテンツと同じようにアイデンティティに関心がないためです。適切には、オブジェクトのプロパティが別のインスタンスのプロパティと同一である限り、NameのEqualsインスタンスメソッドは「true」を返します。

ただし、Customerなどのエンティティの一部の属性を変更しても、顧客は破壊されません。通常、Customerエンティティは変更可能です。 IDは同じままです(少なくともオブジェクトが永続化されると)。

気づかずに値オブジェクトを作成する可能性があります。細分化されたクラスを作成することでエンティティの何らかの側面を表現しているときはいつでも、値オブジェクトがあります。たとえば、有効な値にいくつかの制約がありますが、より単純なデータ型で構成されるクラスIPAddressは、値オブジェクトになります。 EmailAddressは文字列にすることも、独自の動作セットを持つ値オブジェクトにすることもできます。

データベースにIDを持つアイテムでさえ、オブジェクトモデルにIDを持たない可能性は十分にあります。しかし、最も単純なケースは、一緒に意味をなすいくつかの属性の複合です。 Customer.Nameとして一緒に構成できる場合、Customer.FirstName、Customer.LastName、Customer.MiddleInitial、およびCustomer.Titleは必要ないでしょう。おそらく、永続性について考えるまでにデータベース内の複数のフィールドになりますが、オブジェクトモデルは気にしません。

98
JasonTrue

すべての属性によって集合的に定義されるオブジェクトは、値オブジェクトです。属性のいずれかが変更された場合、値オブジェクトの新しいインスタンスがあります。これが、値オブジェクトが不変として定義されている理由です。

オブジェクトがその属性のすべてによって完全に定義されていない場合、オブジェクトのアイデンティティを構成する属性のサブセットがあります。残りの属性は、オブジェクトを再定義せずに変更できます。この種のオブジェクトは不変では定義できません。

より簡単に区別する方法は、値オブジェクトを、決して変化しない静的データと考え、エンティティをアプリケーションで進化するデータと考えることです。

31
Richard Dorman

以下が正しいかどうかはわかりませんが、Addressオブジェクトの場合は、エンティティの代わりにValueオブジェクトとして使用したいと言います。なぜなら、エンティティへの変更は、リンクされたすべてのオブジェクトに反映されるからです(たとえば、Person)。

この場合:あなたは他の人と一緒に家に住んでいます。アドレスにエンティティを使用する場合、すべてのPersonオブジェクトがリンクする一意のアドレスが1つあると主張します。 1人が引っ越した場合は、彼の住所を更新する必要があります。アドレスエンティティのプロパティを更新すると、すべての人が異なるアドレスを持ちます。値オブジェクトの場合、(不変であるため)アドレスを編集することはできず、その個人の新しいアドレスを提供する必要があります。

これは正しいですか? DDDの本を読んだ後も、この違いについて私はまだ混乱していたと言わざるを得ません。

さらに一歩進んで、これをデータベースでどのようにモデル化しますか? AddressオブジェクトのすべてのプロパティをPersonテーブルの列として持っていますか、それとも一意の識別子を持つ別のAddressテーブルを作成しますか?後者の場合、同じ家に住んでいる人々はそれぞれAddressオブジェクトの異なるインスタンスを持ちますが、それらのオブジェクトはIDプロパティを除いて同じです。

6

値の種類:

  • 値型は、エンティティ型に依存して、自分では存在しません。
  • 値型オブジェクトは、エンティティ型オブジェクトに属します。
  • 値型インスタンスの寿命は、所有するエンティティインスタンスの寿命によって制限されます。
  • 3つの値タイプ:基本(プリミティブデータ型)、複合(アドレス)およびコレクション(マップ、リスト、配列)

エンティティ:

  • エンティティタイプは自分で存在できます(ID)
  • エンティティには独自のライフサイクルがあります。他のエンティティから独立して存在する場合があります。
  • 例:個人、組織、大学、モバイル、ホームなど。すべてのオブジェクトには独自のアイデンティティがあります
4
Premraj

addressは、ビジープロセスに依存するエンティティまたは値オブジェクトです。アドレスオブジェクトは宅配便サービスアプリケーションのエンティティにできますが、アドレスは他のアプリケーションの値オブジェクトにできます。クーリエアプリケーションのアドレスオブジェクトの識別事項

3
Dharmesh

私は別のスレッドでこれについて尋ねましたが、私はまだ混乱していると思います。パフォーマンスの考慮事項とデータモデリングを混同している可能性があります。カタログアプリケーションでは、顧客は必要になるまで変更されません。それは馬鹿げているように聞こえますが、顧客データの「読み取り」は「書き込み」よりもはるかに多く、多くのWeb要求がすべて「アクティブなセット」のオブジェクトにヒットしているため、何度も顧客をロードし続けたくありません。そのため、Customerオブジェクトの不変の道を進みました。それをロードし、キャッシュし、顧客に会いたい(マルチスレッド化された)リクエストの99%に同じものを提供します。その後、顧客が何かを変更したら、「エディター」を取得して新しい顧客を作成し、古い顧客を無効にします。

私の懸念は、多くのスレッドが同じ顧客オブジェクトを認識し、それが可変である場合、1つのスレッドが変更を開始すると、他のスレッドで混乱が起こることです。

私の問題は、1)これは合理的であり、2)プロパティに関する多くのコードを複製せずにこれを行うにはどうすればよいかということです。

2
n8wrl

EntitiesValue Objectsの3つの区別

  • 識別子と構造的同等性:エンティティには識別子があり、エンティティは同じ識別子を持つ場合は同じです。手の届かない値オブジェクトは構造的に等しいため、すべてのフィールドが同じ場合に2つの値オブジェクトが等しいと見なします。値オブジェクトに識別子を含めることはできません。

  • 可変性と不変性:値オブジェクトは不変のデータ構造ですが、エンティティは存続期間中に変化します。

  • 寿命:値オブジェクトはエンティティに属している必要があります

0
Ramin Farajpour