ドメイン駆動設計の実践メモ

# ドメイン駆動設計のゲーム利用についての勉強会
## 勉強会について
ドメイン駆動設計の実践
~ ゲーム開発にどう活用するか ~
[connpassイベント詳細ページ](https://techxgamecollege.connpass.com/event/97423/)
[発表スライド](https://www.slideshare.net/masuda220/ss-111011089)

*以下のドキュメントの方が、正しくまとまってます*
[3つのキーワードで学ぶ、ドメイン駆動設計の基礎知識](https://logmi.jp/310424)
[よくわかるドメイン駆動設計の考え方　従来の設計との違いと、ゲーム開発での活用法](https://logmi.jp/310537)

### 登壇者紹介（敬称略）
増田 亨 ギルドワークス 取締役
Twitter: [@masuda220](https://twitter.com/masuda220)

### 勉強会の趣旨
わざわざ人が来たくなるような登壇者を呼び、継続して勉強会を実施していきたい。
今後も勉強会にて、エンジニアの交流をしていきたいとのこと。

## 発表内容
### はじめに
増田氏は、テクロスさんのUNITIAの設計で参画されていた。
自身もゲームが好きで、ドラクエ初期は1週間ゲーム漬けだったこともある。

### アジェンダ
1. ドメイン駆動設計の全体像
2. ゲーム開発への取り入れ
3. ドメイン駆動設計を取り入れるハードルへの取り組みのヒント

### 基礎知識
- ドメイン駆動設計とは？
ソフトウェア設計の考え方の一つ
設計に対するメリハリの付け方と理解すると、ドメイン駆動設計がつかみやすい。

- ソフトウェア設計の一般原則（増田氏いわく。）
    - 関心の分離
        - 関心事心配事をどのように切り分けてアプローチするか？
    - モジュール構造
        - ソフトウェアで関心事が分離出来ている ＝ モジュール単位で分離されている
    
- 要するにドメイン駆動設計とは？
関心をどう捉えて、どう分離されているか。
要するにどのようにモジュール単位で分離されているか。

### 1.ドメイン駆動設計の関心、モジュールをどのように分離するか？

#### ドメインロジックに焦点をあわせる
ドメインロジックだけに焦点をあわせる。
その他がぼやけてても良い。

従来の設計は、入出力に焦点をあわせる
ドメイン駆動設計は、ドメインロジックに焦点をあわせるので、従来の設計とは違う。
入出力は背景としておく。値にフォーカスする。

##### ドメインロジックの構成要素
- ゲーム分野
    - ゲームを構成する概念（用語）
        - ゲームの世界観、キャラ設定、シナリオ、、、
    - ゲームの状況を表現する値
        - レベル、ゴールド、HP,MP,SP、アイテム、武器、、、
    - 値を使った計算や判定
        - バトル開始条件の判定ルール、勝敗の判定ルール、、、

##### ドメインロジックの関心事
- ゲーム分野
    - ビジュアルデザイン
    - サウンドエフェクト
    - インタラクションデザイン
    
ドメイン駆動設計で、これらは**「ドメインロジックに従属すべき関心事」**である。
ソフトウェアの開発者は、関心事の前に、構成要素を作るという順番で進める。

##### ドメインロジックに焦点をあわせる理由
ドメインロジック ＝ 計算ロジックと判定ロジック

1. ソフトの複雑さの原因は、ドメインロジック（計算ロジックと判定ロジック）にある。
2. ドメインロジックと入出力が混在していると、ドメインロジックの全体像や構造が見えてこない
3. 入出力の関心事を分離し、ドメインロジックだけを対象にし、ドメインロジックの輪郭や構造がはっきりしてくる
4. DRの輪郭、構造が見えると、計算ロジック、判定ロジックの発見が進み、ロジックの整理がやりやすくなる
5. 計算ロジック、判定ロジックが整理できると、入出力の記述もシンプルになる
6. ソフトウェア全体が見通し良くなり、変更が楽で安全になる。

##### 入出力+ドメインロジック
- プレゼンテーション層
- アプリケーション層
- データソース層

上記とは別に、、、
計算・判定ルールの記述（ドメインロジック）を独立したモジュールとする。

##### ゲーム開発でのメリット
- 計算ロジック、判定ロジックの記述が整理できる。
    - 同一ロジックの重複記述の防止
    - ロジックの組み合わせ方の見通しをよくできる

- 世界観・キャラ設定・シナリオ構成計算ロジック・判定ロジックの記述を直接的に関係づける
    - 全体が整合する
    - 変更の対象箇所、影響範囲を特定しやすい

    ゲームコンセプトとソフトウェアの同期が取れる状態になる。
    ゲームの変化とソフトウェアの変化に同期が取れる状態になる。

- 入出力の記述がシンプルになる
    - 計算や判定の記述

    ドメイン駆動設計がある程度できるようになったら、間違いなく入出力の記述がシンプルになる。

##### デモ
コンソールベースのUnixのゲーム(rogue)を紹介。
オープンソースで公開されているとのこと。

- ローグは、入出力から分離したゲームロジックだけのモジュールにあたる。
    - ビジュアル、インタラクション、サウンド、どれも貧弱。
    - ゲームロジックを表現したコードが大半を占める。
    - ユーザーインタフェースが貧弱なので、もっと面白いゲームにするためには、ゲームロジックに焦点を合わせた改良になる

コンソールレベルでのゲームを触ると、ロジックに焦点を当てているということがわかりやすいので紹介した。
ロジックにフォーカスしたゲームの作り方が、ドメイン駆動設計らしいゲームになる。

#### 2. オブジェクト指向でモジュール化
オブジェクト指向でのモジュール化と、それ以外でのモジュール化は、何が違うか。

##### ソフトウェアのモジュール
- コードを扱いやすいかたまりにグループ化し、グループごとに別ファイルで記述する。
ソース単位でコンパイル、実行できるようにする。
- モジュール（ソースファイル）間の依存関係を小さくする・少なくする。

##### ２つのアプローチ
どういう観点でソースを分割する？
「入出力の単位ごと」 or 「計算する値の種類ごと」

一番簡単な例は、String。文字列をどのように扱うか？で１ファイルでまとめられている。

##### 入出力単位のモジュール
（書ききれなかった、、、）

##### 値の種類ごとのモジュール化
- 計算や判定に登場する値を見つける
    - レベル、HP,MP,SP、、、
    - 武器の種類、、、
    - ダメージの判定結果、、、
- 計算する値の種類ごとに、必要な計算を整理する
    - 一致不一致、大小の判定、境界値の判定、値のリテラル表現への変換

「値の種類は多い、計算の種類は少ない」

##### 値の種類に焦点をあわせる

- オブジェクト指向の具体的なアプローチ
    1. ゲームロジックを値の種類ごとに整理
    2. 型の発見
    3. 型をClass構文で記述
    4. 実行時にオブジェクトとして生成
    5. 必要な計算と判定を実行する

ドメイン駆動設計を実行するためには、オブジェクト指向によるモジュール化しかないんじゃね？とういことで、オブジェクト指向を用いている。

##### オブジェクト指向のモジュール化と考え方とやり方を学ぶ
- 値オブジェクト
- 区分オブジェクト
- コレクションオブジェクト

- オブジェクト指向を学ぶ、おすすめの本
    - オブジェクト指向を理解するためには
        - 現場で役立つシステム設計の原則
    - オブジェクト指向で迷ったときは
        - オブジェクト指向入門 第２版 原則・コンセプト
        - オブジェクト指向入門 第２版 方法論・実践

Evans本はオブジェクト指向でモジュール化をする。と書かれている。

#### 3. インクリメンタルに設計
コードに落として、モジュール化をする。

##### 最初から良い設計は出来ない
- 開発を始めるときは対象領域の知識が貧弱
知識を少しずつ広げ、掘り下げる。

- 最初に書いたコードは、後から良い書き方が見つかる
一度書いたらそれが正解は、ない。
最初に書いたコードを見直しながら改善する
コードの１行の観点は、モジュール観点のアセスメントはセット
あるいみインクリメントな設計という意味での具体例。

- 最初の要求はあいまいで、時間とともに具体的で詳細になっていく

- 要求は、時間とともに変化する
誰かが悪いわけではなく、環境の変化や、ユーザーからのフィードバック、新しいタイプのゲームがでてくると、要求は変わる。

##### インクリメンタルに設計する
1. 基本的な値の種類を見つける
2. 値と値を組み合わせたロジックを置く場所を見つける
3. 値の種類（型）をグルーピングする

例）

1. HP,MPといった、プリミティブな型を集める
2. HP,MPなどを持った第三のクラスを見つける
3. サブタイピングして、構造的に型を整理する


##### 型のグルーピングの一つの設計のアイデア
- 値と値を組み合わせたクラス
    - ターン型
    - バトルコンテキスト型
    - バトル型

- 値の種類(型)のグルーピング
    - ポイント型
        - HP型、MP型、などに共通のメソッド定義
    - アイテム型
        - 食料型、薬型、巻物型

ゲームの特徴に合わせて型を作っていくのが、ドメインロジックに合わせたインクリメントな設計


#### 4. ゲーム開発を進めるときのドメイン駆動設計の障害

1. そうはいっても入出力
    - ビジュアル、インタラクション、通信、DB
    
2. フレームワーク
    - 入力イベントハンドラ
    - 入力を起点に出力までの処理手順をスクリプティングする道具

3. 開発プロセス
    - フェーズ分けと分業
    - コードを書き始めるタイミング/変更のリズム
    - コード変更の理由の混乱（モデルの変更？ビューの変更？両方？）
    
いいから直して！ここはすぐ直して！となると、ドメイン駆動設計だとスピードが遅くなる。

#### 5. いくつかのアプローチ
- ドメイン駆動設計に思い切って飛び込む
    - 少数精鋭かつ小規模で、徹底したDDDでやってみる
    - 学びのためのプロジェクトを実施する
- 従来のやり方に少しずつ、こっそりと
- 数値の計算ロジックは、必ず独自の型にラッピングする
- コレクションの操作ロジックは、必ず独自の型にラッピング
- booleann禁止　判定結果は必ずenum型で宣言する。

何よりも、実際にコードを書いて、その結果を確認しながら、議論し、決めていく
机上の空論ではなく、コードベースでドメイン駆動設計を実施してみる。

## Q&A

1. Q.（聞き逃した、、、）

2. Q.ディレクターに設計についていなどの理解してもらうのが難しい問題にたいしてどのように対応すればいいか？
A.最近、要件定義を生業にされている、神崎善司氏と話す機会があったとのこと。
ディレクターだけで仕様を意識できるのは、１割程度。RDRAを使って言語化しても、３割程度。残りの７割はディレクターから見た場合、「よしなに」してほしいところ。
エンジニアからすると、残り9割で「よしなに」すると間違いはおこるが、残り７割程度であれば、「よしなに」の手がかりができる。なので、３割まではヒアリングにて聞き出す必要はあるが、その先は諦めて自分たちで作っていくのが良い。

## 感想
- ドメイン駆動設計の勉強はしたことなかったが、初心者にもわかりやすい内容の勉強会だったため、非常にコスパが良かった。
- 実践をテーマにした勉強会とは言いつつ、そもそも設計について知らないと実践できないからか、ドメイン駆動設計の考え方の話がほとんどだった。
- 勉強会によりドメイン駆動設計により解決できる問題のイメージはできたが、オブジェクト指向設計やインクリメントな設計ではなく、ドメイン駆動設計をどのように現場に入れ込めばいいのかわからなかった。
- ゲーム業界をメインとした勉強会ではあったものの、業界に偏らず、ソフトウェア設計の一般論が９割だったため、未経験者にも優しい勉強会だった。
- 超概念的な内容から説明いただけたので、大学の講義を聞いているような感覚になり、非常に良い刺激となった。