- Repositoryは「永続化層」ではない
- Repositoryが扱うのは「集約」である
- なぜRepositoryを介さずに触ってはいけないのか
- interfaceを切ることが目的ではない
- 良いRepositoryは「問い」を持っている
- RepositoryとUseCaseの健全な距離
- Repositoryを薄くしすぎない
- この章のまとめ
Repositoryは「永続化層」ではない
Repositoryと聞いて、多くの人がまず思い浮かべるのは次のような役割です。
- データベースへのアクセスを隠蔽する
- CRUD処理をまとめる
- ORMやSQLの詳細を隔離する
これらはRepositoryの“効果”ではありますが、Repositoryそのものの本質ではありません。
Repositoryは、永続化のための仕組みではなく、集約を扱うための抽象です。もしRepositoryを「DB操作クラス」として設計してしまうと、DDDの重要な意図はほぼ失われます。
Repositoryが扱うのは「集約」である
前章で述べた通り、集約は「同時に守るべき判断とルールの単位」でした。
Repositoryは、その集約を
- 取得する
- 保存する
ための唯一の窓口です。
重要なのは、Repositoryが
- Entity単体
- テーブル単位のレコード
を扱う存在ではない、という点です。Repositoryが扱うのは、常に意味を持った集約全体です。
この制約があるからこそ、集約の不変条件は安全に保たれます。
なぜRepositoryを介さずに触ってはいけないのか
もし集約の内部オブジェクトを、Repositoryを介さずに直接取得・更新できてしまうと、次のような問題が起こります。
- 不変条件を守らずに状態を書き換えられる
- 集約の境界が形骸化する
- 「正しい操作」が分からなくなる
これは、設計が破綻する典型的なパターンです。
Repositoryは、「この集約は、こういう単位でしか扱えない」というルールをシステム全体に強制する役割を持っています。
interfaceを切ることが目的ではない
Repositoryはしばしばinterfaceとして定義されます。そのため、「Repository = interface」という理解が広まりがちです。
しかし、interfaceを切ること自体は目的ではありません。
Repositoryを抽象として定義する理由は、
- 集約の概念をインフラから切り離すため
- モデルの言葉で取得・保存を表現するため
です。
もしinterfaceを切ったにもかかわらず、
- findById
- save
- delete
といった汎用的なCRUDメソッドしか存在しないのであれば、そのRepositoryはドメインの言葉をほとんど語っていません。
良いRepositoryは「問い」を持っている
良いRepositoryは、ドメインの問いをそのままメソッドとして表現します。
- 有効な注文を取得する
- 処理待ちの支払いを探す
- 特定の条件を満たす集約を取得する
これらは、SQLやクエリの話ではありません。ドメインが何を知りたいかという問いです。
この形でRepositoryを設計すると、UseCaseのコードは自然言語に近づいていきます。
RepositoryとUseCaseの健全な距離
UseCaseは、Repositoryを使って集約を取得し、操作し、結果を保存します。
ここで重要なのは、UseCaseが
- 集約の内部構造を知らない
- 永続化の詳細を知らない
という状態を保つことです。
UseCaseが知っているのは、
- どの集約を使うか
- どの操作を呼ぶか
- 結果を保存する必要があるか
だけで十分です。
この距離感が保たれていると、UseCaseは「流れ」に集中でき、判断はモデルと集約に委ねられます。
Repositoryを薄くしすぎない
「Repositoryは薄く保つべきだ」という言葉も、誤解されやすい表現です。
Repositoryが薄いとは、ロジックを持たないことではありません。 ドメインの「判断」を持たないことです。
Repositoryは、ドメインモデルを永続化の世界に橋渡しする責務だけを持ちます。
- キャッシュ戦略
- データソースの切り替え
- 永続化の最適化
これらはRepositoryの内部にあって構いません。重要なのは、それらがUseCaseやモデルに漏れ出さないことです。
この章のまとめ
Repositoryは、永続化のための仕組みではありません。Repositoryは、集約を集約として扱うための境界です。
次章では、Repositoryを使って処理の流れを組み立てる存在である「UseCase」について掘り下げていきます。そこで、DDDとアプリケーション層の関係が、より明確になります。