明日から使えるDDDのためのユースケース駆動開発（ICONIXプロセス）

## この記事について

この記事は2020年3月30日に [BPStudy#151〜オブジェクト指向、モデリング、設計 LT大会[リモート開催]](https://bpstudy.connpass.com/event/170610/)という勉強会で[DDD時代に考えたいICONIXプロセス](https://speakerdeck.com/hirodragon112/iconix-in-ddd)というスライドを発表させて頂いたのですが、発表時間の都合上説明できなかった部分をもう一歩踏み込んで具体的なやり方を紹介する為にまとめたものです。
スライドをご覧になって頂いた上で読んで頂くとより前後関係がわかりやすくなりますが、スライドを見ていなくてもこの記事から読んで頂いても問題ありません。

https://speakerdeck.com/hirodragon112/iconix-in-ddd

## 序
みなさんDDDは好きですか？
筆者は大好きです。
DDDとは簡潔に説明すると**「ドメインに詳しい人と一緒に育てたモデルをそのままコードに落としむ」**という設計手法です。
モデルとコードが対応しているからモデルの育成と共にコードを育てられる。そしてそのモデルはドメインに詳しい人と共に育てる。
凄く良さそうですね！

ですが、そんなDDDですが一番重要と言われながらもあまり語られていないもの、一番難しそうなのに情報が少ないものがありませんか？
そう。**モデリングのやり方**です。
モデルをコードに落とし込むと言っている以上はここを解決できないとDDDはスタートする事すらできません。

本稿ではそのモデリングの手法としてICONIXプロセスを紹介したいと思います。
具体的にどうモデリングすれば良いの？とお悩みの方の参考になれば幸いです。

## ICONIXプロセスとは？

### ユースケース駆動開発実践ガイド
ICONIXプロセスは「ユースケース駆動開発実践ガイド」（以下UCDD本）という書籍にて説明されているユースケースからモデリング、実装、テストまで開発の一連の流れのやり方を説明したプロセスです。
理論の説明から演習までついている至れり尽くせりの書籍ですが、その分中々ぶ厚くて心がお折られやすいので注意が必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/0ae11326-22f1-9ac0-a31a-de2177f6f108.png)

### ICONIXプロセスの価値
ICONIXプロセスを端的に説明すると「ユースケースを実装に変換する為のフレームワーク」です。
ユースケースは本質的である反面システムを作成するには曖昧で不明瞭です。
ICONIXプロセスはそのギャップを埋めるための手法と言っても良いと思います。

### 本稿で紹介する範囲

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/b057f987-07ae-f19c-84be-61cad28ac138.png)


本稿で紹介するのはそのICONIXプロセスの一部となります。（画像の赤枠部分）
スライドにも記載がありますがICONIXプロセスを取り入れながらDDDに繋げていきたいと思います。
**なぜICONIXを使うの？という部分などに関してはスライドをご覧ください。**


## Step. 1 要求定義



### ドメインモデリング
最初のステップはドメインモデリングです。
ここでは「ドメインモデル」という言葉の意味に注意してください。
DDDの文脈ではある程度完成されたドメインモデル図を思い浮かべる方もいるかもしれません。
ICONIXプロセスでは違います。簡単に説明するとドメインモデルとはシステム化する対象の**用語集**です。
ですが、単なる用語集よりも強力です。オブジェクトモデルとして視覚化され関連についても表現します。

このドメインモデル（用語集）を作成する事は凄く重要です。
これから作成する各モデルたちは全てこの用語集に登場する言葉のみで作成していくからです。
これはDDDで言うユビキタス言語に相当すると考えても大丈夫です。


> ドメインモデルは皆とのやり取りの中から生みだされ、成長していくモノです。プロジェクトの中で洗練そして更新されるため、ドメインモデルには常に問題領域に対する現在の理解が表現されます。

ドメインモデル作成に限らずですがICONIXプロセスを実践する上で重要な事が一つあります。
**それは時間を区切って実施する（タイムボックス）**事です。
いきなり完璧なものを作る必要はありません。それは大概の場合時間ばかりかかって成果は伴わないでしょう。
イテレーティブに洗練していくイメージで実施してください。


