集計とイベントのより具体的な例を投稿すると、さらに役立ちます。通常、状況に応じて、より詳細なイベントを作成できます。次に、コマンドとイベントの間に 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 集約をテンプレートとして使用することについては、私はそれを気にせず、代わりに中間状態を収集するためのアキュムレータとして機能するデータ構造を作成します。その後、単純にシリアライズ/デシリアライズできます。テンプレートの入力の背後に動作がない場合は、集計はまったく必要ありません。これは、後で集計を作成してビジネス ルールを実行するために使用される単なるデータの塊です。おそらく、この「テンプレート」オブジェクトを使用して、セッション状態のように、複数のリクエスト間でユーザーが入力した状態を保存していますよね;)?
それが役立つことを願っています。