【10分で分かる】ドメインモデリングの進め方

本記事はダグ・ローゼンバーグ著の[ユースケース駆動開発実践ガイド](https://www.amazon.co.jp/%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-OOP-Foundations-%E3%83%80%E3%82%B0%E3%83%BB%E3%83%AD%E3%83%BC%E3%82%BC%E3%83%B3%E3%83%90%E3%83%BC%E3%82%B0/dp/4798114456)や、ネット上の人気記事を参考に書かせていただいています。


# 導入

## ドメインモデリングとは？

![image.png](http://www.plantuml.com/plantuml/png/SoWkIImgAStDuKfCBialKW2JN8dfgNab2e-RjZzkNlwukVbnyvJ7pPiVDsrutBJwSVEUnyqTK1LF-wSzRkfwrhdnSMFBqycDpsUlWqeysxpYsRHsBgYX-ReAqNWCY-N2AmlMZcaJOLr0RH1tn78vfEQb03q90000)

- プロジェクト用語集、プロジェクト内で利用される用語をまとめた「生きるている」辞書
- 初期段階で完璧なものを作ることは不可能で、繰り返し議論し固めていく

## 何故ドメインモデリングが重要なのか？

- プロジェクトメンバー全員に明確な用語で問題領域を確実に理解させることができる
- プロジェクトのスコープを定義し、ユースケース作成の基盤とも成る



##　作成のためのガイドライン

[ユースケース駆動開発実践ガイド](https://www.amazon.co.jp/%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-OOP-Foundations-%E3%83%80%E3%82%B0%E3%83%BB%E3%83%AD%E3%83%BC%E3%82%BC%E3%83%B3%E3%83%90%E3%83%BC%E3%82%B0/dp/4798114456)で紹介されている、ドメインモデル作成のためのガイドラインを紹介します

<details><summary>作成のためのガイドライン</summary><div>

1. **現実世界のオブジェクトに少テインを合わせなさい**
    1. ソフトウェアは変化しやすいが現実は変化しにくいので、より現実世界を意識することでモデルの要求の変化に強くする
1. **汎化・集約関係を使いなさい**
1. **最初のドメインモデリングにかける時間は2時間に限定しなさい**
    1. ドメインモデルとはそもそも不完全なもので、何が足りないかを「ユースケース図」「ロバストネス図」を作成するプロセスこそに意味がある
1. **問題領域の主要な概念を中心にクラスを構成しなさい**
1. **ドメインモデリングとデータモデルを勘違いしてはいけません**
    1. 似てる結果になることもあるが同じではない
    1. 良いクラスは比較的小さくまとまっているが、テーブルはその限りではない
1. **オブジェクトとデータベースのテーブルとを混同してはいけません**
1. **ドメインモデルをプロジェクトの用語集として使いなさい**
    1. 似た用語は必ず1つにまとめること。話す人によって意味が変わる用語も存在してはいけない。
1. **ユースケースを書く前にドメインモデルを書きなさい**
1. **最終的なクラス図が、ドメインモデルと正確に合致することを期待してはいけません**
    1. クラス図は詳細に仕上げていくが、ドメインモデルは意図的にシンプルに仕上げること
1. **ドメインモデルには画面やその他のGUI固有の部品クラスを配置してはいけません**
    1. 純粋にドメインモデルの問題領域の表現に注力すること 　
</div></details>

# 実践

## 1. 要求定義

ドメインモデル構築時にドメインクラスの抽出源として利用する情報源には、高い抽象度を持った要求が含まれています。
これらは「システムは〜しなければならない」「システムは〜すべきではない」という形式で記述されることが多いです。

では今回モデリングするシステムの要求を見ていきましょう。

<details><summary>システム要求</summary><div>

> 1. **ユーザー**は精算前に、**オンラインショッピングカート**に**書籍**を加えることができ
> なければなりません。
> 1. 同じように、ユーザーはショッピングカートから**品目**を取り出すことができなければなりません。
> 1. ユーザーは、あとで購入するつもりの書籍に対する**購入予定リスト**を利用できなければなりません。
> 1.配送前であれば、ユーザーは注文をキャンセルすることができなければなりません。
> 1. ユーザーは**クレジットカード**や**発注書**で支払うことができなければなりません。
> 1.ユーザーは書籍を返品できなければなりません。
> 1. システムが(名前、住所、クレジットカードといった)ユーザーの詳細情報を記録できるようにするため、ユーザーはログイン時に**顧客アカウント**を作成できなければなりません。
> 1. ユーザーはさまざまな**検索方法**(タイトル、著者、キーワード、カテゴリーなど)で書籍を検索し、そこから**書籍詳細**を見ることができなければなりません。
> 1. ユーザーは自分の好きな書籍に、レビューを投稿することができなければなりません。**レビューコメント**は書籍詳細に表示されなければなりません。レビューは**顧客評価**(1~5)を含み、**> 書籍一覧**で書籍のタイトルとともに表示されなければなりません。
> 1. スタッフは**編集者レビュー**を投稿することができなければなりません。また、それは書籍詳細ページに表示されなければなりません。

</div></details>



## 2. 用語抽出・整理

これらの要求から、強調された名刺や名詞句をリストにしていきます。

<details><summary>名刺・名詞句リスト</summary><div>

> アカウントリスト
> クレジットカード
> 購入予定リスト
> 顧客
> 顧客アカウント
> 顧客評価
> 書籍
> 書籍一覧
> 書籍詳細
> 書籍レビュー
> ショッピングカート
> 精算
> タイトル
> 注文
> 著者
> 発注書
> 販売者
> 品目
> 編集者レビュー
> ミニカタログ
> ユーザーアカウント
> レビューコメント

</div></details>


続いて抽出した名詞を整理していきます。

<details><summary>名刺・名詞句リスト整理</summary><div>

- 「顧客」「顧客アカウント」は同じように思えるかもしれないが、実際は異なる
    - 顧客 : アクター
    - 顧客アカウント : DBに格納されるエンティティ
- 「ユーザーアカウント」「顧客アカウント」は同じなので、今回はより明示的な「顧客アカウント」のみ使用する
- 「書籍レビュー」「レビューコメント」は同じなので、「書籍レビュー」を使用
- 「書籍一覧」は抽象度が高い名詞である。不明な点はドメインエキスパートによく尋ねる

などなど。。

</div></details>

## 3. モデリング

整理した名詞リストを元に、1回目のモデル図を書いていきます。

![image.png](http://www.plantuml.com/plantuml/png/SoWkIImgAStDuKfCBialKdYvSFdJTOku4jDJyqgWdCTDGBJwSTEonysR7pTteCYzM3droRw5KA77pVCUD-rytBJ_SVCUD4sFcrS1fH2wdsrUyMnQEvJpVDE-v-kcmpWpTu4aP--06Tgq_d7pciTDEnutDmFr0mq5cTxS2PVU_hXvELXk2iYgfWqm5HrSN10tAkJhwYf4O_LBB9eIX9TYkOZn3LWVLfE9rWuB2WW54e651q844IX8WhX31bUOeDdea9gN0enu0000)

![image.png]
(http://www.plantuml.com/plantuml/png/SoWkIImgAStDuU9AJ2x9Br9uiMdbqyMRNZIqSYMcf-QLA3oRlUFvnbuevyN4wGYPnqsh7pUtFMxQyhXvrUFcFIZg7pUlUTmy-N7pKf04GddJ_iVDQnytRK1H-sH7mujbos4sRDxpj7NfarqTJzVD0fdRjFDnSmSN5znL2lcwkWhHo6R5SY7pGF8mDqCea0ZCuGWH3DSZfB1v0Tcbo5PWTIwo0Yw7rBmKKF020000)

## 4. 集約関係(has-a)を記述

上記では既に`has-a`の関係を記述してありますが、全てが正しい状態ではありません。
正しいかどうかを判断する方法の１つに`「◯が△を持っている」`と声に出して読み上げる、という方法があります。
「注文」は「精算」を「持っている」かどうか、を考えると、イマイチイメージしづらいことに気付くでしょう。
自然な関係を考えると、「顧客アカウント」が「注文履歴」を持っていて、「注文履歴」が「注文」を持っている、という関係に落ち着くでしょう。
また、「精算」は名詞ではなく動詞に近いので取り除きます。
また「著者」はクラスとしては小さすぎであり、「書籍」の属性に過ぎないので取り除きます。

## 5. 汎化関係(is-a)を記述

続いて汎化関係(is-a)について考えます。
まず「書籍一覧」について考えます。
「書籍一覧」についてユーザーのニーズを深堀っていくと、「購入予定リスト」の他に、「関連書籍」「推奨品リスト」「検索結果」などの言葉が存在することが分かりました。
汎化の関係を判断する方法の１つに`「◯は△です」`と言葉に出す、という方法があります。

- 「購入予定リスト」は「書籍一覧」です。
- 「関連書籍」は「書籍一覧」です。
- 「推奨品リスト」は「書籍一覧」です。
- 「検索結果」は「書籍一覧」です。

この文章がしっくり来れば、それは汎化の関係と言えます。

## 6. 上記を反映する

上記を反映し、一部修正を加えたのが下記になります
これを元に実装やユースケース分析を進めていくわけですが、次以降のフェーズに取り組んでいる過程不自然な点が明らかになっていくと思われます。
そうした場合はまたドメインモデル図を修正し、反復的に改良していく、というサイクルを繰り返していきます。

![image.png](http://www.plantuml.com/plantuml/png/ZPJHRjem58Rl_HHvWRn2rVUOk41RrKtQsecbzy5UExZODAa5QGDLAbqWm811c0W8RGzpi9EynMnY9mvEf24aEFz_x7Dy_2Nd7vnwmxbvznRb_-eldUk6bJoDw7o0wfSNLuuC0FFl5F0GI02aLV3YSUVmvqbAG1u1Rm7_1R8_MGHa8gniDGjyrlr4bnwRhGkI2XuMhDs1vaVMtRAW8zNesqvazK9L42-0_0GS0Y6Y29wAogITsHiWewFt8Dh0lrH62ydZnginVLx5xgsgsmkZvMSP7BFl0Az5zsHVI15roJqGBpUYZP_qxlXU9LuycPc6gY46DkFT5GeSGZSUZjJoO4zllSEkHUVVZL5-yQddq_lcgP5q1udxN3WH-z6FreFezrVss4VvK1EtAGFQz-bkgWAtBGAKNhLrRLilz5klvOPq35Pgw7-O41jKi6QgAhz0a1vmLvfIveB1KnKvbdtptZupqZFmAlngqlHc4K8PR-dGzDkl8JqIlg8n_H6AWQHcbN1PIgGwWfbkGbgTgqFAopVUNBvsiePBSTNtKdIRx9PcQTIM-JhePJvAgTP7oj5MIcegnJv-pjHJaH5aA-NyukeLVrt-0m00)

# 引用

[ユースケース駆動開発実践ガイド](https://www.amazon.co.jp/%E3%83%A6%E3%83%BC%E3%82%B9%E3%82%B1%E3%83%BC%E3%82%B9%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-OOP-Foundations-%E3%83%80%E3%82%B0%E3%83%BB%E3%83%AD%E3%83%BC%E3%82%BC%E3%83%B3%E3%83%90%E3%83%BC%E3%82%B0/dp/4798114456)
[ドメインモデリングの始め方](https://speakerdeck.com/j5ik2o/tomeinmoterinkufalseshi-mefang)