8

イベントソーシングを使用して、イベントのストリームから集計を構築しています。A1 と A2 の 2 つの集計があります。A1 は、A2 を作成するためのテンプレートとして使用されます。A1のサイズはかなり大きいです。イベント ソーシングの基本的な考え方は、アプリケーションの状態に対するすべての変更がイベント オブジェクトに確実に取り込まれるようにすることです。したがって、A2 を保存するには、最初のイベントに多くの情報を保存する必要があります。

この状況は一般的ですか、それともテンプレートから作成するのは良い考えではありませんか? それを解決するためのより良い方法はありますか?

4

2 に答える 2

4

集計とイベントのより具体的な例を投稿すると、さらに役立ちます。通常、状況に応じて、より詳細なイベントを作成できます。次に、コマンドとイベントの間に 1 対 1 の関係を持つ代わりに、CQRS 理論と完全に一致する 1 対 N の関係を持つことになります。

例を挙げると:

CreateInvoice : Command
- InvoiceId
- Customer (10 fields)
- Address (5 more fields)
- InvoceLine[] (where each InvoiceLine also have 10 fields or so)
- Rest of 100 or so fields

InvoiceCreated : Event
- InvoiceId
- Customer (10 fields)
- Address (5 more fields)
- InvoceLine[] (where each InvoiceLine also have 10 fields or so)
- Total
- Rest of 100 or so fields

そしてコマンドハンドラーで:

void Handle(CreateInvoce cmd)
{
  var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address, cmd.Lines ....)
  uow.Register(invoice);
}

InvoceCreated イベントが 1 つだけ発生します。

代わりに、より詳細なイベントを作成できます。

InvoiceCreated : Event
- InvoiceId
- Customer
- Address

InvoiceLineAdded
- InvoiceId
- Item
- Vat
- Subtotal
- Etc

次に、コマンド ハンドラーで次のようにします。

void Handle(CreateInvoce cmd)
{
  var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address);

  foreach (var line in cmd.Lines)
  {
      invoice.AddLine(line.Item, line.Quantity, line.Price, ...);
  }

  uow.Register(invoice);
}

ここで、ctor は InvoiceCreated イベントを発生させ、AddLine メソッドは InvoiceLineAdded イベントを発生させます。その後、更新で使用できる InvoiceLineChanged/InvoiceLineRemoved などのイベントを作成できます。

これにより、より粗粒度のコマンドを発行できるようにしながら、より粒度の細かいイベントを作成できます。

ユーザー/システムの PoV からのアトミック アクションを表す場合、大きなコマンドは問題ありません。

PS 集約をテンプレートとして使用することについては、私はそれを気にせず、代わりに中間状態を収集するためのアキュムレータとして機能するデータ構造を作成します。その後、単純にシリアライズ/デシリアライズできます。テンプレートの入力の背後に動作がない場合は、集計はまったく必要ありません。これは、後で集計を作成してビジネス ルールを実行するために使用される単なるデータの塊です。おそらく、この「テンプレート」オブジェクトを使用して、セッション状態のように、複数のリクエスト間でユーザーが入力した状態を保存していますよね;)?

それが役立つことを願っています。

于 2012-06-09T13:23:52.013 に答える