集計境界を設計する方法は?


10

eコマースのようなアプリケーションを書きたいのですが。

また、類似のアプリケーションでは、製品のプロパティと機能が異なる場合があります。このような機会をシミュレートするために、次のドメインモデルエンティティを作成しました。

カテゴリ -これは「エレクトロニクス>コンピューター」のようなもの、つまり製品のタイプです。Сategoriesには、プロパティのリストが含まれています(List <Property>)。

プロパティ -名前、測定単位、データ型を含む独立したエンティティ。たとえば、「名前」、「重量」、「画面サイズ」。同じプロパティに異なる製品を含めることができます。

製品 -プロパティに関連する名前と値のリストのみが含まれます。Valueは、プロパティの値フィールドとフィールドIDのみを含むオブジェクトです。

たとえば、新しい製品を追加するときに、現在のカテゴリに関連するプロパティ(category.AddNewProduct(product))を含む現在のカテゴリに関連するすべてのデータを知る必要があるため、このスキームでカテゴリを単一の集計のようにすることを最初に決定しました。しかし、どのカテゴリにも属さない新しいプロパティを追加する必要がある場合はどうすればよいですか。たとえば、特定のカテゴリにプロパティを追加することを明確に示しているため、このcategory.AddNewProperty(property)は実行できません。

次のステップでは、個別のプロパティを個別の集計に決定しましたが、それは単純なエンティティのリストになります。

もちろん、PropertyAggregateのようなものを作成して、プロパティとビジネスルールの内部リストを保持できますが、製品を追加するときは、不変条件を確認するために、このカテゴリに属する​​プロパティのリスト全体をカテゴリ内に含める必要があります。しかし、アグリゲート内のリンクを他のアグリゲートで維持することは悪い習慣であることも知っています。

このビジネスケースを設計するためのオプションは何ですか?


カテゴリ、プロパティ、製品のより完全な例を提供できますか?電子機器やコンピュータがカテゴリになり、iPhone Xが製品の例になり、プロパティは正確に何でしょうか。11インチのディスプレイ?
Neil、

あなたはほぼ正しいです。私はいくつかの説明を追加しました
cephei '22

「データコンテナ」の観点からのみ集計デザインを検討しているようです。また、アカウントトランザクションの側面、コラボレーション/同時アクセス、発生するイベント、状態遷移などを考慮して、アプリケーションの用途の例について考えたいかもしれません
guillaume31

回答:


7

DDDの観点ではCategoryProductおよびPropertyはエンティティです。これらはすべて、独自のIDを持つオブジェクトに対応しています。

オプション1:オリジナルデザイン

Category単一の集計のルートを作成しました。一方では、これは理にかなっています。これは、オブジェクトが変更されたときに集計が一貫性を保証し、そののがProduct必要になるためPropertiesですCategory

ここに画像の説明を入力してください

ただし、反対に、単一の集約は、そのすべてのオブジェクトがそれらを所有するルートに関連付けられていることを意味し、すべての外部参照はこの集約ルートを介して行われる必要があります。これは以下を意味します:

  • 特定のProduct1つは1つにのみ属しCategoryます。場合はCategory削除されるので、そのですProducts
  • 特定Propertyは1つだけに属しCategoryます。別の言い方をすると、「テレビ画面」と「コンピューターモニター」が2つのカテゴリである場合、「テレビ画面:サイズ」と「コンピューターモニター:サイズ」は2つの異なるプロパティになります。

第二の点は、あなたの物語に対応していない:「しかし、私はちょうど新しい追加する必要があるとき、私は何をすべきProperty任意のカテゴリに属していないことを」。そして、同じものPropertiesが別ので使用できるかどうかは明確ではありませんCategories

オプション2:集計外のプロパティ

Propertyがから独立して存在する場合Categories、それは集約の外になければなりません。そして、あなたが共有したい場合は、同じPropertiesCategories(高さ、幅、大きさ、等...のために理にかなっています)。これは間違いなくそうです。

