DDD Alliance! ドメインオブジェクトの見つけ方・作り方・育て方


久しぶりにDDDのイベントいってきました。
スライドとあわせて読むメモ。

[イベントページ](http://ddd-alliance.connpass.com/event/31834/)
[スライド](http://www.slideshare.net/masuda220/ss-62386442)

ドメインオブジェクト

- どうやって見つけるか
- どうやって作るか
- どうやって育てるか

考え方とやり方

- ThoughtWorksアンソロジー
- リファクタリング
	- イヤな匂いと改善策

今回は具体的な話

## アジェンダ

- 設計の基本
- 見つけ方
- 作り方
	- コード寄りの話
- 育て方
	- これもコード寄り

4冊に共通する価値観

複雑なものは変化していかなければいけない、自分たちも変わる必要があるという考え方
完全に予測するのは不可能。
最初に定義してその通りにやるのはツラい
DDDはそれに対するノウハウ集

## オブジェクト指向の開発スタイル

アジャイルとオブジェクト指向片方ずつでは成立しないだろう
作る→オブジェクト指向
プロセス→アジャイル

側面としてはデザイン、プロセスの見方だけど、目指してるものはそれぞれ同じはず

**言葉大事**

Iterative, Incremental, Interactiveの相乗効果

## 設計の基本

根本はモジュール性
独立性の高い部品を作ることがよいものを作ることに繋がる

機能分割のモジュールとオブジェクト指向のモジュール性を論じると絶対噛み合わない

前提として「オブジェクト指向のモジュール性」というコンテキストで話さないといけない。

### モジュール性

「オブジェクト指向入門」 バートランドメイヤー
モジュール性をすげー取り上げてる

モジュール性の評価基準

- 分解しやすい
- 組み合わせやすい
	- 分解した後組立直しやすいか
	- 最初の通りじゃないと組み立てられないのはアカン
	- これがオブジェクト指向と機能分解という意味のモジュール性の分解点
- わかりやすい
- 連続性
	- 例えば丸め計算
	- 消費税の丸めを四捨五入から切り捨てにする
	- 上の一つの変更要求をありとあらゆる機能全てをテストしなきゃいけないのはよくない
	- 仕様の変更とコードの変更が同じだけついていけること
- 保護性

簡単に言えば、変更が容易なのがよいモジュール性、大変なのが悪いモジュール性

### 2つのアプローチ

機能クラスとデータクラスに分けるのがよく使われる（機能分割のコンテキスト）
本で言ってるのは抽象データ型として作ることを言っている（オブジェクト指向のコンテキスト）

### 機能分割

元々はC言語やCOBOLの設計スタイルをJavaに適用したもの
伝統的なBeanの作り方
Sun自身がこれを推奨していた

オブジェクト指向らしく作ろうとするとこのアプローチは違う

JPAは失敗したEJBの焼き直し

これらのセカイでJava使って作ってると、今回の話は謎に見えるかもしれない
違うパラダイムの話

### 抽象データ型

外から見たときにどう見えるか、内部で見た場合の違いの話
内部でどういう処理ロジックで書かれてるかは関係ない。
`BigDecimal`とか見るといいよ

何をしたいかと内部でやってることを分けるという考え方

### モジュール性の比較

機能分割でやると

- 分解しやすい

だけ

オブジェクト指向

- 分解しやすい
- 組み合わせやすい
- わかりやすい
- 連続性
- 保護性

機能分割とは違ったアプローチの仕方

体で覚えてきたもの

- オブジェクト指向エクササイズ 9つのルール
- リファクタリング イヤな匂いとその改善
- ドメイン駆動設計 しなやかな設計の6つのパターン

開発中盤に大きな仕様変更が入っても無駄になる感覚はない
なぜかというと部品でやってるから組み合わせを変えるだけだから

### モジュール性に優れたオブジェクト

- オブジェクト指向エクササイズ 9つのルール
- リファクタリング イヤな臭い

## ドメインオブジェクトの見つけ方

ドメインを学ぶ→言葉で会話を交わす→コードに落とす→(繰り返し)……

実際にどうやってるか

アソビューさんの例

説明を聞いたときに出てくる言葉が引っかかる→ドメインの学びの始まり

**利用規約はドメインモデルそのもの**

ビジネスとシステム開発が近い関係でできるのでいい。
ラフスケッチはいきなりこんなキレイにはなってない

コードドリブン

### 関心事の見つけ方

ヒトというのは複雑で特別な関心事
そのドメインをうまく理解するために、ヒト・モノ・コトを理解する

やってるうちにこういうのをコードで作っちゃう

最初からいい名前見つけるのは大変

## ドメインオブジェクトの作り方

基本データ型に対して色々やるというロジックになる
それをどうモジュールにするか

オブジェクト指向エクササイズに沿って書いてれば黙っててもいい感じになる

getterを使わない
小さなクラスになるのでモジュール性が高まる

### 主役は値オブジェクト
業務ロジックがどんどん値オブジェクトに書かれるようになる

例えば…
1000で割って表示する、みたいなちょっとした式が色んなところに点在しなくなる

nullを渡さない、戻さないなど、オブジェクト全員が守れば、正しくできるはず

約束をハッキリさせようという考え方

## 育て方

### ドメインを隔離する

値オブジェクトは`fundamentals`
ドメインモデルは`model`

Spring Boot

コントローラ、サービスクラスはほぼスカスカ
ほとんどロジックを書かなくていいはず


コントローラとかサービスが複雑になってくるとそれはドメイン知識が漏れ出してる

if文一個書けば解決するってのはまあわかる

グラフ構造（ドメインのモジュール）とリスト構造（現実）
データをどう扱いたいかだけに関心がある
こっちに引っ張られるとドメインの表現がショボくなる
手っ取り早く書くなら内部の構造にあわせた方が早い。けど…。
良さが失われる。

妥協したところから腐り始める

### フレームワークの都合を排除する

MyBatis SQL Mapper
Jsonはpath記法で書けなくはないけど乱雑になっちゃうからやらない

### 育て方のシナリオ

手っ取り早く動かせるようにするんだけど、ちゃんとやらなきゃいけないんだよというプレッシャーのもとにやる。
野放図に妥協してるわけじゃない。

getterあたりを手がかりに複雑になってる場所を見つける

- コードの重複
	- 式
	- Value Objectに持たせちゃった方がいいんじゃないか
- 長いメソッド
	- 50越えたら大きいクラス
	- メソッドが5行越えたら怪しい
	- VOにロジックを寄せたらそんな長くならない
- 大きなクラス
- 引数の多さ
	- 2コ以上になってくるとドメインオブジェクトの置き方間違ってる説

#### メソッドの抽出

5行も6行も改行が入らず連続してたら抽出できるかも
メソッドに抽出するときに名前を考えなきゃいけなくなる→ここ頑張りポイント！
ぎこちなくても良いからメソッドに抽出してしまう
怪しい名前は気になるので改善したくなる

改行でグルーピングすることで止めちゃうとそれ以降触られなくなるので絶対ダメ、ダメ絶対

クラス名で名前考えた後にメソッド名考えた方が楽

一時変数を値オブジェクトに
けっこう大変

メソッド名を名刺に変える→その名前のクラスを作る→メソッド毎コピーする

区分オブジェクトのパターンは相当コードがキレイになる，オススメ。

#### 振る舞いを豊かにするメソッド候補

- 文字列で表現する
- 文字列空生成する
- 同一性の判定
	- 業務的な意味の同一性
- 比較・順序づけ
- 計算
- 列挙
- 上限・下限

元ネタはHaskellの型クラス

#### 10章 しなやかな設計

ぶっちゃけわかりづらい

チェックリストとして優れているからモジュール改善のチェックリストとして使う

### まとめ

- ごちゃごちゃしてきたら整理
- 整理の基本はメソッドの抽出と移動
- 7つの視点で振る舞いを豊かに

## まとめ

できない理由

- 今の○○ではムリ
- DDDにしたい意思があるならこのメッセージを

ケントベックのメッセージを思い出す

ドメイン駆動設計への道
ドメインの言葉で話すことで怒られることはない

## QA

- リファクタリングがツラい
	- IntelliJ IDEA素晴らしい
- クラス多いときにレビューがツラい
	- 意外と障害になりそう
	- その人がどういう風に考えてるか見えるので興味がある
- コンテキストを越えて使いたい型はどうするか
	- コピーして使ってる
	- それぞれのコンテキストで成長していくもの
- モジュール間の依存関係が複雑な場合のテストはどうしてるか
	- そんな複雑なのは改善できるんじゃないか？
	- ドメインオブジェクトにはテストコード書いてない
	- ドメインオブジェクトを使ったサービスレベル、E2Eのテストはしてる
	- リファクタリングすごいやるからテストコード直していくのがヤダ
	- テストを否定してるわけじゃない