Serviceを読んで理解し、同意したものとみなします。スタック・オーバーフローはプログラマーとプログラミングに熱心な人のためのQ&Aサイトです。3,249件49Javaでドメイン駆動設計を実践しようとしています。質問ですが、DBレコードからドメインモデルを完全に構築するのがコスト面で現実的でない場合、どのように実装すべきでしょうか?例えば、Lineが多数のPointを持ち、かつ、PointからLineを参照可能なモデルがあるとき、指定するidのPointの完全な状態のドメインモデルを構築するには、Point、Lineに加え、Lineに属する全てのPointのDBレコードを獲得しなくてはなりません。仮にLine.pointsの数が非常に多い場合、完全な状態のドメインモデルを構築するコストが高くなります。遅延ロードは遅延ロードを行う操作が行われるまでDBセッションを閉じられないのが少し気にかかります。別の策として、似て非なるLineとPointクラスを用意することも考えましたが、LineやPointクラスにフィールドやロジックが増えてくるとコードの重複が多くなってしまいそうです。票5非常に面白い話題ですね!ちょっと簡単にまとめてみました。参考になれば幸いです。話は若干逸れますが、そもそも相互参照がつらいって話があるので、その話から。関連の章を読んでいたら理解できると思いますが、双方向の関連は仕様を満たしているか検証する実装コストが高いと思います。(B)は両方の状態が正しく設定されていないといけません。実際は(A)もしくは(B)の参照の設定を忘れてしまうと、どちらが正しい状態を示しているか見分けがつかなくなります。それだけ参照が増えるというのは設計や実装が複雑になる原因になるってことですね。いうことで、エリックさん曰く、便利なだけの参照はやめて、本質的な参照に絞れって話らしい。相互参照をできるだけ諦めて単一方向の参照に絞れと。次に、集約の境界定義について。集約にはオブジェクト同士の関連の爆発を防ぐための役割もあります。ひとつ質問がありまして、PointはLineの一部(つまりPointという集約の一部)でしょうか?それともLineはPointからみて外部のオブジェクトでしょうか?前者であれば、PointはLineの一部という考え方です。Pointは所属しているLineがひとつしかないので、Point.lineを保持するメリットはさほどないと思っています。その他の属性}上記だと、Point内部でLineにアクセスできないという問題があるかもしれません。あれば、少し変形させてPointからLineの機能にアクセスできるようにする方法もありますね。}}後者、つまり両方がグローバルエンティティだとしても、集約内部に外部の集約を内包せずに識別子で間接的な参照を作るべきだと思います。識別子自体はその集約の一部なので境界定義としての一貫性は保証されます(そもそも集約というのは、内部に複数のオブジェクトを抱えていても、それ自体で1個のオブジェクトとみなす考え方なので、外部の集約を含めるのは現実的ではない)。実体はどこから手に入れればいいかというと、リポジトリから取得すればいいわけですね。一手間入って面倒というのはありますが、ドメインモデル間の結合度は下がります。lineRepository.resolveAllByLineId(point.getLineId);この例は、間接であってもこれは相互参照なので、仮に子が親を知っているという前提であれば、単一方向参照にできますね。LineIdでPointを取得したい場合はリポジトリに問い合わせればよいですし。pointRepository.resolveAllByLineId(line.getId());以上、僕がいつも考えている設計と実装はこんな感じです。追記:補足ですが、DDD二部のライフサイクル管理の章を読んでいただくとわかりますが、集約をベースにしたファクトリやリポジトリなどのライフサイクル管理はユビキタス言語由‌​来ではないので、ドメイン上の課題とは直接関係ありません。ファクトリやリポジトリの存在意義としては、ドメインモデルから永続化などの複雑な責務を分離し、ドメイン上の課‌​題解決に専念するためのものです。便利だからといって、ドメインモデル内にリポジトリ機能などを安易に実装してしまうと、このようなリスクに直面することになります‌​。リスクテイクするってのもありですが。僕はいまのところそういう設計は複雑になるだけだと思っているのでやっていませんね。Lineからみて複数のPointがあって、それを遅延ロードしたいという性能上の要求がドメイン上の課題解決より優先される場合はあります。Pointをそれぞれグローバルエンティティ化してしまえば、いくらでも遅延ロードできます(LineからみてPointがローカルエンティティの場合は、その時点での複‌​数のPointを含むLineの状態を再現しなければならないので、状態管理が難しくなるでしょう)。個の銅バッジ1その補足部分は「編集」で本文に追記したらどうでしょう。控えめに読んでも、コメントに収まっているのがもったいない内容だと思います。3:361ありがとうございます。|3集約について、きちんと整理したほうが良いと思いました。集約の内部のモデル(Pointは値オブジェクトで十分と思われる)としてPointを実装するのかによって、設計方針が大きく異なります。複数のPointを同一トランザクションで一貫性を持って変更する必要がある場合は、Line集約の内部モデルとしてPointを実装するのが良いです。その場合、PointにはLineを介してしか触ることはできません。同一トランザクションでの一貫性が必要ない場合は、LineとPointを別の集約として実装することで、Line集約のインスタンスが肥大化することを防ぐことが出来ます。第10章が詳しいです。Qiitaでも簡単にまとめてくれている人がいます。さんが書かれているとおりです。PointからLineへの参照をlineIdで実装することで、集約間の関係を疎結合にすることができます。Line集約の内部モデルとしてPointを保持する場合Point自身のidに大きな意味は無いので、おそらくPointは値オブジェクトとして実装したほうば良いです。Point数が大きい場合にモデルの構築コストが大きくなりますが、トランザクショナルな一貫性が必要なら、この制約は受け入れざるを得ないでしょう。再利用するオブジェクトをキャッシュするなど、別のところで工夫は出来そうです。haradakiroさんが言うように、そもそもこのモデルが適切なのかも再考した方が良いと思います。LineやPointを読込みおんりーで利用するなら、CQRSでリード専用のDTOを実装する方法もあります。|2ほぼ今出ている回答で十分かつ、重複もあるとは思いますが、私の意見も。皆さんはこういったケースではどのように実装されていますか?私であれば前提としてそもそも本当に相互参照が必要なのかを検討。複雑さを回避する為、原則相互参照は採用しない。返す、他の回答者の方々が指摘されている様なドメイン特有の限定的、効率的な取得が可能かを検討といったアプローチをとります。ドメインモデリングの話しになる為、より明確な実装案を提示するには、例示のドメインを明確にする必要がでてきます。ベースの設計は、パフォーマンスのトレードオフとなる選択が求められる事が多い為、原理主義にならず常に現実の要求とバランスさせる事が重要です。復元せずに機能するフェーズはごく短いと思われます。非常に多い場合は性能上の考慮が必要です。集計用クエリを発行してスカラー値として取得する」など、全ポイント復元を極力避けるようにすべきかと。ドメインモデルって、対象ドメインを周辺的な処理から隔離してなるべくピュアに表現しようとする試みなので、データアクセスはリポジトリの責務として簡潔なメソッドを提供するのがよいです。実現することも考えられます。そもそもがコスト高な世界(工数的にも計算機資源的にも)なので、モデルがそれほど巨大でなければ基本は完全構築なんじゃないでしょうか。その時も上記のようにリポジトリや集約ルートのドメインに構築の責務を持たせる。問題が発生するよりはマシかなと思います。|1おお、DDDの質問だ。蛇足ながらちょっと、コメントを加えてみようと思います。Lineは、直線なので、Pointで表すとすると2つのPointが必要ですね。Chain(折れ線)のどちらかでしょうか?そのあたりをモデルで記述できているとよいですね(名前はとっても大事です)。そこで、DDDで大事なのは、そこでどういう振る舞いを期待しようとするかです。折れ線の状態を確かめたいのか(交差がないかとか、閉じてるかどうかとか)?そこでの振る舞いに合わせて、適切な表現方法を探すことになります。すると、DDD本の航路みたいに、Legの連続で表すほうが適切かもしれませんね。それらのクラスをどう使いたいのかをご説明いただけると、よりよいコメントができるかもしれません。個の銅バッジ1折れ線を想定していましたが、例を提示したかっただけなのでモデルの用途などは考えていませんでした。用途に合わせて最適な解を見つけるべきということですね。|回答スタック・オーバーフローに参加してくれて、ありがとうございます!質問の回答を共有してください。回答を説明し、自分の検討結果も共有してください。意見を述べること(意見を述べるなら、参照リソース、自分の経験で意見をサポートしてください)さらにサポートが必要な場合このヘルプを参考してください。“回答を投稿”をクリックすることで利用規約、プライバシーポリシー、及びクッキーポリシーに同意したものとみなされます。タグが付いた他の質問を参照するか、自分で質問をする。WEBAppでCollectionの内容物を全て表示用に加工するアルゴリズムについて2DDD(ドメイン駆動設計)でドメインモデルの切り出し方について質問です。質問のフィードこのRSSフィードを購読するには、このURLをコピーしてRSSリーダーに貼り付けてください。