エンティティと値オブジェクトの特性を識別する

エンティティと値オブジェクトの特性を識別する

[[411622]]

正確さは集計の設計に直接影響するため、エンティティと値オブジェクトを区別することは非常に重要です。

集約は境界である

DDD では、集約はエンティティと値オブジェクト間の境界です。集約は完全なドメイン概念を外部的に表現し、オブジェクト指向設計の基本原則に従います。集約は多くの場合、複数の小さく凝集度の高いドメイン概念で構成されます。集約内のドメイン モデルはツリーを形成します。ツリーのルートはエンティティである必要があり、集約ルート (Aggregate Root) と呼ぶことができます。もちろん、集約の唯一の入口または出口であるルート エンティティ (Root Entity) と呼ぶこともできます。たとえば、Order 集約は、Order 集約の唯一の代表である Order ルート エンティティを定義します。

境界付けられたコンテキストのすべてのドメイン モデル (エンティティと値オブジェクト) は、草原の部族がパオの緩やかなコミュニティで構成されているのと同じように、関係の強さと概念の完全性に応じて複数の集約に分割されます。

値オブジェクトとエンティティの違いを考慮すると、それらのライフサイクルを管理する必要がある場合、値オブジェクトは集約の境界から独立して存在することはできません。つまり、ドメイン モデルの集約を識別する場合、エンティティと値オブジェクト間の関係の強さは集約境界の定義に影響しません。エンティティと値オブジェクトの間に関係がある限り、その関係がどれほど強いかに関係なく、値オブジェクトは、関係が存在するエンティティと同じ集約に配置する必要があります。値オブジェクトが複数のエンティティと関係を持っている場合、複数のエンティティが 1 つの集約に属していることを意味します。または、次の図に示すように、値オブジェクトを複数のコピーにコピーして、異なる集約に配置する必要があることを意味します。

このように、集約境界の識別は、エンティティ関係の強さの判断になります。エンティティと値オブジェクトを正しく識別する限り、集約を識別するときに値オブジェクトを考慮する必要がなくなり、識別の難易度が軽減されます。

文脈の影響

エンティティと値オブジェクトの本質的な違いは、それらが固有の ID を持っているかどうかにあることはわかっていますが、多くの場合、この違いは依然としてもっともらしいようです。さらに、エンティティと値オブジェクトの定義は絶対的なものではありません。異なるコンテキストでは、同じドメイン概念が異なる設計タイプとして定義される場合があります。たとえば、以下の紙幣:

購入の文脈では、買い手と売り手は紙幣の額面と通貨の種類だけを気にします。価値が等しい限り、それらは同じオブジェクトとみなすことができるため、値オブジェクトとして定義する必要があります。お金を印刷する文脈では、各紙幣には一意の識別子があります。たとえ両方とも人民元で100元であっても、IDが異なっている限り、それらは異なるオブジェクトとみなされるため、エンティティとして定義されます。したがって、エンティティと値オブジェクトを正しく区別するには、特定のコンテキストが必要です。

特定された特徴

それでも、比較的客観的な判断基準がまだ欠けている。そのために、私は以下の特徴をまとめました。

平等

エンティティと値オブジェクトを区別するには、まず等価性によって判断します。ドメイン モデル オブジェクトの属性値が等しい限り、それらは同じオブジェクトとみなされ、最初に値オブジェクトとしてモデル化する必要があります。それ以外の場合は、ドメイン モデル オブジェクトの一意の識別子を定義し、それをエンティティとしてモデル化する必要があります。

注: 等価性チェックを実行する場合、一意の識別子として使用される ID はドメイン モデルの属性とは見なされません。

たとえば、住所ドメインの概念では、国、州、都市、通り、郵便番号の属性値が等しい限り、それらは同じ住所とみなすことができ、Address クラスは値オブジェクトとして定義する必要があります。注文ドメインというおなじみの概念では、理論上は注文番号を除いて同じ属性を持つ 2 つの異なる注文が存在する可能性があるため、一意の注文番号を割り当てる必要があることは明らかです。注文はエンティティとして定義する必要があります。

ただし、同等性を判断する場合、ID と属性の間に暗黙的な対応関係がある場合があります。たとえば、出版業界の正式な出版物である書籍には、書籍フィールドの概念の ID に相当する一意の ISBN 番号があるため、Book はエンティティとして定義する必要があります。 Bookの等価性を判断する際に、ISBNを使って等価性を判断する必要はありません。基本的には、書籍名、著者(翻訳者)、出版社、価格、発行日、版、ページ数、単語数などの属性値が同じであれば、同じ書籍とみなすことができます。ということは、Bookを値オブジェクトとして定義できるということでしょうか。

当然のことながら、同等性の判断を行う際に考慮する属性が増えるほど、より多くの属性の組み合わせが出現し、「隠れた」一意の識別機能を形成します。ビジネス ルールを反映する一部の ID は、それ自体が属性値に基づいて定義されます。たとえば、航空会社の 2 文字コード、フライト番号、離着陸空港の 3 文字コード、およびフライトの日付に基づいて、フライトの一意の識別子を決定できます。一意の識別子を使用して同じフライトであるかどうかを判断でき、マッピングされた複数の属性値に基づいて同等性を判断することもできます。これにより、エンティティと値オブジェクトを区別する際に、人々が躊躇するように見えることがあります。たとえば、Tencent Conference の会議番号は会議の ID です。会議の平等性を比較する場合、会議番号以外の属性、たとえば会議名、会議の種類、開始時間、終了時間、作成者、作成時間などを考慮すると、会議の平等性を判断できますか?

