ドメインオブジェクトの永続化を「コレクションのように扱える抽象」として表現し、ドメイン層を DB やストレージの詳細から切り離す設計パターン。Eric Evans が『ドメイン駆動設計』で体系化した。
概要
ドメイン層から見ると、リポジトリは 「集約をしまっておく場所」 であり、SQL や ORM の存在は意識しない。インターフェース(例: IOrderRepository)はドメイン層に置き、その実装(PostgreSQL 用・テスト用インメモリ用)はインフラストラクチャー層に配置する。
ドメイン層
└─ IOrderRepository(インターフェース)
インフラストラクチャー層
├─ PostgresOrderRepository(実装)
└─ InMemoryOrderRepository(テスト用実装)
典型 API
| 操作 | 例 | 補足 |
|---|---|---|
| 取得 | FindById(id) / FindByCustomer(customerId) | 集約単位で返す |
| 追加 | Add(order) | 新規集約の登録 |
| 削除 | Remove(order) | 物理 / 論理は実装側の責任 |
| 検索 | Find(spec) | 仕様パターンで条件をオブジェクト化 |
「更新」を明示メソッドにせず、取得した集約の変更を Unit of Work で自動反映する設計が多い。
何を「集約」単位にするか
リポジトリは 集約ルートに対して 1 つ が原則。集約内のエンティティを直接取り出すリポジトリを作ると、不変条件が集約境界の外で破られやすい。
| ドメイン | 集約ルート | リポジトリ |
|---|---|---|
| 注文 | Order | IOrderRepository |
| 顧客 | Customer | ICustomerRepository |
| 商品マスタ | Product | IProductRepository |
| 受注明細 | (Order の内部) | リポジトリは持たない |
DAO との違い
| 観点 | リポジトリ | DAO |
|---|---|---|
| 抽象レベル | ドメイン語彙(集約) | テーブル / SQL に近い |
| 配置層 | インターフェースはドメイン層 | データアクセス層 |
| 戻り値 | 集約・値オブジェクト | DTO / レコード |
| 主な目的 | ドメインの純度を保つ | データアクセスの再利用 |
SOLID との関係
リポジトリは DIP(依存性逆転) の代表的な適用例。ドメイン層がインフラに依存するのではなく、インフラがドメイン層のインターフェースに依存する向きを作ることで、DB 交換・テスト差し替えが構造的に可能になる。
テスト容易性
リポジトリインターフェースを切ることで、ユースケーステストでは インメモリ実装 に差し替えられる。DB を起動せずにビジネスルールを高速に回せるため、TDD のサイクルを短く保てる。一方、SQL や JOIN の問題は別途インフラストラクチャー層の統合テストで担保する必要がある。
関連記事
- 開発手法ガイド:概要 — DDD 系列での位置づけ
- COBOL × DDD 設計パターン — 手続き型言語にリポジトリ的責務分離を適用する例
関連用語
- DDD — リポジトリが前提とする設計手法
- 集約 — リポジトリ 1 つに対応する単位
- DAO — データアクセス層のみを分離する類似パターン
- SOLID 原則 — DIP の典型適用例
- オブジェクト指向 — リポジトリは責務分離パラダイムの帰結
- ヘキサゴナルアーキテクチャ — リポジトリを「ポート」として位置づける上位アーキテクチャ
- SoC(関心の分離) — ドメインと永続化の関心を分ける原則
- SSoT — 集約をリポジトリ経由で扱うことで永続化の SSoT を保つ