本稿ではお題として以下のような要求がある勤怠管理システムをモデリングをしていく事にします。
（架空の要求なので実際にはもっとあるはずですが）
お題はtwitterで頂きました。ありがとうございました！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">勤怠打刻システム<br><br>とかどうです？<br><br>みんなよく知ってる<br>スコープによりでかくも小さくもでき、<br>そこそこのムズさ<br>参考ソフトたくさん</p>&mdash; 山崎遼介 / software enginner (@moaieee) <a href="https://twitter.com/moaieee/status/1257903412785471489?ref_src=twsrc%5Etfw">May 6, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


**このシステムへの要求**

- システムには社員アカウントの登録ができなくてはいけない
- システムは勤怠を打刻できなくてはいけない
- 勤怠にはコメントを入力できなくてはいけない
- 管理者は一般ユーザーの勤怠を閲覧できなくてはいけない
- 管理者は打刻の修正ができなくてはいけない
- 一般ユーザーは打刻の修正ができてはいけない
- ユーザーは有給の申請ができなくてはいけない
    - その際上長の承認をとらなくては有給は認定されない
    - 有給には残日数がありそれを越えた申請をする事ができてはいけない
- 管理者は勤怠一覧をcsvでダウンロードできなくてはいけない

さっそく要求を基にドメインモデルを作成してみましょう。

まずは要求に登場する名詞（と名詞句）をそのまま書き出してみました。

- 勤怠
- コメント
- 勤怠一覧
- 有給
- 残日数
- 承認
- csv
- 社員アカウント
- 上長
- 管理者
- 一般ユーザー


要求の一つ一つはシステムを利用する人がやりたい事が表現されているのですが、こうして書き出してみると似たようなものが含まれていそうです。
同じ概念を表す言葉であればこのタイミングで除去してしまいましょう。
また、オブジェクトモデルとして表すものとアクターとなるものも混在しているので注意してください。（今回で言うと管理者、一般ユーザー等はアクターとなります）

重複したものや曖昧な単語を修正して以下の候補に絞ります。

- 勤怠
- 勤怠一覧
- 勤怠csv
- コメント
- 有給
- 承認
- 有給残日数
- 管理ユーザー
- 一般ユーザー

それぞれの関連を関連線と集約線を使用して図にしてみた仮のドメインモデルが完成しました。

![ドメインモデル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/65aecf48-3acd-7ba2-9004-b74751d9157e.png)



関連や登場している概念が全て正しいかはこの段階で深くは気にしない方がいいです。
いきなり完璧を目指すと時間が膨大に必要となってしまいます。


まずは最初のドメインモデルを作成しチームで話し合いながら洗練していきましょう。
例えば「承認」というドメインモデルは名詞のように見えていただけで動詞だった事に気づいて除去されるかもしれません。
また、集約だけでなく汎化も意識していきます。
（本稿では洗練する工程は割愛します）

最初のドメインモデルを洗練した結果以下の図のように変化しました。

![ドメインモデル2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/f89f9c5c-075a-f412-cb5c-057211d592f7.png)

これで最初のドメインモデルが完成しました。
このドメインモデル（用語集）に存在する言葉を使用して以降のモデリングを行っていきます。

最後にUCDD本に記載されているドメインモデリングガイドライントップ10を紹介しておきます
> 10 現実世界（問題領域）のオブジェクトに焦点をあわせなさい。
> 9 オブジェクト同士の関係を表現するため、汎化(is-a)関係および集約(has-a)関係を利用しなさい。
> 8 最初のドメインモデリングにかける時間は2時間に限定しなさい。
> 7 問題領域中の主要な概念を中心にクラスを構成しなさい。
> 6 ドメインモデルをデータモデルと勘違いしてはいけません。
> 5 オブジェクト（単一のインスタンスを表現する存在）とデータベースのテーブル（モノの集合を含む存在）とを混同してはいけません。
> 4 ドメインモデルをプロジェクトの用語集として使いなさい。
> 3 名前が曖昧になることを避けるため、ユースケースを書く前にドメインモデルを書きなさい。
> 2 最終的なクラス図が、ドメインモデルと正確に合致する事を期待してはいけません。しかしこの2つは、何らかの形で相似の関係にあるはずです。
> 1 ドメインモデルには、画面やその他のGUI固有の部品クラスを配置してはいけません。


