一回読み終わって、頭の中を整理してるとこ。
実践ドメイン駆動設計 |
「集約 = トランザクション整合性の境界」
というルールがある。
つまり、複数の集約を1つのトランザクションで変更してはいけない。ということ。
確かにトランザクションを切り離して考えることができると開放感がある。
集約Aと集約Bを別の環境で保持する、というようなこともできそう。
AとBを同じトランザクション内で処理しなくていいんだから。
「小さな集約を設計する」
というルールもある。
「トランザクション内で変更するのは1つの集約だけ」というルールが良さそうなのはなんとなく分かるんだけど。
いざ設計してみようかなと思うとつまづく。
Aの状態がclosedになったときに、Bの状態もclosedにする。っていうような関連があったときに。
AがclosedなのにBがopenしてる状態はありえない。って考えると。
AとBを同じトランザクションで触りたいなぁ・・・ってなって。
じゃあAとBを合わせて1つの集約にするかぁ。って。
(∩´∀`)∩ワーイ秩序が保たれた!
とか、そんなことをやっちゃうと、すぐに集約が大きくなってしまうんだけど。
これって元も子もない。結局、不自由だ。
なので、集約はできるだけ小さくしましょう。という感じなのである。
それってつまり、トランザクションの境界をできるだけ小さくしましょう。ということか。ふむ。
じゃあ集約どうしの整合性はどうやって保つの?
というところで「結果整合性」が出てくる。
「境界の外部では結果整合性を用いる」というルール。
結果整合性っていうのは、しばらくの間不整合がある状態があっても、最終的に整合性がとれた状態になるならOKじゃろ。
というようなイメージ。
そして、その整合性を運ぶ役割を持っているものの一つとしてドメインイベントがあげられている。
Aの状態がclosedになった!→AClosedイベント送信→AClosedイベント受信→Bの状態をclosedにする!
AとBの整合性
ここで僕が勘違いしていた。
「トランザクション内でAとAClosedイベントを同時に触ってはいけない」と思ってしまってたのだ。
そんなことをすると、Aとイベントの整合性が保たれないので。困った話に、頭のなかが展開してしまってた。
Aの状態がclosedになった、と、AClosedイベント送信、はトランザクション内で触って良さそう。
これは「イベント」が、アプリケーションサービスの管轄に置かれるイメージなのかな?よく分かってない。
同様に、受信側もBの状態変化と同じトランザクションで管理する。
ということで、整合性を保つことができそう。
必ず一度送信されることを保証するために、送信側のイベント送信トラッカーを使って
受信側は、メッセージングサービスからの二重受信に対応するため、受信側のイベント受信トラッカーを使って
整合性を保ちそうだなと思った。
疑問とか
- ローカルでのイベント送受信の場合も、メッセージングインフラ使う?
- イベントストアにイベント発行するのと同時にメッセージ送信しても良さそうかな?考えてみる。
- イベントストアからイベントを発行するときに、イベントのサブスクライバが複数ある場合は、どうやって知ろうか?
- イベントの到着順が前後するときには、プロパティ変更トラッカーみたいなのを使ってたけど、その辺りもう一度読んでおこう。
あと、EvansのDDDの集約をもう一回読もうかな。
とはいえ
送金のトランザクションを結果整合性を使ってやるのはあまり想像できていない。
イベントで運んでる途中の状態って、嫌な感じがする。
けど、全部の口座を1つの集約にまとめるなんて無理だし。どんな風にやればよいかな?