結果は、Propertyとに属しているものとの間のリンクにあります。集約の内部からに移動できPropertyますが、a Propertyから対応する値に直接移動することはできなくなりました。このナビゲーション制限は、UMLダイアグラムに表示できます。

ここに画像の説明を入力してください

この設計は、参照セマンティック(Javaなど)を使用してList<Property>in を作成することを妨げるものではないことに注意してください。Categoryリスト内の各参照Propertyは、リポジトリ内の共有可能なオブジェクトを参照します。

この設計の唯一の問題は、変更Propertyまたは削除できることです。これは集計の外にあるため、集計はその不変条件の一貫性を処理できません。しかし、これは問題ではありません。これは、DDDの原則と現実世界の複雑さの結果です。エリックエヴァンスの著書「ドメイン駆動設計:ソフトウェアの中心にある複雑性への取り組み」での引用:

AGGREGATESまたがるルールは、常に最新であるとは限りません。イベント処理、バッチ処理、またはその他の更新メカニズムを通じて、他の依存関係を特定の時間内に解決できます。ただし、AGGREGATE内で適用された不変条件は、各トランザクションの完了時に適用されます。

したがって、はい、を変更する場合Property、サービスがそれを参照するカテゴリをチェックすることを確認して、必要に応じて更新する必要があります。

オプション3:カテゴリ、プロパティ、製品が異なる集合体で

Productaがシングルに属しているという仮定が成り立つかどうか疑問に思いますCategory

  • 私はオンラインショップで1つ以上Productを提案するのをよく見ますCategories。たとえば、「ノートパソコン」カテゴリと「コンピュータ」の下に「ノートパソコンブランドXモデルY」があり、「プリンタ」、「スキャナ」、「ファックス」の下に「多機能プリンタZ」があります。
  • 誰かがProduct最初に作成し、後でそれをカテゴリに割り当てて値を入力することは可能ではないですか?
  • カテゴリを分割したい場合、本当にその製品を削除してから、新しいカテゴリの下にそれらを再作成しますか?

集計は単純化されず、集計にまたがるルールがさらに増えます。しかし、あなたのシステムははるかに将来の証明になるでしょう。


これは非常に役立つ説明です。ただし、いくつかの点を明確にしたいと思います。2番目のオプションから始めたいと思います。私が取る場合Propertyの境界を越えてCategory集計し、この平均値Property自体に集計となり、リポジトリを必要ですか?それが真である場合、必要なものList<Property>Categoryインスタンスに渡す方法は?コンストラクタを通じて?それは正しいでしょうか?そしてPropertyCategoryまだ作成されていないのIDのリストを見つけるにはどうすればよいですか?
cephei 2017年

つまり、@ zetetic:はい、独立したプロパティリポジトリが必要になります。既存のプロパティのリストをカテゴリのファクトリに渡すか、空のカテゴリを作成して、リストにaddPropertyメソッドを入力します。見返りに質問:「必須」と「オプション」のプロパティが必要で、必須の特性はカテゴリによって異なるとします。これをどのように扱いますか?
クリストフ

あなたの質問に答える最初に頭に浮かぶのは、私は特別なエンティティFeatureを作成でき、それはにしか属さないということProductです。このエンティティは検索に参加しません。あなたは何を言っていますか ?
cephei 2017年

