Event Stormingでの集約の導き出し方

本記事は、 [DDD\-Community\-Jp Advent Calendar 2020](https://qiita.com/advent-calendar/2020/dddcj)の1日目です。


# はじめに

DDD-Community-JP(以下、DDDCJ)内では架空の会議室予約のドメインを考え、C#で実装する[モデリング会](https://twitter.com/search?q=%23ModelingKai&src=recent_search_click&f=live)を隔週ペースで行っています。

そこで実施したEvent Stormingというモデリング手法が、集約を探すのに便利そうだっていう意見があったので、そのお話を書いていこうと思います。

# Event Stormingとは？

- Alberto Brandolini 氏が提唱しているモデリング手法です
    - ぱっと見た感じ、ユーザーストーリーマッピングに近い感じですが、ユーザの行動にフォーカスするのではなく、ドメインエキスパートが気にするイベント（＝ドメインイベント）にフォーカスし、時系列に並べていきます。[^1]
[^1]: ドメインイベントとは、実践ドメイン駆動設計の8章で紹介されています。定義としては「ドメインエキスパートが気にかける、何らかの出来事」となっています。
    
- 実際のやり方は、モデリング会ではどんな感じにやったのかは、以下の @98lerr さんのの記事をご参照ください。
    - [EventStormingをやってみた話 \- Qiita](https://qiita.com/98lerr/items/9b1c50348dcaa925e1a5)

# 集約を見つけるのに使える

Event Stormingは、「ドメインエキスパートが気にしているイベントはどんなものがあるのか？」が起点となっていますが、これは集約を探していくのにも重宝します。

始めはワークショップの中で、イベントとそれに対応するコマンドを出していくことになります。
たとえば会議室の予約で考えたときに、「会議室を予約する」というコマンドに対して、「会議室を予約した」というイベントが起きます。
#### イベント（オレンジ）とコマンド（青）を出している状態
<img width="75%" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168063/9144410b-b9ee-b82a-eb2b-937b50cd3c93.png>

ではこのコマンドを受け取り、「会議室を予約した」というイベントを発行する集約はなんだろうと考えた時に、「予約」という集約が出てきそうです。[^2]
[^2]: 予約集約が予約するのって変では？　というツッコミもあると思います。予約したときに問題なく予約が生成できれば（不変条件が満たされていれば）、問題なく予約が生成ができたら、完了イベントを発行するといったのを今は想定しています

#### イベントとコマンドの間に集約（黄）を貼った状態
<img width="75%" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168063/001ee1ef-fca6-a916-d7db-f7e0a85c4355.png>

予約の変更や、予約のキャンセルも考えるとこんな感じになりそうです。


#### 他のイベントとコマンド、それに対応する集約を出した状態
<img width="70%" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168063/9c5f69f7-fb68-1016-6275-229504437fa9.png>

このときに、予約集約が持つべき振る舞いがコマンドから特定できてきます。

- 予約集約
    - 予約をする
    - 予約の変更をする
    - 予約をキャンセルする

予約集約が自身で予約したり、キャンセルしたりするのに怪しい部分を感じます。
もしかしたら予約という名前ではないのかもしれません。

こういった違和感を覚えるのも、前後にコマンドとイベントがあるからだと思います。
そして、そのイベントは**ユーザが気にしている出来事**から出てきているはずなので、そちらを拠り所として集約を考えていくことができます。

# 集約が持つルール、ロジックを考える

ここからは、Event Stormingでの正規のやり方から外れていきますが、
コマンドとイベントでの間にあるルールとロジックを考えておくと良いのではないか、という案です。

会議室を予約する時には、なんでもかんでも予約できるとは限らないはずです。
予約したいところが既に使用中だったりするでしょうし、1年先を予約されても困るので範囲を限定したいとか、そもそも使っていい時間帯が決まっているとか。

そういったビジネスルールやロジックを、集約の付箋の近くに置いておくと、いざ集約の境界内をモデリングするときの材料として考えることができそうです。

もちろん全てが集約のロジックになるかと考えると違うでしょうが、
少なくとも関連するものとして近くに置いておくと、ドメインエキスパートと一緒に議論するときにでも、わかりやすいのではないか、といった仮説です。[^3]
[^3]: 実際ビジネスサイドと話をする際には、例に出しているDesign LevelのEvent Stormingではなく、もっと抽象度の高いBig Picture、Process Modelingでやるべき話なのかもしれません

<img width=70% src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168063/b9cca65e-0d07-ef87-3cc2-93192e816402.png>


# 集約の境界内の構造のモデリングは別途必要

Event Stormingはあくまでイベントに着目し、その前後にどんなコマンドがあり、外部システム、アクター、リードモデルが出てくるかを、時系列に表したものです。
集約の境界内でどんな属性（値オブジェクトもしくは子エンティティ）を持たせるかは、別途考えていかなければいけないと思っています。

実際に考えるときは、予約の集約の内部にどんなものがあるかを付箋に書き出してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168063/dff4b312-3c00-1212-dd9e-2a9b4d3d795a.png)

# 境界づけられたコンテキストを導き出すことにも使える

Event Stormingで出したボードが、関心事が変わってくるのであれば、線を引いて境界づけられたコンテキストを分けていけたりします。

会議室の予約で言うと、会議室予約と、会議室を実際に使用するのは、別のコンテキストとして区切ってみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/168063/783a22e2-86a0-d991-4c99-e8f72e291a9d.png)

# まとめ

Event Stormingは、イベントやコマンド、集約やリードモデルといった単語から想像できると思いますが、イベントソーシングやCQRSなどを半ば前提としたモデリング手法だと思います。

ただ、そういった実装にする予定ではなくても、Event Stormingは集約を探求するのにかなり良い手法だと感じています。

# 参考資料

- [EventStorming](https://www.eventstorming.com/)
- [Design Level EventStorming · Nick Chamberlain](https://buildplease.com/pages/fpc-6/)