リポジトリとは
一般的に「リポジトリ」とはデータの「保管庫」を表します。ソースコードリポジトリであればGitやApache Subversionが有名ですが、DDDにおけるリポジトリは、エンティティや値オブジェクトから構成される集約の格納と取得を担当します。リポジトリは、クライアントへ集約を提供し、背後のデータベースとのやり取りを隠ぺいします。
通常、集約とリポジトリの関係は一対一になります。例えば「注文」の集約を利用したい場合「注文リポジトリ」を使用します。クライアント側はリポジトリのおかげで、物理的な構成(RDBなのか、NoSQLなのか等)を意識せずに、簡単に集約を操作できます。
リポジトリで集約を操作する流れ
リポジトリはデータベースにアクセスしたり、ファクトリを利用したりします。その流れを見てみましょう。
「A.新しい集約をデータベースに追加する流れ」の場合、クライアント側からファクトリを呼び出して集約を生成します。そして、リポジトリの追加メソッドを呼び出すことで永続化の対象として登録します。これによってデータベースに集約の情報が挿入されます。
逆に「B.データベースから集約の情報を取り出し、再構成する流れ」の場合、リポジトリはデータベースにクエリを投げてデータを取り出します。そしてファクトリを使って集約のモデルを再構成し、クライアントに集約を戻します。取り出した集約の変更内容はデータベースへ反映されます。
エヴァンス氏のDDD本におけるリポジトリの説明
IDDD本では、リポジトリの特徴として以下の説明をDDD本から引用しています。
- グローバルアクセスを必要とするオブジェクトの各型に対して、あるオブジェクトを生成し、その型のすべてのオブジェクトで構成されるコレクションが、メモリ上にあると錯覚させることができるようにすること。
- よく知られているグローバルインターフェイスを経由してアクセスできるようにすること。
- オブジェクトの追加と削除を行うメソッドを提供すること。
- ある条件に基づいてオブジェクトを選択し、属性値が条件に一致するような、完全にインスタンス化されたオブジェクトかオブジェクトのコレクションを戻すメソッドを提供すること。
- 集約に対してのみ、リポジトリを提供すること。
この中でも最初の「コレクションがメモリ上にあると錯覚させること」はDDDのリポジトリの特徴をよく表現していると思います。データベースに対する操作(クエリ生成やオブジェクト詰め替え)を意識しなくてよいため、ドメインモデルの操作に集中できます。
リポジトリとDAOの違い
リポジトリは、データベースを操作するため、従来のDAO(データアクセスオブジェクト)と似ているかもしれません。しかし、DAOがデータ中心指向であるのに対して、リポジトリはオブジェクト指向アプローチである点で異なります。
そのため、DDDとしては「ドメインモデル」+「リポジトリ」+「データマッパー(Hibernate等)」との相性が良く、逆にDAOでは「トランザクションスクリプト」+「テーブルモジュール」または「テーブルデータゲートウェイ」または「アクティブレコード」との相性が良いとIDDD本では紹介されています。