### ユースケースモデリング

最初のドメインモデルができたので、いよいよユースケースを書く事ができるようになりました。
さっそく書いていきましょう。
今回はユースケースを1つだけピックアップして進めていきたいと思います。

ユースケースとはこのシステムの使用者（アクター）がこのシステムを使用して何ができるのか？を表したものです。
ふるまい要求のモデリングと考えて良いでしょう。

ユースケースモデリングは大きく二つの工程を組み合わせたものとなります。
1. ユースケース図の作成
2. ユースケース記述の作成


特に2. のユースケース記述は重要です。たまにユースケース図だけを書いているプロジェクトを見かけますが、せっかくユースケース図を書いたのにユースケース記述を書かないのは非常にもったいないです。ユースケース記述はあいまいで抽象的なユースケースをシステムとの対話プロセスに落とし込む重要なステップです。ユースケース図を書く事よりもユースケース記述を書くことの方が重要です。この工程を設計や実装の前に行う事によりのちの手戻り工数を未然に防げるでしょう。ユースケース記述を記述する際のポイントとしては、基本コース以外に代替コースを記述する事を忘れないようにしましょう。


まずユースケース図を作成してみました。

![ユースケース図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/9255874c-d1bd-25f0-0591-cd5c6661931e.png)

ユースケース図を書く際に重要なのは、`precedes`, `extends`, `includes`, `invokes`, `generalization` と言った**関係の定義を正確に書こうと頑張らないでください**。
それは些細な事で時間を使う価値はありません。
重要なのは**何が起きているか**。その一点に注目した方が良いです。
つまり、叙述的にアクターがシステムに対して何を行うのかを明確にしていきましょう。

次にユースケース記述を記載していきます。
**ユースケース記述とはユーザーとシステムの対話です。**ユースケース図でモデリングされた価値が具体的にどのようなシステムとのやり取りを経て実現されるべきかを書いたプロセスのようなものです。通常想定している操作に加えて、使用ケースの少ない操作や操作を誤ってしまった場合にもどうようにシステムが振舞っていくかを記述していきます。
実際コードを書く際に先にコメントで手順を書く方もいらっしゃると思うのですが、それに近いイメージとなるでしょう。

ここでは例として「有給申請を承認する」というユースケースに対するユースケース記述を書いてみました。

|項目|内容|
| --- | --- |
|ユースケース|有給申請を承認する|
|アクター|管理ユーザー|
|事前条件|有給申請一覧画面が表示されている事<br>有給申請が存在する事|
|基本コース|管理ユーザーは有給申請一覧画面から承認したい申請の詳細ボタンをクリックする。<br>システムは有給申請詳細を表示する。<br>管理ユーザーは有給申請の承認ボタンをクリックする。<br>システムは申請した一般ユーザーの有給残日数が申請された日数より多い場合有給申請を承認する。<br>有給申請が承認された事を申請した一般ユーザーにメールで通知する。|
|代替コース|有給残日数が足りなかった場合 : 有給残日数が足りない旨とともに残日数を表示する|
※ シンプルに記載してます。詳細の書き方を知りたい方は調べてみてください。


上述しましたが、ユースケースモデリングはドメインモデルを使用して作成します。
ユースケースがドメインモデルのオブジェクトと紐づいていないとそもそもユースケースからオブジェクトモデルを作成できないからです。
つまりユースケース駆動でもなんでもなくなってしまいます。
**重要な事なので繰り返しますが、ユースケースがドメインモデルのオブジェクトと紐づいている事が凄く重要です。**
また、代替コースもこの時点で分析しておく事で未然に考慮不足を防ぐことができます。


※ ユースケースモデリングをしながら新たにドメインモデルの更新も行われています。更新されたドメインモデルは後ほど紹介します。


