DDD:値オブジェクトにはリストを含めることができますか?
-
10-07-2019 - |
質問
私はドメイン駆動設計に精通しておらず、最近プロジェクトのドメインモデルの作成を開始しました。私はまだORMを決定していません(NHibernateを使用する可能性が高いと思います)。現在、Value Objectがそれだけであることを確認しようとしています。
「いいね」をカプセル化する以外の動作がほとんどないVOがいくつかあります。たとえば、用語:
public class Referral {
public Case Case { get; set; } // this is the a reference to the aggregate root
public ReferralType ReferralType { get; set; } // this is an enum
public string ReferralTypeOther { get; set; }
} // etc, etc.
この特定のクラスには、「ケース」への参照があります。これは2レベル上にあるので、リフェラルにアクセスしようとすると、行くことができます:case.social.referral(ケース、ソーシャル、およびリフェラルはすべてクラスであり、ケース内に単一のソーシャルがあり、内部に単一のリフェラルがありますソーシャル)。入力中に表示されるようになったので、紹介のケースはソーシャルエンティティを介してアクセスできるので、正しいとは思わないでしょう。
今、これはVOであるべきだと思いますが、これをデータベースに永続化するために使用する方法は、NHibernateにサロゲート識別子を割り当てることです(私はまだそうではありません)サロゲート識別子がVOにIdをすでに持っている必要があるかどうか、またはIDなしで動作できるかどうかがわからないため照会クラスの外部に公開されない保護されたIDプロパティ(DBに永続化することのみを目的とする)。
タイトルの質問に移りましょう:VOにはコレクション(私の場合はリスト)を含めるべきですか?これはデータベース内の1対多の関係としか考えられませんが、IDがないため、クラスをエンティティにすることは適切ではないと思われました。以下にコードを示します。
public class LivingSituation {
private IList<AdultAtHome> AdultsAtHome { get; set; }
public ResidingWith CurrentlyResidingWith { get; set } // this is an enum
} // etc, etc.
このクラスには現在Idがなく、AdultsAtHomeクラスには組み込み型(string、int)のみがあります。したがって、これがエンティティであるか、VOとして残ることができるかどうかはわかりませんが、独自のテーブルとプライベート/保護されたIDフィールドを使用してこれに1:mの関係を使用するようにORMを設定する必要がありますORMはDBに保持できます。
また、クラスごとに正規化されたテーブルを使用する必要がありますか?エンティティまたは値オブジェクトにクラスの複数のインスタンスが割り当てられている可能性がある場合、および/またはそれらのオブジェクトの一部とコレクション1:m関係がある可能性がある場合にのみ、クラスごとにテーブルを使用する必要があると思います。組み込み型を持つ特定の値オブジェクトに対して単一のテーブルを使用しても問題ありませんが、ネストされた型では、正規化されたテーブルを使用する方が有利だと思います。これに関する提案もありますか?
複数の質問で非常に冗長になったためごめんなさい:
1)値オブジェクトにサロゲート識別子(NHibernateなど)が必要ですか?
2)#1がyesの場合、これはプライベート/保護する必要があるので、私の値オブジェクトは「残り」ます。コンセプトの値オブジェクト?
3)値オブジェクトは他の値オブジェクト(たとえば、リスト)を持つことができますか、それがエンティティを構成しますか? (これに対する答えはノーだと思いますが、先に進む前に確認したいです。)
4)集約ルートから数レベル下の値オブジェクトから集約ルートへの参照が必要ですか? (私はそうは思わない、これはおそらくモデルを書くときの私の側の見落としである、誰もが同意する?)
5)ORMにマッピングを行わせながら、特定の事柄(ネストされたタイプや、1:mの関係のために独自のテーブルを必要とするプロパティを持つコレクションを持つタイプなど)に対して正規化されたテーブルを使用してもよいですか?エンティティに属する同じテーブルへのより単純な値オブジェクト?
ありがとうございます。
解決
1)はい- VOを独自のテーブルに保存する場合
2)プライベート/保護されたIDプロパティを使用できる場合、素晴らしい。または、明示的なインターフェイスを使用してIDプロパティを「隠す」こともできます。
しかし、あなたの質問を読んで、IDプロパティを見る開発者がオブジェクトがエンティティであると自動的に仮定することを提案していますか?もしそうなら、彼らは(再)トレーニングが必要です。
3)はい、できますが、次の制限があります:
- 非常にまれなはずです
- 他のVOのみを参照する必要があります
また、これを考慮してください:VOは固執するべきではありません 。必要なたびにVO全体を再作成するのは簡単/効率的ですか?そうでない場合は、エンティティにします。
4) 集計ロックの実装方法によって異なります。 Ayendeのソリューション、答えはイエスです。それ以外の場合は、オブジェクトグラフを横断して集約ルートに戻るメカニズムが必要になります。
5)はい。 DDDは永続的無知であることを忘れないでください(理想的な世界では!)。
ただし...
紹介はエンティティである必要があると思います。これらの会話を想像してください:
会話1:
- Tom:&quot; Hey Joe! David Joneの紹介をお願いできますか?&quot;
- ジョー:&quot;どっちがいい?&quot;
- トム:&quot;ごめんなさい、紹介番号123を意味します&quot;
会話2:
- Tom:&quot; Hey Joe! David Joneの紹介をお願いできますか?&quot;
- ジョー:&quot;どれ?&quot;
- トム:&quot;私は気にしません-ただ私に教えてください&quot;
会話1は、紹介がエンティティであることを示唆していますが、会話2は、紹介がVOであることを示唆しています。
もう1つ: Referral.ReferralType
はその存続期間中に変更されますか(エンティティである必要があるという別のヒントがあります)?変更されない場合は、ポリポルフィズムの使用を検討し、NHに処理させます。
役立つことを願っています!