2012-04-07 7 views
26

Fowler(here)によれば、リポジトリは、「メモリ内ドメインオブジェクトコレクションのように機能する、ドメインとデータマッピングレイヤの間を仲介します」。たとえば、私のCourier Serviceアプリケーションでは、新しい実行がサブミットされると、アプリケーションサービスは新しいRun集約ルートオブジェクトを作成し、要求からの値を入力してからRunRepositoryに追加してからUnit of Workを呼び出して保存しますデータベースへの変更。ユーザーが現在の実行のリストを表示したい場合、私は同じリポジトリに照会し、その情報を表す非正規化されたDTOを返します。 CQRSを見たときにリポジトリはCQRSとどのように適合していますか?

しかし、クエリが同じリポジトリにヒットしません。代わりに、おそらくデータストアに直接向かい、常に非正規化されます。私のコマンド側は、NewRunCommandとHandlerに進化し、NewRunドメインオブジェクトを作成してデータをデータストアに永続化します。

最初の質問は、私たちがドメインオブジェクトのメモリ内コレクション(キャッシュする場合)を維持していない場合、リポジトリがCQRSモデルに収まる場所です。

アプリケーションサービスに送信される情報に、ドメインオブジェクトを構築するためにサービスが解決しなければならない一連のID値だけが含まれている場合を考えてみましょう。たとえば、要求には実行に割り当てられた宅配便のID番号が含まれます。サービスはID値に基づいて実際のCourierオブジェクトをルックアップし、AssignCourierメソッド(宅配業者を検証して他のビジネスロジックを実行する)を使用してNewRunにオブジェクトを割り当てる必要があります。

もう1つの質問は、クエリの分離とリポジトリの不在を考えれば、アプリケーションサービスがクーリエドメインオブジェクトを見つけるためにルックアップをどのように実行するのでしょうか?

UPDATE

デニスのコメントの後、いくつかの追加の読書との考えに基づいて、私は私の質問を言い換えます。

CQRSは単にデータアクセスとデータストレージメカニズムを超えるファサードあるリポジトリを奨励するように私には見えます。 Fowlerのようにコレクションの「外観」を提供しますが、Dennisが指摘するように、メモリ内のエンティティを管理していません。これは、リポジトリ上のすべての操作がパススルーであることを意味します。

は、どのように作業ユニットは、このアプローチに適合していますか?通常、UoWはリポジトリに加えられた変更をコミットするために使用されますが、リポジトリがメモリ内のエンティティを維持していない場合、UoWはどのような役割を果たしますか?

コマンドハンドラは、同じリポジトリ、別のリポジトリ、またはおそらくリポジトリの代わりにUoWへの参照を持っていますか?
+0

Fowlerの定義は、Eric Evanのリポジトリパターンとわずかに異なります(DDDの本で説明しています)。私はCQRSがEvanの定義に傾いていると思います。 –

+0

説明してください。私が見ることのできる唯一の違いは「メモリ内」の側面ですが、使用法は同じでしょうか? – SonOfPirate

答えて

5

私は、アプリケーションの状態を表すためにコマンド側に単純なキー値ストアを保持するCQRSシステムと、単にメッセージを相関させる(何らかの種類のサガを使用して)クエリストアを利用してアプリケーションは代わりに状態を示します。どちらの方法でも、これらのアプローチに関連する永続性テクノロジは間違いありませんが、これらの場合のリポジトリパターンは、その上の不要な抽象化になります。

CQRSに関する私の経験は、過去のイベントを再生してビジネスロジックとインバリアントをカプセル化して強制する集約を再現したイベントソーシングにのみ関連しています。この場合、リポジトリパターンは、これらの集約のいずれかを検索するためのより簡単な方法を提供できる使い慣れた抽象である。

クエリの面に関しては、できるだけデータストアに近づけることをお勧めします。これは、UI(何でも)とデータストアの間のリポジトリ、サービス、ファサードなどを避けることを意味します。

これらのアプローチの例を使用しているのが分かります。たぶん、次のプロジェクトを見てみましょう:

をNESの場合、リポジトリは単に使い慣れたインターフェイスを提供しますアグリゲートを直接追加して読み込む作業単位との間でやりとりします。しかし、現在のプロジェクトで、私は私の集約のためのリポジトリを持っている - 私はこれがどのようにオーソドックスわからない

+1

私は、そこの例のほとんどがCQRSとEvent Sourcingを結合していることに同意します。しかし、私は、CQRSパターンの一部ではなく実装選択においてこの関係が指摘されているUdi Dahanと同じ考え方です。 – SonOfPirate

+0

Event Sourcingは、エンティティの状態を維持するのではなく、変更をトランザクションとして保持するという考え方を追加します。私はその価値を知ることができますが、これに必要な専門知識と思考プロセスがあれば、それは難しいアプローチです。私の場合、私は引き続き利用しなければならないレガシーデータベースを含め、多くの機関の開発者やレガシーアプリケーションを扱っています。だから私のCQRSの実装にはEvent Sourcingは含まれていません。 – SonOfPirate

+0

イベントモデルとアプリケーションの状態を表すモデルを同期させておくことが難しくなることがあります。 –

1

役立つかもしれないいくつかのより多くのリンク

エンティティルート。このリポジトリには、GetとApplyEventの2つのメソッドしかありません。

すべてのイベントは、そのタイプの共通インターフェースを実装しています。OrderEventsなどがあります。個人的には、新しいタイプのイベントの追加が非常に簡単になるように、各イベントのビジネスロジックを多相メソッドに入れます。

Getの場合、リポジトリはイベントストアに行き、そのタイプのスコープ内のすべてのイベントを取得します(たとえば、単一のストアロケーションの注文)。次に、イベントの再生を行い、与えられたすべてのイベントのエンティティの現在の状態に到達します。スナップショットからも機能するので、ロードするたびにすべてのイベントを再作成する必要はありません。一般的なイベントリポジトリを使用して、イベントの保存方法を抽象化したり、仕様に基づいて検索することもできます。

ApplyEventsはイベントのリストを取り込み、それに基づいてエンティティの状態を変更して返します。リポジトリに、変更するだけでなく、エンティティを再作成するオプションを与えることに注意してください。これは関数型のプログラミングではうまくいくが、C#またはJavaではオブジェクトの等価性(obj1 == obj2)を避けることが最善であることを意味する。私は、エンティティではなくValueObjectsだけが、とにかく平等であるべきだと主張したいと思います。

実際にどのように動作するのですか(C#) - 注文があり、アイテムを追加したいと思います。 currentOrder.Itemsは空のリストを返します。そうすれば私は

今私はcurrentOrder.Itemsが1つのエントリを見るはずです。

ここでの欠点は、自分のビジネスロジックをEntityに入れるのではなく、すべての処理がイベントを通じて行われることです。しかし、私の場合、ほとんどすべてのオブジェクトがシリアライズ可能(基本的にはPOCO)で、複数のシステムで動作する必要がある場所では、実際にはうまくいきます。

関連する問題