# 2021-06-10 メンターセッション ## 質問 ### オブジェクト同士の参照について #### 大前提 - 業務を表すために必要な参照は保持しておくべき - 必要ないものは表現しない #### 参照は少なくしておくべきか? - 循環参照が発生してそもそも作れないケースもあるかも - idで紐つけてれば大丈夫かも - そもそも使うのかどうかで考えてもいいかも - 例えば、親→子を見ることがあっても子→親をみるタイミングがユースケースとしてないのであれば、いらない #### 集約内部の場合はルートから辿れるようにしておくべき? - べき #### 別集約の場合、極力1つの向きに参照のむきを限定する? - 質問に至った背景は? - オブジェクトどうしの関係性をシンプルに保ちたい - 参照しまくってたら整合性を保つのが大変になる - ケースバイケース - 必要なければ減らしたほうがいいとおもう - DDDは、業務を表現する手段 - 業務にて発生しない状況は再現する必要はない #### 相互参照にすると管理が複雑になる? - なる ### デメテルの法則について - 明確な基準はない - Arrayクラスのメソッドとか使うと、無秩序に配列を破壊できるので、しないほうがよい - .ageとかをアプリケーション層で呼んだりするのは、ドメインルールがドメイン層の外にでちゃってる状況 - 「デメテルの法則的にどうか?」っていうのはよくわからない - DDDてきに守れるなら守ったほうがいいのは、それはそう - ドメインの知識を隠蔽する。そのプロパティは公開するべきか?を先に検討するべき ### ドメインサービスで永続化をすべきか - してはいけない理由はない - ドメインサービスは、ファクトリでもないし、なんだこれ?→その他!みたいなものが集まりがち - ドメインサービスのメソッドは、ユビキタス言語になるようにしよう、と、エリック・エヴァンスさんは言っている - 抽象的な扱いができるような命名にしておくべき - 「複雑なメソッドは、なるべく一部に集めて、多くの部分はできるだけシンプルにしよう」という話がある → それがDDDではドメインサービスなのかもしれない ### 更新と削除が同時に実行される際の排他制御について - MySQLのアイソレーションレベルを適切に設定していれば、起きない…? - 同じタイミングで削除と更新が走る場合、削除が完了するまで更新は待機するので - upsertにしてなければおきない(ふつうのupdateにしておけば、「そんなんないよ!」で失敗してくれるはず) - 消したはずのものが戻ってもいいようなものだったらupsertにしてもいいかも ### 別集約の外部キー制約について - ユーザーがポスト持ってるなら、まずポスト全部消してからユーザーを消さないといけない - やるなら以下の方法 - カスケードを使ってデリートする - アプリケーションが知っている - ポスト→ユーザーの順番で消す、という順番はどこが知っているべき? - ドメインサービス - 関連付けはWEBサービスでなくても存在するのでドメインルールに近い - 外部キーもドメインのルールを表しただけなのでは? - 集約が一緒ならリポジトリで消しちゃっていいかも? ### 概念として存在する否定形の表現をコードでどう表現するか - 宅急便を例 - 不在だった は 概念としてある。在ではない(?)という状態ではない。 - こういうケースなら 不在 としてコードに書く - アクティブ、インアクティブは意味がよくわからないので避けるかも ### メソッド1つを持つだけのクラスを関数にしたい - やっちゃってもいいのでは? - DIコンテナとか使えるのはクラスのいいとこ - 関数では依存の向き制御しにくいんでは? - 関数の型を定義できるので、インターフェース代わりに使うことができるかも? - 依存の向きの制御が必要なところはクラスの方が自然 - それ以外は関数で書いたほうがシンプルになる可能性が高い - チームにあわせる、というのもある - 認知負荷がかかる場合がある ### エンティティのIDについて - DBにオートインクリメントを持たせてしまうとファクトリでエンティティが初期化できなくなる - uuidもしくは採番テーブル(シーケンス)などを使う - 以下リンクで同様なことが起き、対策案の掲示あり - https://github.com/little-hands/ddd-q-and-a/issues/34 ###### Tags: `Team-2`