@zeteticなぜだ!値は現在製品にあるのでそのままにしておき、機能をカテゴリに関連付けます。カテゴリはn個のフィーチャ(その集計の一部)を持ち、プロパティはm個のフィーチャを定義します(ただし、リンクはカテゴリ->フィーチャを経由します)。次に、多対多の関係をより管理しやすい要素に分解し、集計の境界を明確にしました。最後に、リポジトリの注射について:あなたはアイデンティティによって他の凝集体を参照する場合、これは必要ありません(この記事読んinformit.com/articles/article.aspx?p=2020371&seqNum=4を
クリストフ・

5

私が見ると、これは次の2つの方法のいずれかで解決できます。

カテゴリーは特別なタイプの製品です

つまり、データベース内の特定の製品には、まったく同じテーブル製品を指す外部キーが含まれています。製品は、外部キーがその製品のIDと等しい製品が存在しない場合にのみ製品です。つまり、その下に製品がない場合、それは製品です。

これは少し物事を簡素化します。プロパティと製品は1対多の関係にあり、したがって、カテゴリーも製品であるため、カテゴリーも1対多の関係にあります。カテゴリにプロパティを追加するのは、プログラムの製品にプロパティを追加するのと同じくらい簡単です。すべてのプロパティをロードすることは、製品のプロパティを関連するカテゴリ製品のプロパティと組み合わせることを意味し、親のないカテゴリ製品に到達するまで続きます。

eコマースアプリケーションはこの区別をする必要がありますが、とにかくカテゴリの製品をロードする可能性が高い場合でも、カテゴリまたは製品を扱っているかどうかを知ることはパフォーマンスの低下ではありません。また、各製品(カテゴリ)が追加の作業なしでサブ製品のリストを開くため、製品レベルでツリー形式で検索するのにも適しています。

これの欠点は、もちろん、カテゴリに意味をなさない追加の情報が製品に存在することであり、製品に扱いにくい未使用フィールドが作成されます。このソリューションはアプリケーションでより柔軟になりますが、直感的ではありません。

多対多の関係

製品はプロパティとの複合的な関係ではなくなりました。2つをリンクする製品テーブルとプロパティテーブルの両方の外部キーを使用してProductPropertyテーブルを作成します。同様に、プロパティテーブルと多対多の関係を持つカテゴリテーブルと、カテゴリテーブルとプロパティテーブルの両方の外部キーを持つCategoryPropertyテーブルがあります。

製品自体はカテゴリと多対1の関係にあり、基本的に、適切に形式化されたselectステートメントを使用して、製品とカテゴリの両方に関連する一意のプロパティのリストを作成できます。

データベースの観点からは、これは間違いなくよりクリーンで柔軟です。クエリが適切に実行されている場合、アプリケーションは、ほとんどの場合、CategoryPropertyまたはProductPropertyを直接処理せずに実行できます。ただし、カテゴリや製品を所有者として扱うべきではありません。これは、プログラム内の独自のエンティティでなければなりません。これはまた、上記のプロパティの管理は、プロパティ自体を作成し、2つの別々のステップでカテゴリまたは製品に関連付けることの問題になることを意味します。確かに最初のソリューションよりも多くの作業が必要ですが、決して難しいことではありません。

これに加えて、そのプロパティのいずれかが他で使用されている場合は、カテゴリまたは製品の削除時に追加のチェックを実行する必要があります(特定の製品/カテゴリのすべての関連プロパティを安全に削除できる最初のソリューションとは異なります)。 。

結論

専門家のコンテキストでは、多対多のアプローチを使用して、製品からの距離と距離からのカテゴリに、製品と物件からの製品を追加します。データが重複する可能性はなく、ある意味では、これら3つそれぞれを独自のエンティティーとして推論する方が簡単です。ただし、より簡単なアプリケーションを作成することもできるため、最初の解決策は決して悪いものではありません。最終的に1つのソリューションから別のソリューションに移行する必要があると思われる場合は、おそらく2番目のソリューションを選択することをお勧めします。

幸運を!


詳細で興味深い答えをありがとう!2番目のケースで説明したように、すでにモデル化したデータベースレベルでは、このパターンはエンティティ-属性-値と呼ばれますが、コードレベル、つまり集計の定義にこだわっています。ほとんどの場合、これらのエンティティはすべて一緒に使用されます。1つのアグリゲートに結合することは可能ですが、ディレクトリのフィルのように、アグリゲートから追い出される場合があります。
cephei 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.