したがって、平等性の判断に加えて、不変性も考慮する必要があります。

不変性

Eric Evans は、値によって等しいと判断される値オブジェクトは不変であるべきであるため、値オブジェクトを不変クラスとして定義することを提案しました。引き続き購入の文脈における紙幣の例を取り上げますと、50 元 + 50 元 = 100 元です。この 100 元は元の 50 元とは異なる紙幣です。

逆に、ID を除いて、オブジェクトの他のすべての属性値は、新しいオブジェクトを作成せずに変更できます。この場合、ドメイン オブジェクトは変更可能と見なされ、エンティティとして定義されていると見なされます。前述の通り、Meeting オブジェクトについては、meetingId 値が変更されない限り、会議名、会議タイプ、開始時刻、終了時刻などの属性値が大幅に変更された場合でも、同じ会議であるとみなします。明らかに、会議はエンティティとして定義する必要があります。

典型的な注文集約を考えてみましょう。

注文集計で OrderItem をエンティティとして定義するのはなぜでしょうか? ID 属性を無視すると、orderId、product、quantity の値が同じであれば、同じ注文項目とみなすことができます。ただし、注文品目の数量値は変更可能であり、数量が変更された注文品目は別の注文品目とはみなされません。注文項目は可変であるため、エンティティとして定義する必要があります。

OrderItem の Product プロパティを値オブジェクトとして定義する必要があるのはなぜでしょうか。Product 型は productId プロパティも定義していることを知っておく必要があります。これは ID 識別子を持っているため、エンティティとして定義すべきではないでしょうか。注文コンテキストでは、製品の productId は製品コンテキストの製品 ID から取得されるためです。注文集計では、productId は Product クラスの属性値と見なすことができます。 productId、name、price の値が同じであれば、同じ製品とみなされ、値は変更されません。これが、Product が値オブジェクトとして定義される理由です。

独立

平等性と不変性を考慮した後でも、独立性という例外が 1 つあります。エンティティの属性として、値オブジェクトはエンティティに添付される必要があり、独立して存在することはできません。ドメイン オブジェクトが等価性と不変性の両方を満たす場合は、値オブジェクトとして定義できます。ただし、独立して存在し、そのライフ サイクルを管理する必要がある場合は、そのようなクラスをエンティティに「アップグレード」する必要があります。

出席の文脈で休暇ドメインの概念を検討します。中国の太陰暦の休日のため、毎年新しい休日を設定する必要があります。休日の概念に対応する Holiday クラスは次のように定義されます。

当然ですが、このクラスの属性値がすべて等しい場合は、同じ休日とみなすことができます。休日の値が変更されると、別の休日とみなすこともできます。つまり、Holiday クラスは等価性と不変性の両方を満たしており、値オブジェクトとして定義する必要があります。ただし、出席コンテキストのドメイン モデルでは、Holiday クラスは完全に独立しており、他のエンティティに接続されておらず、ライフ サイクルも管理する必要があります。このとき、独立性の特性に従い、エンティティに「アップグレード」する必要があります。

優先度

上記の 3 つの特性は重要度順に並べられているわけではなく、総合的に考慮する必要があります。それでも判断できない場合は、優先順位の原則に従ってください。つまり、ドメイン概念を値オブジェクトとしてモデリングすることを優先します。

<<:  ドローンが農家にもたらす3つのメリット

>>:  再帰アルゴリズム: 不可解なスイッチ「ライトを引く」

ブログ    
ブログ    
ブログ    

推薦する

生成 AI は SOC アナリストにどのような力を与えるのでしょうか?

今日のサイバーセキュリティの脅威がますます深刻化する中、セキュリティ オペレーション センター (S...

...

Googleはプライバシーポリシーを更新し、インターネット上の公開情報をAIモデルのトレーニングに利用することを許可した。

検索エンジン大手のGoogleは7月4日、プライバシーポリシーを更新し、インターネット上の公開情報を...

アイティ族テクニカルクリニック第6回

【51CTO.comオリジナル記事】 [51CTO オリジナル記事、パートナーサイトに転載する場合は...

...

...

AI動画の「ちらつき」問題が解決しました!動画スタイルを簡単に変更、北京大学卒業生の作品

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

...

...

DIFFアルゴリズムがわからない場合は、私に連絡してください(画像付き)

序文インタビュアー: 「仮想 DOM と Diff アルゴリズムをご存知ですか? 説明してください。...

Baidu Shen Dou: AIネイティブアプリケーションを作成するには2つのステップが重要

2024年1月10日、Honor MagicOS 8.0発表会と開発者会議において、Honor Te...

AI を活用して経費管理におけるバイアス問題を解決する方法

新型コロナウイルス感染症のパンデミックによってもたらされた変化の中で、組織の業務が在宅勤務からリモー...

米国のテクノロジー業界が冬を乗り切る中、プログラマーたちは仕事を維持するために率先して給与を削減している。 35歳の会社員:給料をもう少し下げてもいい

テクノロジー業界は歴史的に平均給与が最も高い業界の一つであり、リストのトップにランクされることも少な...

DeepMindの創設者:生成AIは単なる過渡期であり、将来AIは無料になり、インタラクティブAIは人類を変えるだろう

DeepMindの共同創設者であり、Inflection AIの創設者でもあるムスタファ・スレイマン...