考える場所

ココロとカラダ、思考する全部

CQRSの小さな演習(5) リポジトリ

MySQLを使っていてもPostgreSQLを使っていても、JNDIでデータソース(JDBC)を取得することによって、ベンダー依存しないデータベースアクセスをすることができます。リポジトリはこれをもっと抽象化して、エンティティ(集約)を取得するインタフェースを考えるものです。

ドメインオブジェクトのコレクション

f:id:fukuchiharuki:20160319150109p:plain

A Repository ... , acting like an in-memory domain object collection.
- P of EAA: Repository

リポジトリは、インメモリなドメインオブジェクトのコレクションのように振る舞います。エンティティが必要なとき、RDBに接続してキーが指定のIDであるレコードを取得して、とドメインのモデルにおいては考えないようにします。エンティティの集合がなぜかもうそこ(メモリ)にはあって、すぐに取り出すことができる窓口、それがリポジトリというわけです。

コレクションのインタフェース

f:id:fukuchiharuki:20160319154044p:plain

There will typically be multiple adapters for any one port, for various technologies that may plug into that port.
- Alistair.Cockburn.us | Hexagonal architecture

ここで、RDBに接続して〜と考えないというのは、RDBに接続することがドメインの関心事ではないということです。たとえばTodoというエンティティがDBに保存されていても、ファイルに保存されていても、Todoというドメインに影響はありません。なので、ドメインのモデルにリポジトリの実装は入りません。ドメインのモデルにあるのはリポジトリのインタフェースまでです。

インタフェースの実装と注入

f:id:fukuchiharuki:20160319154742p:plain

class DoProcessor implements ICommandHandler<Do> {
  private ITodoRepository repository;
  public DoProcessor(ITodoRepository repository) {
    this.repository = repository;
  }
  public void receive(Do command) {
    Todo todo = repository.find(command.getId());
    todo.doIt();
  }
}

コマンドハンドラDoProcessorはリポジトリのインタフェースITodoRepositoryにしか依存していません。それでITodoRepositoryの実装(DBであるのかファイルであるのかは分からないが)をどうするのかと言うと、最も簡単にはコンストラクタの引数にすることができます。個人的にはこのやり方がすごく気に入っています。まず単純に見てコードを追いやすいですし、完全コンストラクタは使う側にとっても使われる側にとっても話を簡単にしてくれます。とは言え、今どき@EJBと書いておけばインジェクションできてしまう世の中ですから、DIを利用するのもよいと思います。

f:id:fukuchiharuki:20160319171543p:plain

コマンドからイベントを、リポジトリも含めてクラス図にするとこのようになります。ドメインのモデルはインフラストラクチャに依らず設計することができます。この設計(ポート)に従ってアダプタを後から実装することで、ドメインのモデルはインフラストラクチャを使って動作することができます。これはテスト用のアダプタを後から別に用意することができるということです。

次回は、

データの取り扱いを俯瞰してCQRSについて考えてみたいと思います。

blog.fukuchiharuki.me

最初

blog.fukuchiharuki.me