わかった気になるDDD入門記事まとめ

## はじめに

こんにちは。はじめまして。tarokamikazeです。
これは、社内勉強会用に参考資料をまとめたものです。

## この資料のゴール

- DDD専門用語について、どんなワードでググったらいいかわかるようになる
- DDDを知らない人が、戦術的DDD(軽量DDD)だけでもやってみようかなという気になる

### 前段; MVCの限界

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">余談ですが、凝集度・結合度の観点からするとRailsのMVCがどう問題があるかをコラムで紹介しています。MVCそれぞれの責務を図示すると、低凝集・高結合になっていることがわかります。<br>とにかく、凝集度、凝集度なのです。 <a href="https://t.co/fDWv1ERJA1">pic.twitter.com/fDWv1ERJA1</a></p>&mdash; 松岡@技術書典8Day2え28 / DDDブログ書いてます (@little_hand_s) <a href="https://twitter.com/little_hand_s/status/1224114009709805568?ref_src=twsrc%5Etfw">February 2, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

あえて過激に言うと。
ある程度の複雑度を持ったアプリケーションにおいて、MVCであるというだけで、 `Fat Model` か `Fat Controller` は避けられない。
モデルの中を整理できるような設計思想が必要なのだ！
というか、モデルっていうな！！

### 参考

