web-dev-qa-db-ja.com

CQRSでの読み取りアプリケーションと書き込みアプリケーション間のコード重複の削減

私はアプリケーションを構築し、ドメイン主導の設計原則、CQRS、およびイベントソーシングを採用しようとしています。

読み取り用と書き込み用の2つのアプリケーションがあります。書き込みアプリケーションは、イベントストアデータベースを使用しています。また、アグリゲートでトランザクションが完了した後、ドメインイベントを読み取りアプリケーションに発行します。

読み取りアプリケーションと書き込みアプリケーションの両方がイベントを取得し、イベントを適用して現在の状態に集約を構築する必要があります。

  1. 書き込みアプリケーションは、IDによって集約が照会されたときにリポジトリでこれを行います。
  2. 読み取りアプリケーションは、書き込みアプリケーションからイベントを受信すると、ドメインイベントハンドラーでこれを行います。

読み取りアプリケーションと書き込みアプリケーションの間には、特にアグリゲートを作成してアグリゲートにイベントを適用するための多くの共通コードがあります。

私が解決しようとしている問題は、重複したコードを削除することです。私はいくつかの選択肢を心に抱きましたが、これらの選択肢の長所と短所をかなり理解しています。見落としているのかわかりません。また、他に簡単な方法がないかどうかを理解しようとします。私が持っているオプションは以下の通りです

オプション1:読み取りアプリケーションと書き込みアプリケーションで使用される共有ライブラリを用意します。現在、3つのコードリポジトリがあります。ここでは、独立した展開機能の一部が失われています。

オプション2:読み取りおよび書き込みアプリケーション用に1つの共通コードベースを用意します。異なる構成を使用して、読み取りアプリケーションと書き込みアプリケーションの2つのデプロイメントを用意します。ここでは、独立した配置機能は失われます。

オプション3:書き込みアプリケーションには、集約の状態構築ロジックがあります。読み取りアプリケーションが集計に関するイベントを取得したとき。書き込みアプリケーションに(http経由で)クエリを実行し、モデルを構築します

オプション4: CQRSで根本的に悪いことをしています。これが、コードが重複する理由です。だから私は概念を再考する必要があります。

同じ重要なイベントとペイロード構造を理解することから始めて、コマンド側とクエリ側の間でいくつかの重複があることはかなり自然です。標準的な構造でも問題はないかもしれませんが、DRYを参照したり、それらの間のコードの重複を削除したりしてはいけない理由はたくさんあります。

Googleで「DDD and DRYing code」を検索すると、コードレベルでこのように最適化しないことを正当化する多くのブログ投稿が表示されます。私もこれをやっていて、見た目は似ているが概念的に異なるコードセグメントを結合することにより、偶然に複雑さを導入しました。

次の3つの引数を検討してください。

  • 複雑なDDD実装では、1つの書き込み表現が複数の読み取り表現を持つことになります。これらの表現は似ていますが、非常に異なる要件(UIビュー、レポート、またはパフォーマンス)のために構築されます。これらの概念は完全に具体化され、時間の経過とともに複雑さが増すことが予想されるため、これらの概念を混在させることは避けてください。
  • リグレッションを作成したりSnowball効果を発生させたりせずにシステムの複雑さを増すことができるように、読み取りモデル間でもコードを分離しておく必要があります。
  • CQRSの根本的な前提の1つは、read側はwrite側とは異なるスケーリングになるということです。ソーシャルネットワークは、2つの側面が桁違いに異なる良い例です。したがって、デプロイとスケーリングを容易にするために、コードベースを独立して分離しておくことを積極的に望んでいます。同じコードベースを使用している場合でも、可能な限り分離しておく必要があり、ドメインイベントの形でのみ相互に対話する必要があります。
6
Subhash Bhushan