私はCQRSとイベントソーシングと共にDDDを研究しています。私は最近、グレッグヤングが数年前に行った講演を聞きました。彼は、CQRSとイベントソーシングはトップレベルのアーキテクチャではなく、特定の制限されたコンテキストの範囲内で使用する必要があると述べました。そうでなければ、アンチパターンになります。
これは一般的には理にかなっていますが、イベントソースシステムの利点の1つであると私が認識したものとは矛盾するようです。異なるコンテキストで同じ「もの」の異なるコンテキスト固有の集約ルートを持つことができること、それぞれが同じイベントストリームから再構築されます。
たとえば、Customer
は異なるコンテキスト(注文、マーケティング/製品の推奨、カスタマーサービス、認証)で異なる実装を持ちますが、特定のイベントは複数のコンテキストに関連します(たとえば、CustomerEmailChanged
はマーケティング、カスタマーサービス、認証に関連します。OrderPlaced
は、注文とマーケティングに関連します)。
その話を聞く前は、これらの異なるコンテキストでイベントストアを共有し、関連のないイベントは無視することを計画していました。それでも、それを処理するための非常に合理的な方法のように思われますが、さまざまな境界のあるコンテキスト間の線をぼかして、これがどのようにアンチパターンになるかを見ることができます。
これに対処する正しい方法は何ですか?または私のアプローチは完全に欠陥がありますか?
ESが一般にトップレベルのアーキテクチャに適さない理由(「アンチパターン」はもはや本当の意味はありません)は、複雑であるためです。簡潔でシンプル。
ESシステムは、RDBMSを基盤とする従来のシステムよりも概念化および開発が進んでいます。それについて考えてください。基本的に、アプリケーションに別の下位層(新しい「真実」)を追加し、その層をドメインに向かって「投影」するために必要なすべての配管を追加します。これは簡単なことではありません。データの制約、型チェック、および正規化に関してRDBMSが提供する多くの組み込みの利点を失う可能性があるだけでなく(イベントストアは通常、もう少し自由形式です)、可能なことなどを考慮する必要があります。一部の動作を根本的に変更する必要があるとわかったときに、将来の変更(バージョン管理)とイベントストアを「遡及的に」変更することの頭痛(私はこれを約束しますwill重要なシステムで発生します)。全体として見ると、ESは理解しにくく、管理しにくく、変更するのが難しいシステムを提示します(これは論点のように思えるかもしれませんが、適切に設計された従来のDDDシステムは変更が簡単です。それが全体のポイントです。 DDDの正しいですか?).
コインの反対側では、ESのほとんどのメリットは本質的に高レベルです(アプリケーションに別のレイヤーを導入しても、開発者にはメリットがありません)。最大の利点の1つは、ESシステムの拡張が容易であることです。個別の読み取り/書き込みモデルを備えた単一の追加専用ストアは、簡単にスケーリングできます。さらに、@ Ewanが言及したように、ドメインは単なるイベントストアのプロジェクションであるため(つまり、別のレイヤーを追加したため)、ESシステムはデータのさまざまなプロジェクションを簡単に作成する機能を提供します(新しいコマンドモデル)たとえば、DBスキーマを変更しなくても出現できます)。これは、データウェアハウジング/分析に役立ちますが、アプリケーションの将来的な保証にも役立ちます。
上記を念頭に置くと、ESシステムの利点は、その欠点と直行することが明確にわかります。高レベルの利点と低レベルの欠点です。これは、他のほとんどのアーキテクチャと直接対照的です。DDDは、スケーリングなどの困難を犠牲にして、開発と変更が簡単なシステムを作成することです。これは、ソフトウェアシステムが進化する傾向があるため、一般にソフトウェアシステムのより良いトレードオフです。時間が経つにつれ、ハードウェアは安価になり、ほとんどのアプリケーションは大規模なスケール/スループットを必要としません。
したがって、ESは、必要に応じて適用して、アプリケーション全体に盲目的に適用するのではなく、特定の問題/ドメインを解決する必要があります(ペットプロジェクトは免除されます)。
編集-コンテキスト間での「共有」イベントに関する質問について。各コンテキストは、変更を「所有」する必要があります。あるコンテキストで変更を加えて、別のコンテキストで直接変更を作成したくない場合。そうすることでそれらを結合し、そもそも2つのコンテキストを作成するという目的全体を無効にします。これは、2つの集計がRDBMSの同じフィールドに依存しているのと似ています。イベントストリームからのさまざまなモデルの再構築に関して、概要を説明するメリットを誤解していると思います。これはコマンドモデルには適用されません。イベントストリームごとに1つのコマンドモデルのみを使用できます。ビジネスルールを選択的に適用することはできません。そのため、どのシステムでも複数の読み取りモデルが可能です。
具体的には、EmailChanged
イベントが複数のコンテキストに関連している「理由」を自問してください。コンテキストを適切に分割していない可能性がありますか?組織の境界を越えてコンテキストを作成したようです。これはしばしば問題を引き起こします。これはトピックの短い議論です:
http://udidahan.com/2016/02/19/ask-udi-two-services-operating-on-the-same-entity/
エンティティと境界のあるコンテキストは多くの場合「発見」され、ビジネスの全体的な知識に基づいて決定されるのではないことを理解することが重要です。行動別モデル!
はい、最初は多少の痛みがありますが、UN-SOLIDモノリスがますます複雑になるにつれて、それを維持することで耐えられる累積的な痛みの一部ではありません。
CQRSとイベントソーシングは、重要なビジネスモデルの最も自然な実装です。毎日あなたの周りで起こるすべてを考えてください。トリガー(コマンド)なしでは何も始まらず、すべてが一連のイベントにつながります。ドメインモデルがクラスとリレーションシップのみで構成されているという概念は、データベースの永続性が未熟だった90年代の遺物です。
エンティティ、関係、集計ルート、値オブジェクト、コマンド、イベントのモデルを作成すると、次のことが起こります。
ワークロードが本来あるべき場所に分散されるため、単一責任が大きくなります。 (MVCの大きな肥大したコントローラーはだれでも:-)
バグのほぼ半分は、オブジェクトが期待された状態になっていないことが原因です。イベントソーシングはマンモスクラスを分割し、不変性をもたらすため、バグが少なくなります。
ある程度まともなワークフローを無料で利用できます。
ESシステムは概念化するのがより難しくなります
逆に、複雑なモデルの方が直感的です。
組み込みのメリットの多くを失うだけでなく、
あなたはそれらを取り除きたいのですが、彼らはあなたをコマンド側に引き留めています。彼らはまだクエリ側のあなたの友達です。
ドメインは単なるイベントストアの投影なので
イベントストアISドメインモデル。時間の経過とともに広がります。投影はビューモデルであり、クライアントに提示する非正規化データセットです。
あなたのアプローチには欠陥があります。
「販売コンテキスト」のビジネスルールを検討する
お客様がメールアドレスを変更した場合、10ポンドがクレジットされます
「セールスコンテキスト」のお客様は、Eメールが設定されたときにこのクレジットを適用し、EmailChangedイベントから正しく再構成します
ただし、「アカウントコンテキスト」の顧客はEmailChangedイベントを無視しています。それがプログラムされたとき、£10のルールは発明されていませんでした。そのため、アカウントアプリケーションで表示すると、顧客の残高は変更されず、正しくありません。
イベントから2つの異なるオブジェクトを生成することにより、まさにそれを実行します。同じ顧客の2つの「ビュー」がなく、2つの代替ユニバースの顧客があります。ビジネスルールのサブセットのみが存在する場合と同じように見えます。
編集-コメントのディスカッションの要約
あなたの見解では、イベントはオブジェクトに適用されたときに1つのことだけを行い、プロパティをイベントに格納された値に更新するべきです。
何かが複数のことを行う場合、それはコマンドであり、複数のイベントを生成する可能性があります。つまり、EmailChanged、AccountIncremented
私の見解では、これはイベントソーシングの大きなチャンクを逃している、つまり、イベントをモデルに適用する関数は好きなものにできるということです。 EmailChangedイベントが顧客に適用され、ドメイン境界の挑戦的なアカウントの例は別として、次のようにすることができます。
これらはすべてCustomerオブジェクトに対する内部変更です。新しいイベントは生成されません。生成された場合、問題が発生します。
イベントを無視するアプローチの欠点は、イベントがドメインにバインドされており、クロスドメインの影響を与えることができないと想定していることです。
はい、優れた設計は、電子メールアドレスを変更するとお客様のアカウントにクレジットが付与される場合、shouldがExternalコマンド例のようにアカウントドメインに渡されるAccountCreditイベント。
しかし、それから私は明白な例を選びました。たとえば、InvalidEmailフラグが設定されている場合、追加の不正チェックが行われている可能性があります。