- [お前らがModelと呼ぶアレをなんと呼ぶべきか。近辺の用語(EntityとかVOとかDTOとか)について整理しつつ考える](https://qiita.com/takasek/items/70ab5a61756ee620aee6)
- [MVCのモデルの誤解を解くためにフレームワークを例に挙げようとしたら誤解してもしゃーないなって思った](https://qiita.com/khsk/items/a8cd3adf1e22c9eb209e)

## DDD概観

### DDDとは

> Domain-driven design (ドメイン駆動設計)
> 顧客と開発者が業務を戦略的に理解し、共通の言葉を使いながらシステムを発展させる手法

[ドメイン駆動設計のメリットと始め方 ～ 1章「DDDへの誘い」](https://codezine.jp/article/detail/9546)

> ドメインの中にあるコアとなる複雑さ、クリティカルなパートにフォーカスする
> ドメインとソフトウェアのエキスパートが協力しモデルを探索する
> モデルをはっきりと表現するソフトウェアを書く
> 境界づけられたコンテキストの中でユビキタス言語を話す

[ドメイン駆動設計の道標](http://tlync.hateblo.jp/entry/2016/12/25/171648)

### いつ誰がいいだしたの？

Eric Evans というひとが2011年頃に書籍 「エリック・エヴァンスのドメイン駆動設計」を出版。これが原点とされる。
その後、2015年「実践ドメイン駆動設計(通称 実践本、iDDD本)」が出版。この記事はこちらに依拠してます。

### ドメインってなによ？

> 知識、影響、または活動の領域
> 問題領域、業務領域とも訳されます。ソフトウェアが表現する対象。例えば、人事評価システムであれば、従業員や業績が知識であり、目標設定や評価が活動に当たります

[ドメイン駆動設計の用語と解説(抜粋版)](https://qiita.com/nunulk/items/84438605eb4d75dbef00)

### ふわっとしすぎてよくわからんのですが

> DDDの領域は大きく分けて3つに分けられます。
> 
> 開発思想：
システムの複雑性に取り組むために、業務の専門家と技術の専門家で言語・モデルの認識を合わせ、継続的に進化させていこう、という考え方
> 戦略的設計：
ドメインモデリングの前提を揃えるための、モデリング対象を定義する原則と手法(コアドメイン/サブドメイン、境界付けられたコンテキスト、コンテキストマップ等)
> 戦術的設計
モデルを具体的に表現するためのパターン(エンティティ、レポジトリ、レイヤードアーキテクチャ等)

[なぜDDD初心者はググり出してすぐに心がくじけてしまうのか](https://little-hands.hatenablog.com/entry/2017/09/24/005903)

### DDDやると、なにがうれしいの？

> プロセスやツールよりも個人と対話を、
> 包括的なドキュメントよりも動くソフトウェアを、
> 契約交渉よりも顧客との協調を、
> 計画に従うことよりも変化への対応を、

[アジャイルソフトウェア開発宣言](https://agilemanifesto.org/iso/ja/manifesto.html)

と言われても、どんなふうに対話するの？ どんなふうに変化に対応するの？ という疑問は浮かぶでしょう。
DDDはその道標になります。


もうすこし具体的に言うと。

- MVCだとよくおこる「このロジックはどこに書けばいいんだっけ...」という迷いが出ないので、プログラム設計がサクサクできる
- プログラムが高凝集・疎結合になるので、メンテナンスコストが下がるし、バグがおこりづらい。特に致命的なビジネスロジック周りのバグを防ぎやすい
- ドメインエキスパート = 事業領域（ドメイン）に超詳しいひとと、開発者が話しながら実装を進められるので、上流工程がスムーズにいくし、認識齟齬がおきづらい（個人的には、アジャイル開発における上流工程のデファクトスタンダードだと思う)

## 戦術的DDD

プログラムレベルでは、こういうパターンで設計したらいいですよ、というベストプラクティス。
個人やプロダクト単位で「とりあえずDDDやってみるか！」となったら、戦術的DDDから導入するのが王道。
プログラマーにはとっつきやすい部分。しかし戦略までやらないと、開発の辛さは(減りはすれども)消えないのだ......

ちなみに、戦術的DDDだけを導入している状態/開発方針を「軽量DDD」と呼ぶ。基本的にはアンチパターンと言われているので、はやく戦略も手を出してみよう。

### ようするにどういうことよ？

以下のベストプラクティス、デザインパターンの一種

- オブジェクト指向、クラス設計
- 単体アプリケーション設計、モジュールの依存関係

### 全部これで書き換えなきゃいけないの？

DDDは設計・実装コストが高いので、複雑でつらい更新系処理からやってみよう。以下のようなルールで柔軟に考えるべき。

- 原則、更新系のみに適用すべき。参照系に全然適用しない方がいい。[CQRS(コマンドクエリ責任分離)](https://docs.microsoft.com/ja-jp/azure/architecture/patterns/cqrs).
- 単純な更新系処理ならば、設計・実装コスパがあわないのでやらんでもいい。
- ビジネス的にコアな機能や、複雑な処理から手をつけ始めよう。

### MVCでそれできるの？

MVCの考え方から脱却したほうが、すんなり理解できる。
iDDD本ではヘキサゴナルアーキテクチャを推していたが、正直ふわっとしすぎてイメージできなかった。
個人的には DDD + クリーンアーキテクチャ が最強。

下図でいう、Entitiesの部分がまるごとDDDの担当領域。

![DDD + クリーンアーキテクチャ](https://camo.githubusercontent.com/466e05c456651fbb55b64f59bf32f82bf99ee90d/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f32383436342f31316431383638392d396139392d356263302d333964632d6534383632336631643131632e6a706567)

[実装から学ぶクリーンアーキテクチャ](https://gist.github.com/mpppk/609d592f25cab9312654b39f1b357c60)

なおここ数年では、 [Ruby On Rails でDDDを導入した例もちらほら。](https://quipper.hatenablog.com/entry/2018/07/27/separate-concerns-with-ddd)

### 代表的なパターン

以下は、名前だけでも覚えていってください!

- 集約(Aggregate)
- 値オブジェクト(Value Object)
- エンティティ(Entity)
- リポジトリ(Repository)
- ドメインサービス(Domain Service)

### 集約 / 値オブジェクト / エンティティ

![集約](https://cz-cdn.shoeisha.jp/static/images/article/10776/10776_001_s.png)

[実践DDD本 第10章「集約」～トランザクション整合性を保つ境界～](https://codezine.jp/article/detail/10776)

値オブジェクト: 開発言語依存のプリミティブな型(stringとか)をラップしたもの。値依存のビジネスロジックはここに書く。不変(イミュータブル)で、IDをもたない。密結合なら、値をいくつか持っていい。（価格オブジェクトなら、金額とか通貨単位など）
エンティティ: IDで判別される値のかたまり。ユーザーとか。不変ではない。
集約: エンティティや値オブジェクトをまとめた塊。トランザクション境界(たとえば、どれかのエンティティの更新がコケたら全部コケてほしい)の単位でセットにしていく。

### リポジトリ

- 定義としては、集約を取得したり保存したりする入り口。
- 実装的には、DBとか外部APIを叩くやつ。
- ドメイン層(domain package)にinterfaceとして定義し、他の層から利用する場合はこのinterfaceに依存させる。実装はインフラ層に書く。

### ドメインサービス

- 単一の集約 / 値オブジェクト / エンティティ に依存させられないビジネスロジックをここに書く。
- 例) ユーザーIDはユニークじゃなきゃいけないよ、というロジック
- これがいっぱいできるのは設計がイケてない証拠。苦肉の策として使おう。

### エンティティやリポジトリって、ORMのあれ？

[ORMの定義は忘れろ。あれはDDDの用語を借りたナニカだ。](https://qiita.com/takasek/items/70ab5a61756ee620aee6)

特にエンティティは、DTO的オブジェクト<-->DDD的エンティティへの値の詰替が推奨される。
詰替はだるいが、それが戦術的DDDなのだ。がまんしよう。
この値詰め替え実装コストが、戦術的DDDの実装コストの代表例といってもいいくらい。

## DDDの開発思想

### ユビキタス言語

> ユビキタス言語とは、開発者とドメインエキスパートなどシステムの開発に関わる人達全体のコミュニケーションを円滑に、曖昧さをなくすために厳格に定義された共有言語

[ユビキタス言語の用語管理について調べた](http://tbpgr.hatenablog.com/entry/2018/10/31/190000)

ドメインエキスパート = 事業領域（ドメイン）に超詳しいひとと、開発者の用語と、クラス名やメソッド名をそろえよう。そうすれば上流工程もすんなりいくし、改修もかんたん。

ドメインエキスパートと開発者が言語 = 認識を合わせていけば、齟齬も生まれにくいものだ。
ドメインエキスパートが社内にいない？　ならば君がドメインエキスパートになるしかないのだ!!
ユーザーインタビューに行きまくるしかない。

### 余談; UI/UXの世界でも

デザイナーの世界でも、概念モデルベースで設計しようぜ！的なことをが語られていますね。

![OOUI](https://www.sociomedia.co.jp/assets/images/dooui-quote.png)

[OOUI – オブジェクトベースのUIモデリング](https://www.sociomedia.co.jp/7279)

## 戦略的DDD

> 戦術の失敗は戦略で補うことが可能だが、戦略の失敗は戦術で補うことはできない

[軍事入門/戦略的な思考法](https://ja.wikibooks.org/wiki/%E8%BB%8D%E4%BA%8B%E5%85%A5%E9%96%80/%E6%88%A6%E7%95%A5%E7%9A%84%E3%81%AA%E6%80%9D%E8%80%83%E6%B3%95)

戦術的DDDに慣れてきたら、戦略的DDDにもトライしてみよう。
そもそものアプリの建付けからメスをいれるのだ！

### ドメイン? コンテキスト???

![境界づけられたコンテキスト](https://cz-cdn.shoeisha.jp/static/images/article/9744/9744_001_s.gif)

[実践DDD本 第2章「ドメイン」「サブドメイン」「境界づけられたコンテキスト」を読み解く](https://codezine.jp/article/detail/9744)

### 境界づけられたコンテキスト = マイクロサービスの境界

> システムが大規模になると、関係者すべてで統一したモデルを作ることは難しくなる
> 大きなシステムを「境界づけられたコンテキスト」に分割し、それぞれの中でモデル、言語の統一を目指す

![コンテキストをわける](https://cdn-ak.f.st-hatena.com/images/fotolife/l/little_hands/20171128/20171128084349.png)

[境界づけられたコンテキスト 概念編 - ドメイン駆動設計用語解説 [DDD]](https://little-hands.hatenablog.com/entry/2017/11/28/bouded-context-concept)

マイクロサービスをやりたいんだったら、戦略的DDDもきちんとやりましょう。

### どんな単位で切ればいいのさ？

エンジニアリング組織論への招待でも、two pizza rule で分けろと言われている。
いろいろ話をきいた結果、逆コンウェイの法則（組織にあわせてシステム設計する）のが正解っぽい。
つまり、1コンテキスト = 1マイクロサービス = 6~12名。

### ユーザー部門で切ればいいの？

そういうわけではない。とにかくシステムが高凝縮になるように、いいかんじに切れればいい。
ECシステムだったら、以下みたいに切っている例もあるらしい。

- カート
- 決済
- 商品(一覧とか更新とか)
- 配送

## まとめ

戦術的DDD(軽量DDD)から、雑にトライすればいいんじゃないかな。
勇気を持って学習棄却していこう。知的蛮勇を持っていこうぜ！！