最後にUCDD本に記載されているユースケースモデリングガイドライントップ10を紹介しておきます
> 10 2段落ルールに従いなさい。
> 9 アクターとユースケース図を使ってユースケースを組織化しなさい。
> 8 ユースケースは叙述的に書きなさい。
> 7 イベントとその等々のながれとしてユースケースを書き、ユーザーとシステムの対話の両側を記述しなさい。
> 6 GUIプロトタイプや画面モックアップを使いなさい
> 5 ユースケースは実行時の振る舞いの仕様であるということを忘れないように。
> 4 オブジェクトモデルの言葉を使ってユースケースを書きなさい。
> 3 「名詞 - 名詞 - 動詞」という分の構造に従ってユースケースを書きなさい。
> 2 ドメインクラスの名前を使いなさい。
> 1 （画面のような）バウンダリクラスの名前を使いなさい。

### 要求レビュー

2つのモデリングを終えた所で最後に要求定義のレビューを行います。
この時点でレビューを行いドメインモデリングやユースケースモデリングに違和感がないかを確認しましょう。
本稿ではUCDD本のガイドライントップ10を紹介するにとどめたいと思います。
（今回の先に示した例も正直全部は満たせてないですね！架空の記事なので許してください！ただ、個人的にはこの辺も完璧でなくても良いと思ってます）

> 10 問題領域におけるもっとも重要な概念（現実のオブジェクトなど）の少なくとも80%が、エンドユーザーにも理解できるように技術的な言葉を使わずにドメインモデルに記述されていることを確認しなさい。
> 9 ドメインモデルが、ドメインオブジェクト間のis-a（汎化）関係has-a（集約）関係を示している事を確認しなさい。
> 8 ユースケースの基本コースと代替コースの双方を、叙述的に記述していることを確認しなさい。
> 7 機能要求のリスト（「～しなければならない」という記述」）がある場合、それが叙述的なユースケース記述中に紛れ込んでたり、テキストを「ぐちゃぐちゃに」していたりといったことがないことを確認しなさい。
> 6 ユースケースがパッケージによって組織化され、かつ各パッケージには最低ひとつのユースケース図が含まれていることを確認しなさい。
> 5 ユースケースがオブジェクトモデルの用語で記述されていることを確認しなさい。
> 4 ユースケースはユーザーインターフェースの用語で記述しなさい。
> 3 ユースケース記述にはGUI紙芝居、線図、画面モックアップあるいはGUIプロトタイプを付随させなさい。
> 2 ユースケース、ドメインモデル、画面モックアップ/GUIプロトタイプを、エンドユーザー、ステークホルダー、販売担当者、技術担当メンバーと一緒にレビューしなさい。
> 1 レビューを「より良いユースケースのための8つの簡単なステップ」に沿って構成しなさい。[^1]

Step1. 要求定義はこれで終わりです。
要求一覧からドメインモデルとユースケースモデルを作成して紐づけました。
このようにICONIXプロセスでは静的モデルと動的モデルを紐づけながら進めていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/3e067b8a-022d-a9ad-fcb5-68c3108c889f.png)





## Step2. 分析/予備レビュー
この工程では主にロバストネス分析、ドメインモデル更新、論理名付け、ユースケースの修正を行い、詳細設計へと進む為にモデルを洗練していきます。
予備設計と呼ばれる工程となります。

### ロバストネス分析
まずはUCDD本より引用
> ユースケースから詳細設計（とコード）を作成するには、ユースケースをオブジェクトに関連付ける必要があります。

次の工程の**ロバストネス分析はICONIXプロセスの中心と言える工程です**。
ここまで要求定義で作成したドメインモデルとユースケースモデルはまだシステムに落とし込む事まではできない自然言語中心のモデルです。
ロバストネス分析を行う事により、自然言語で作成されたユースケースがオブジェクトへと関連付けられていきます。

