9

DDD を初めて試みたのですが、集約設計で問題が発生しました。

私のアプリケーションには 3 つのエンティティが含まれています。グラフ、ノード、リンク。これらの各エンティティには、ユーザーが変更できる name プロパティがあります (これにより、'name' はエンティティ ID として不適切になると思います)。グラフにはノードのコレクションが含まれ、ノードには発信リンクのコレクションがあります (この問題の目的のために、着信リンクを無視しても問題ありません)。各ノードは、一度に 1 つのグラフにのみ関連付けることができます (ただし、グラフ間で移動できます)。同様に、各リンクは、任意の時点で 1 つのノードにのみ関連付けることができます (ただし、移動することはできます)。

私が強制しようとしている不変条件は、すべてのエンティティ名が親コレクション内で一意であることです。上記のアーキテクチャでは、不変条件は実際のコレクションにあるため、コレクションの所有者 (グラフとノード) は両方とも集約ルートにする必要があると判断しました。

私が抱えている問題は、ノードで名前の不変をどのように強制するかということです? リンクでは、ノード AR 内に隠されているため簡単です。そのため、ノードはすべてのリンクの名前変更/移動がこの不変条件を破らないことを確認できます。しかし、私が見る限り、不変条件を壊す可能性のある Node の直接の名前変更を妨げるものは何もありません。ここでは結果整合性は受け入れられるオプションではありません。これは真のシステム不変条件でなければなりません。

私が検討しているアプローチは、Node.Rename() に実際に不変条件を適用させることですが、私の懸念は、これには親グラフ内を調べて、名前の変更が有効かどうかを確認することです。これは正しく「感じられない」 - グラフがこの名前空間の制約を強制するものであるべきであり、その Node はそれについて何も知らなくてもよいように感じます。

これが理にかなっていることを願っており、人々の考えを聞くことを楽しみにしています.

編集: 上記のドメイン モデルは、ドメイン全体の単純化されたサブセットです。すべてのエンティティを 1 つの AR 内に保持するには複雑すぎます........

4

2 に答える 2

21

コメントですでに結論付けているように、唯一の集計ルートは Graph である必要があります。

集約と集約ルートには違いがあります。あなたの例では、グラフとノードの両方が集計ですが、集計全体を管理するオブジェクトはグラフです。ですから、これが根です。

オブジェクトが集約ルートであるかどうかを判断する最も簡単な方法は、自問自答することです。

このオブジェクトだけを親から切り離すことに意味があるでしょうか?

答えが「いいえ」の場合、おそらく集約ルートではありません。たとえば、単一の Node は、親 Graph の一部でない場合、おそらくほとんど役に立ちません。そのため、通常は集約ルートのリポジトリしかありません。対応する集約ルートの一部ではないオブジェクトにアクセスできないようにします。

次に、不変条件に進みます。あなたは次のように述べました(私のものを強調してください):

すべての [ノード] 名は、その親 [グラフ] 内で一意です

あなたは基本的にあなたの質問にすぐに答えました。単一のノードのコンテキストでは、その名前が一意であると言うのは意味がありません。しかし、Graph のコンテキストでは、それはNode ではなくGraph の不変量であるためです。したがって、グラフはこの不変式を保護する責任があります。

「神の集約ルート」について言えば、グローバル ビジネスの観点からは、単一の集約ルートを持つことは珍しくありません。しかし、DDD の重要な側面は、システム内のさまざまなコンテキストを識別することです。システムには、多くの Graph オブジェクトを含む高レベルのルートがある場合があります。グラフを管理するこの高レベルのコンテキストでは、おそらく、グラフ内の低レベルの Link オブジェクトには関心がありません。

コンテキストに従ってドメイン オブジェクトをモデル化することが重要です。これは、私がこの数か月で気付いた最も重要なことの 1 つです。ほとんどの人は DDD について知っているのは、リポジトリ、またはエンティティと値オブジェクトのせいかもしれませんが、これらは境界付けられたコンテキストほど重要ではありません。

何かのビジネス コンセプトは 1 つしかありませんが、この何かのコンセプトを表す複数のモデル、つまりコンテキストごとに 1 つの実装を使用することはまったく問題ありません。1 つの実装は集約ルートである可能性があり、もう 1 つの実装はより大きな集約の一部に過ぎず、すべてコンテキストに依存します。

一般的なソフトウェアのマントラは、コードの再利用、DRY などに関するものであるため、最初は、同じビジネス コンセプトを表す複数のクラスを持つことは間違っていると感じました。しかし、この気持ちを手放し、各実装には独自の責任があることに気付くと、物事がとても簡単になりました:)

于 2013-07-31T19:36:40.460 に答える