daisuzz.log

実践ドメイン駆動設計におけるRepositoryについて

最近Javaで書かれたソースコードリファクタリングをがっつり行う機会があったので、実践ドメイン駆動設計を読み直しています。今回はその中でRepositoryについて書いていきたいと思います。

実践ドメイン駆動設計 (Object Oriented SELECTION)

実践ドメイン駆動設計 (Object Oriented SELECTION)

 

実践ドメイン駆動設計でのRepositoryの分類

実践ドメイン駆動設計では、Repositoryについて、コレクション指向のRepositoryと、永続化指向のRepositoryという二種類のRepositoryの実装を紹介しています。

コレクション指向のRepositoryは、JavaのCollection型、ひいてはHashSet型と同じインターフェースを集約単位で提供することを目指して実装されています。

インターフェースとして持つ基本的なメソッドはadd(), addAll(), remove(), removeAll(), findById(), findAll()といった追加、削除、取得を行う処理であり、更新に関するメソッドを持ちません。Repositoryから集約を取得し、その集約の要素を変更することで更新を実現できるように実装します。

更新処理をどこに持たせるか?

ここで疑問になるのが、更新の処理をどこに持たせるべきかということです。Hibernateを直接使うのであれば、たしかにEntityの要素を更新するだけで、DBにも更新が反映されますが、その場合Hibernateが用意するEntityとドメインモデルである集約を1対1で利用する必要があり、これは特定のライブラリにドメインモデルが依存してしまっている状況を作ってしまうので個人的にはあまりやりたくないです。

かと言ってHibernateのEntityを使わない場合は、集約あるいはドメインサービスに更新系のメソッドを作成して、メソッド内部で変更をDBに反映する必要があります。リポジトリに更新のメソッドを持たせないという方針があるため、DBへの反映の詳細を集約あるいはドメインサービス内に置くことが考えられますが、これではドメインモデルがDBの具体的な仕様に依存してしまい、ドメインモデルはDBの変更に影響を受けてしまいます。

こういう理由から、実践ドメイン駆動設計のうちコレクション指向のRepositoryを実装する場合は、更新処理がないread onlyなシステムに限られるもしくは、ドメインモデルが特定のフレームワークに依存することを許容してHibernateなどのORMを利用するのではないかと思っています。

個人的には、実践ドメイン駆動設計でもう一つのRepositoryとして紹介されている永続化指向のRepositoryを実装することが現実的であると思います。

永続化思考のRepository

永続化指向のRepositoryは、コレクション指向のRepositoryとは異なり、追加、削除、取得に加えて、save()やsaveAll()といった更新系のメソッドを持ちます。永続化指向のRepositoryを使って集約を変更する場合は、まず取得系のメソッドを利用して変更対象の集約を取得し、その後集約の状態を変更し、最後にRepositoryの更新メソッドに変更した集約を渡すことで、変更した情報がDBなどに永続化されます。

コレクション指向のRepositoryではRepositoryが更新操作を持つことができなかったため、エンティティやドメインサービスで永続化をおこなう必要がありましたが、永続化指向のRepositoryであれば、永続化に関する詳細を全てRepositoryの実装クラスに集めて隠蔽することができます。