ユースケースはユーザーがシステムに対して何ができるか？という曖昧で抽象的なものでした。
それを具体的なオブジェクトとして紐づける事でユースケース（とそれを構成するドメインモデル）がオブジェクトへとマッピングされていきます。
また、このロバストネス分析は紐づけだけの為に行うものではありません。
具体的に紐づけを行っている最中にここまでで足りていなかった概念に気づく事もあるでしょう。
その際はかかさずドメインモデルを更新して洗練していきましょう。

ロバストネス図は3つのオブジェクトを使用して作成します。

バウンダリ : システムとシステム外部の境界を示すインターフェース
エンティティ : ドメインモデル上のクラス
コントローラー : バウンダリとエンティティの間の「接着剤」

バウンダリが画面やCLI、エンティティが名詞、コントローラーが動詞と覚えるとわかりやすいと思います。

![アイコン.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/7e1dfbb1-a7d8-e923-c67f-dbb5508c00a3.png)

ロバストネス図は以下の簡単なルールに沿って作成します。

- 名詞は動詞とつなぐことができる（逆もまた同様）
- 名詞を他の名詞につなぐことはできない。
- 動詞は他の動詞とつなぐことができる。

ユースケース記述のをオブジェクトとして表したものです。
つまり、ユースケース記述とロバストネス図は表現が違うだけで同じものを表しているという事になります。


実際に作成してみた図がこちらです。

![有給申請を承認する.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/5df30b06-8b0d-b630-9639-5a4ad3388ba2.png)


ロバストネス分析で大切なのはユースケース記述をオブジェクトとして関連付けていっているかという点になります。
また、ここで出てくる名詞（エンティティ）はドメインモデルとして作成したオブジェクトでなくてはいけません。
ユースケース記述がちゃんとドメインモデルで作成されていればきっと自然とそうなっているでしょう。

最後にUCDD本に記載されているロバストネス分析ガイドライントップ10を紹介しておきます
> 10 ユースケース記述をロバストネス図に直接貼り付けなさい。
> 9 ドメインモデルからエンティティクラスを取り出し、不足しているものがあれば追加しなさい。
> 8 ロバストネス図の作成中も、ユースケース記述を書きなおして明確にする事があります。
> 7 画面単位にバウンダリオブジェクトを作成し、明確な画面名を付けてください。
> 6 コントローラは、本物のコントロールオブジェクトになることがあるかもしれないということを忘れないでください。これらは通常、論理的なソフトウェア機能にすぎません。
> 5 ロバストネス図上の矢印の方向について気にしてはいけません。
> 4 親のユースケースから起動されるのであれば、ユースケースをロバストネス図上にドラッグしてもかまいません。
> 3 ロバストネス図はユースケースに対する予備的な概念設計を示しています。文字通りの詳細設計ではありません。
> 2 一般的に、ロバストネス図上のバウンダリオブジェクトとエンティティクラスはシーケンス図上のオブジェクトインスタンスとなります。一方、コントローラはシーケンス図上のメッセージとなります。
> 1 ロバストネス図はユースケースの「オブジェクトの絵」であるということを忘れないでください。その目的はユースケース記述とオブジェクトモデルの両方を強制的に洗練させることです。


### ドメインモデル更新

ただ、この図を見ると上記のドメインモデルに登場していないオブジェクトが存在しますね。
そうです。これらはロバストネス図を作成している際に見えてきたモデル達です。
「有給申請」と「有給申請リスト」を別の概念として登場させました。
メール送信の「メール」も追加されていますが、これはそもそも要求時点で存在していませんでした。
ユースケースモデリングをする過程で見つかった要求と概念となります。

こういった発見も貴重な発見となります。
そしてこれに合わせてドメインモデルも更新しましょう。

更新後のドメインモデル（ユースケースモデリングの際に更新された分も含めて反映されています）


![ドメインモデル_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/4e2cf099-a1ff-069e-23b6-6ba8dd76b770.png)

このように静的モデルと動的モデルをオブジェクトとして関連付けていき、同時に足りない概念の洗い出しが行えます。
また、同時にバウンダリに適切な名前を検討する作業もロバストネス分析の際に行います。

### 予備設計レビュー

Step1 の最後に要求レビューを行ったようにStep2でも最後にレビューを行います。

