# 2021-06-02 Pair-A v2 定例 ## 疑問 ### 粟田 #### 別集約のルートに対してのID参照は必ず持つべきか? - オブジェクト同士の参照は必要最低限が良い? - ID参照があれば、紐づくオブジェクトをIDから取れる - ID参照がなければ、別集約のリポジトリに依頼する必要がある #### 集約内部はルートから必ず辿る? - リポジトリは集約単位で返す - 内部だけを取るためにリポジトリに問い合わせるのは原則が崩れる #### デメテルの法則について - メソッドチェーンは悪なのか? - どこまで守るべきか? ```typescript= class Circle { members: User[] join(user: User) } class User { name: string age: number } const circle = new Circle(); // ダメ circle.members.push(new User('Awata')) // こうすべき circle.join(new User('Awata')) // ダメ circle.members.find(member => member.name === 'Awata') // こうすべき circle.findMemberByName('Awata') // これは? circle.findMembersByName('Awata').age ``` #### ドメインサービス内で永続化するか、しないか - ファクトリは永続化まではしない(してもいいのかもしれないが、責務が増えるから避けたい) - 課題グループを削除する時に、所属する課題も削除するドメインサービスを作ったら永続化までドメインサービスがやる?それとも削除すべきIDだけを返すような作りにする? - 統一できるなら、可読性が上がると思う - ただどちらかに統一すると、それによって作りが変な感じになったりしそう #### 排他制御について 更新と削除が同時に動き始めて、削除した後に更新が走った場合、削除されたはずのデータが登録されるっていうケースが起きそう、どう防ぐ? - upsertっぽい作りにせず、insertとupdateを明確に使い分ければ、updateは対象行なしになる - insertは成功してしまっても良い気もする - ロックする、、、?のはなんかいまいちな気もする #### 別集約の外部キー制約 削除の順番を保証するのはどこか? 本来はリポジトリに隠蔽すべきだと思うが、別集約の場合は順番を担保できない #### 概念としてあるInActive 否定系は基本よくない、ただ概念として存在する場合は? #### 仕様を変えたことを共有する ### 玄徳 executeみたいなメソッドが一つだけあるだけのクラス、関数でいいんではない?という気持ちになったがどうなのでしょうか ```typescript= // このようなクラス class GetAllMember { private queryService: IGetAllMemberQueryService; constructor(queryService: IGetAllMemberQueryService) { this.queryService = queryService; } public async execute(): Promise<GetAllMemberDTO> { const result = await this.queryService.execute(); return result; } } // このような関数にしてしまったほうが、テストしやすかったり、状態(プロパティなど)を持たなくていいのでは? // というより、クラスで統一してるからクラスで書く、というのが脳死な気がする const getAllMember = async ( queryService: IGetAllMemberQueryService, ): Promise<GetAllMemberDTO> => { const result = await queryService.execute(); return result; }; ``` ### 永井 - DBのカラムでunique制約がある場合、isExistするためのドメインサービスは必要か? dbに関わらず、必要 DBでチェックすると例えば、リポジトリでエラーが発生する -> ドメイン知識がリポジトリに漏れている。 ###### Tags: `Pair-A v2`