Whyから始めるドメイン駆動設計

この記事は、[ドメイン駆動設計 Advent Calendar #1](https://qiita.com/advent-calendar/2018/ddd) の18日目の記事です。

ドメイン駆動設計をどうやって実現していくかについては、既にたくさんの素晴らしい記事があります。
しかし、ドメイン駆動設計をなぜやるのかについて考察した記事はそれほど多くないように思いました。
この記事では、なぜドメイン駆動設計が大事なのかについて考察することで、ドメイン駆動設計の勘所を追究していきます。
自分なりに噛み砕いたあとの文章なので、もし変な所があれば指摘頂けると大変助かります。

# DDDを駆動している原則
エリック・エヴァンスのドメイン駆動設計では、DDDを駆動している原則として以下の3つが挙げられています。

* コアドメインに集中すること
* ドメインの実践者とソフトウェアの実践者による創造的な共同作業を通じて、モデルを探求すること
* 明示的な境界づけられたコンテキストの内部で、ユビキタス言語を語ること

なぜこれらが大事なのでしょうか？
まず、これらの原則を全く無視した場合にどのような問題が発生するのかについて考えてみます。

# ソフトウェアを開発していく中で発生する問題
## 的はずれなソフトウェアを作ってしまう
ソフトウェアの核心は、ドメイン(ソフトウェアの問題領域)に関係した問題を、ユーザのために解決できることです。

開発者は、複雑なドメインの問題を解決するために、ドメインに没頭しなければなりません。
しかし、**大抵のソフトウェアプロジェクトでは、ドメインの問題を解決することが重要視されません。**

技術指向の開発者は、自分の専門スキルを発揮できるパズルのような問題について楽しむものです。
ドメインの問題について考えるのは、自分のコンピュータ科学についての能力を向上させることと関係ないように見えてしまうのです。

この結果、ドメインに関係した問題は解決されず、的はずれなソフトウェアを作ってしまうことになる可能性があります。

----

エリック・エヴァンスのドメイン駆動設計では、あるコメディ番組の撮影中に発生した出来事を例にこの問題について説明しています。
要約すると以下のような内容になります。

* あるコメディアンが、コメディ番組のシーンを繰り返し撮影し、苦労の末におもしろいものを撮ることが出来た。
* しかし、映像編集者は全然面白くないシーンを採用した。
    * 映像編集者は、番組に関係ない人物が写り込んでいたのでこのシーンを不採用にした。
    * 映像編集者は、自分の専門的な仕事を正確に遂行することしか考えていなかった。
* その後、コメディのなんたるかを理解する監督によって面白いシーンは復活した。

## ソフトウェアが複雑になりすぎて手に負えない
多くの事柄が原因で、プロジェクトは正しい道から逸れてしまいます。
ソフトウェアが手に負えないほど複雑になると、もはや開発者はソフトウェアを十分には理解できなくなります。
何が原因でソフトウェアは複雑になっていくのでしょうか。

多くのソフトウェア(ビジネスに関係する判定・条件分岐が含まれるもの)において、最も重要な複雑さはドメインそのもの、つまりユーザの活動やビジネスです。
**その複雑なドメインそのものを体系的に扱う方法が無いと、ソフトウェアはドメインの複雑さに引っ張られ全体が複雑化し、入り組んだ構造になっていきます。**

## ソフトウェアについての知識が失われていく
チームで開発を続けていくと、既存のロジックと矛盾したコードが生まれることがあるかもしれません。
このようなことが起こらないよう、チームメンバーと日々コミュニケーションを取り続けているはずなのになぜこのようなことが起こるのでしょうか。
このような問題が発生するとき、そのチームは知識の積み重ねに失敗しているか、知識の共有が不十分な可能性があります。
ある特定のメンバーしか把握していない知識があったり、普段メンバー同士で話している会話の内容と結びついていないような設計を行っているのかもしれません。

ソフトウェアに関する法則の中に、コンウェイの法則というものがあります。
> システムを設計する組織は、その構造をそっくりまねた構造の設計を生み出してしまう

同じチームであっても、コミュニケーションが不十分なため、ドメインエキスパートと開発者の間、開発者と開発者の間に知識の差が生まれることがあります。
これが原因で、**ある開発者のコードの中に重要な知識が閉じ込められ、重要な知識を共有することが考えられていないような設計が生まれてしまいます。**
重要な知識は、一部のメンバーだけが理解する実装の中で死んでいくのです。

## 時間が限られている中で、何を優先すべきなのかが分からない
設計が大事なのは分かっています。設計に気を配らなければ、降り注ぐ要件追加の要求の中で、とても保守していけるとは思えないようなコードが増殖していくことは目に見えています。
しかし、設計にかけられる時間は限られています。
私達はどの部分の設計に時間を使うべきで、どの部分の設計をあきらめればいいのでしょうか？
**取り組むべき問題の優先順位が決まっていなければ、貴重な工数をドブに捨てることになるかもしれません。**

# 問題を解決するために役に立つDDDの原則
## 的はずれなソフトウェアを作ってしまう

この問題を解決するために役に立つ原則は以下のとおりです。

* ドメインの実践者とソフトウェアの実践者による創造的な共同作業を通じて、モデルを探求すること

DDDではドメインに関係した問題をユーザのために解決するために、ドメインに関する膨大な知識を噛み砕き、ドメインについての深い洞察と、集中すべき主要な概念を反映したモデルを構築することに力を注ぎます。
この作業は、ドメインに精通したドメインエキスパートと開発者との間で、密にコミュニケーションを取りあいながら進めます。
作業を通して、**チームはドメインの中心に何があるのか、何が本当に大事なのかを理解することができ、進むべき道を見失った場合でもプロジェクトを元の進路に戻すことができるようになります。**

## ソフトウェアについての知識が失われていく

この問題を解決するために役に立つ原則は以下のとおりです。

* 明示的な境界づけられたコンテキストの内部で、ユビキタス言語を語ること

ソフトウェアについての知識が失われていくような状況にある場合、チーム内のコミュニケーションに問題がある可能性があります。
コード内に含まれる言葉や、書き溜めているドキュメントが実際に利用できる形になっていないため、**口頭での伝承が何らかの形で途切れた瞬間、ソースコードは秘伝のタレと化していくのです。**
高度に生産的なチームは、継続的に学習することで自分たちの知識をチーム内に生きた形で育て続けます。

DDDでは、知識を生きた形で育て続けるために、共有されたチームの言語であるユビキタス言語を活用します。
ユビキタスとは、いつでもどこにでも、といった意味の言葉です。
境界づけられたコンテキストとは、ある概念や言葉の集合が、まったく同じ意味のままで通じる範囲のことです。
ユビキタス言語はその名の通り、境界づけられたコンテキストの内部の、普段の会話中やソースコード、設計、ありとあらゆるコミュニケーションの中で使います。開発者、デザイナー、ドメインエキスパートなど関係なくチームの中心にある言語として育てていくものです。

曖昧さの無い知識豊富な言語を普段の会話・設計・実装のすべてで使い、チームの中心に持ってくることができれば、知識をチームの中に生かし続けることができるようになるでしょう。

**情報工学は知識を扱う学問、知識を明確に表現する生きた言葉は大事です。**

## ソフトウェアが複雑になりすぎて手に負えない
この問題を解決するために役に立つ原則は以下のとおりです。

* ドメインの実践者とソフトウェアの実践者による創造的な共同作業を通じて、モデルを探求すること
* 明示的な境界づけられたコンテキストの内部で、ユビキタス言語を語ること

先の説明で、多くのソフトウェアで、最も重要な複雑さはドメインそのものと説明しました。
ドメインそのものの複雑さを解消することができれば、ソフトウェア全体の複雑さはかなり軽減することができるでしょう。
しかし、この問題をコストをかけずに解決する方法はありません。複雑さから逃げず、絶えずドメインを学習し続け、ドメインエキスパートとともにモデルを洗練させていかなければならないのです。

エリック・エヴァンスのドメイン駆動設計では、ドメインの複雑さと戦う様々なテクニックが紹介されています。
今回はこれらの中から一部を紹介します。

### ドメインエキスパートと協力しモデルを探求する
ドメインそのものの複雑さに向き合わなければ、ソフトウェアはドメインの知識を表現しなくなり、一見して分かりづらい複雑な構造になります。
**ドメインエキスパートと協力し、ユビキタス言語を用いてモデルを探求し続けることで、ドメインはよりシンプルに表現できるようになっていきます。**
モデルが現状にそぐわないものになっていくことも多々あるはずですが、そこでモデルの探求をやめてはいけません。
複雑さに立ち向かい継続してモデルを更新し、ユビキタス言語を洗練させていきましょう。
こうすることで、ドメインの複雑さをコントロールすることができるようになっていきます。

### モデルと実装を結びつける
せっかく作ったモデルでも、実際にコード内で使われないのであれば、いずれ捨て去られます。
もしモデルと実装が結びついておらず実質使われていないなら、そのモデルにほとんど価値は無く、ソフトウェアが正確であるかどうかも疑わしくなってきます。
逆にモデルと実装が結びついているなら、次のような良いことがあります。

* モデルの探求で得た知識と、実装を通して得た知識が相互にフィードバックし合う、フィードバックループが生まれる
* モデルの探求と実装の垣根がなくなり、普段の会話がそのまま実装に、普段の実装がそのままモデルの探求になる

モデルと実装が結びついているなら、**モデルの実装の相談をしたいときにエディタを開いてコードを見せなくても、チャット上の日本語の会話だけでほとんどの相談ができるようになるはずです。**

### ドメインを隔離する
ドメインの知識がソースコードに散らばっている場合、ソースコードを見た時ひと目でドメインの知識の構造を理解できなくなります。
思考を最適に働かせるには、モデルを表現したオブジェクトであるドメインオブジェクトは、システムの他の要素から切り離す必要があります。
こうすることで、**ドメインの概念をソフトウェアの詳細な技術にしか関係しない概念と混同したり、システム全体の中に紛れ込んでドメインを見失うことを避けられるようになります。**

## 時間が限られている中で、何を優先すべきなのかが分からない
この問題を解決するために役に立つ原則は以下のとおりです。

* コアドメインに集中すること

優先順位を付けて中心となる問題に集中し、些末な問題の海で溺れずにいるためにはどうしたらよいでしょう？
ドメインエキスパートと協力しモデルを探求するたび、どの知識について優先して取り組むべきかが見えてくることがあります。
まるでアルコールを蒸留するかのように、自分たちのソフトウェアを特徴付け価値のあるものにしていきたいソフトウェアの本質部分、その部分には入らないがソフトウェアを構成する上で重要な部分、が見えてくるはずです。

自分たちのソフトウェアの中で、一番の強みとなる価値ある部分、これがコアドメインです。
蒸留によりコアドメインを抽出することの利点としては、例えば以下があります。

* モデルで最も価値がある領域が明確になり、その部分の作業に集中できるようになる
* モデルの領域に優先順位が付き、リファクタリングの際の指針となる

**現実は厳しいもので、ソフトウェアのすべての部分を等しく改良していくことは出来ません。
コアドメインを抽出することで、時間がない中でも何に集中すべきか、どこを改良するのが一番効果的かが分かるようになります。**

# ドメイン駆動チーム
これまでの説明を振り返ると、DDDがコミュニケーションに重きを置いているのが伝わってきます。
最後に、エリック・エヴァンスのドメイン駆動設計のまえがきに書かれている文章を紹介します。

> ドメイン駆動設計を理解している個々の開発者は、価値のある設計テクニックと全体を見る視点を本書から得るだろう。しかし、最大の収穫が得られるのは、チームが一致団結してドメイン駆動設計アプローチを適用し、ドメインモデルをプロジェクトで交わされる会話の中心に持ってきたときである。
> そうすることで、チームメンバは言語を共有し、コミュニケーションを豊かにして、コミュニケーションがソフトウェアとつながった状態を保てるようになる。
> (中略)
> ドメイン駆動設計は困難な技術的課題だが、大抵のソフトウェアプロジェクトがまさにレガシーへと風化し始めるときに、チャンスを大きく広げることができるものなのだ。

# さいごに
なぜドメイン駆動設計が重要なのかについて説明してきましたが、ここまで読んだところでまだまだ分からないことがたくさんあると思います。

* モデルはどうやって見つければいいのか
* ユビキタス言語はどうやって作っていけばいいのか
* モデルを実装と結びつけるとは、具体的にどんなコードになるのか
* ドメインを隔離するとは、実際にはどうやればいいのか
* 今あるソフトウェアが結構ひどい状態、この状態からでもDDDはできるのか
* そもそもDDDをやるべきなのか

ドメイン駆動設計は、完璧にやろうと思うと膨大な時間がかかります。
筆者の考えとしては、最初から全部理解しようとせずに、チーム内の協力してくれそうなメンバーを誘って分かるところから色々試行錯誤してみる、というのがいいのかなと思います。
ちょこちょこ勉強を続けていきましょう。
具体的な実装のテクニックをまず知りたい場合には、以下のスライドがおすすめです。

> ボトムアップドメイン駆動設計 (@nrslibさんの記事です)
https://nrslib.com/bottomup-ddd/
スライド
https://www.slideshare.net/MasanobuNaruse/bottomup-ddd-1
https://www.slideshare.net/MasanobuNaruse/bottomup-ddd-2

また、DDDのコミュニティもあるので、こちらで色々質問してみるのもいいかもしれません。
<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">「DDD Study Group」という名前でDiscordコミュニティ作成しました！<br>ご参加頂いた方とこのグループ内で、具体的に今後の活動について話していきたいと思います。まずは自己紹介channelで自己紹介いただけると嬉しいです！<a href="https://twitter.com/hashtag/%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88?src=hash&amp;ref_src=twsrc%5Etfw">#ドメイン駆動設計</a> <br>↓招待リンク<a href="https://t.co/FDhCcS6bho">https://t.co/FDhCcS6bho</a> <a href="https://t.co/TGsSNUQ4vu">https://t.co/TGsSNUQ4vu</a></p>&mdash; 松岡@DDDブログ書いてます (@little_hand_s) <a href="https://twitter.com/little_hand_s/status/982979772157313025?ref_src=twsrc%5Etfw">2018年4月8日</a></blockquote>

以上ですm(_ _)m