> 予備設計レビューのセッションでは、ロバストネス図、ドメインモデル図、およびユースケース記述の辻褄がすべて合っていることを確認します。

本稿ではUCDD本の予備設計レビューガイドラインのトップ10を紹介するに留めさせて頂きます。
> 10 ユースケースごとに、**ユースケース記述とロバストネス図が一致しているかどうかを**蛍光ペンを使って確認しなさい。
> 9 ロバストネス図上のすべてのエンティティが、更新後のドメインモデル上に確実に存在するようにしなさい。
> 8 エンティティクラスと画面の間で、データの流れを確実に追跡できるようにしなさい。
> 7 **代替コースが漏れていないか**、そして見つけ出したすべての代替コースに対する振る舞いが記述されているかを確認しなさい。
> 6 各ユースケースが、確実にユーザーとシステムの間の対話の両側をカバーするようにしなさい。
> 5 ロバストネス図の構文ルールを破っていないことを確認しなさい。
> 4 技術者以外（顧客やマーケティングチームなど）と技術者（プログラマ）の双方が確実にレビューに参加するようにしなさい。
> 3 ユースケースがオブジェクトモデルとGUIの用語で記述されていることを確認しなさい。
> 2 ロバストネス図（と対応するユースケース記述）でシーケンス図上に表現するようなレベルの詳細をしめそうとしていないことを確認しなさい（詳細設計にはまだ手を付けていません）
> 1 より良い予備設計のための「6つの簡単な手順」に従いなさい[^2]


Step2. 分析/予備レビューはこれで終わりです。
下図の赤枠の部分に該当しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235958/431b966e-ab68-5bba-3163-4b85a0b5018c.png)


## そしてDDDの戦術的設計へ

ICONIXプロセスはここからさらにテクニカルアーキテクチャを経て、詳細設計に突入していきます。
ロバストネス図を基にシーケンス図の作成等を行っていくのです。

ですが、本稿で紹介したいのはここまでとなります。
なぜなら本稿ではDDDの戦略設計を補助する為のプロセスとしてICONIXプロセスの一部を実施する事を目的としているからです。
DDDの戦略はまだ他にもあります。戦術設計の要素も取り入れていません。
ここからはDDDの工程に戻って、手に入れたドメインモデルからEntityやValueObjectを洗い出したりする必要があるでしょう。
集約設計も行わなくてはいけません。

ですが、それはもう難しいものではなくなっているはずです。
なぜならここまでの工程で、要求と密接に紐づいたユースケースとドメインモデルを手に入れました。
ここで手に入れたドメインモデルの多くはEntityへとなるでしょう。
ICONIXプロセスのドメインモデリングでは小さすぎて記述しなかったValueObjectを足していく作業が中心となると思います。
また、関連が記載されたドメインモデル達は集約設計をスムーズにしてくれるはずです。
またユースケースモデルはそのままユースケースクラスへと変化していくはずです。


## 了

今回はDDDの戦略設計に欠かせないモデリングの手法としてICONIXプロセスを導入する方法を紹介しました。
ICONIXプロセスはユースケースを中心に据えてモデリングを行います。
それによって完成するシステムはユーザーの活動に沿ったものになる可能性が高いと考えています。

もちろんDDDをやる上でICONIXプロセスは必須ではありません。
ですが、もしモデリングのやり方にもし迷いが方がいらっしゃいましたら試してみるのも良いかと思います。

この記事がみなさんのモデリングの一助になれば幸いです。

一気に書いたのでおかしな点があるかもしれません。その際は編集リクエストを頂けるとありがたいです。
また、twitter [@hirodragon112](https://twitter.com/hirodragon112) でやってますのでご質問等ございましたらそちらへお願いいたします！





[^1]: より良いユースケースのための8つの簡単なステップはUCDD本の要求レビューの項で紹介されていますので詳細は書籍をご確認下さい。
[^2]: より良い予備設計のための「6つの簡単な手順」はUCDD本の要求レビューの項で紹介されていますので詳細は書籍をご確認下さい。