問題
上図のように、UserPersona
エンティティと UserPersonaRepositoryInterface
を定義した。
このとき私は、エンティティのドメインメソッドとリポジトリのメソッドを見比べて、「どちらも情報の取得や更新を行っており、責務が重なっているのでは?」という疑問を抱いた。
特に、以前の設計では UpdatePersonalInfos(userID, infos []PersonalInfo)
のように、リポジトリがエンティティ内部の情報に直接アクセスして更新する設計となっており、「これはリポジトリが本来持つべき責務を超えていないか?」という違和感があった。
解決
ユースケース層の構造を見直すことで、それぞれの責務の違いが明確になった。
// ユースケース層の例
persona := repo.FindByUserID("user-123") // ← データ取得(リポジトリ)
persona.UpdatePersonaInfoByName("趣味", "サウナ") // ← 状態変更(ドメインメソッド)
err := repo.Update(persona) // ← 永続化(リポジトリ)
-
リポジトリの責務は、
UserPersona
集約ルート全体を取り扱い、エンティティ単位での取得・保存・削除を担当する。 - 一方で、ドメインメソッドは
UserPersona
の内部状態(personalInfos
など)に対する業務ルールに基づく変更処理を担う。
このように、責務を正しく分離することで、リポジトリがドメインの内部構造に介入することを防ぎ、ドメインモデルの保守性と一貫性を保つことができる。
✔ 教訓
「リポジトリが操作するのは、あくまで集約ルート全体である」
「状態を変更するのはドメインの責務、状態を保存するのはリポジトリの責務」
当初は曖昧に感じた両者の役割も、Clean Architecture の原則を意識することで、明確に区別して設計できるようになった。