初心者のためのDDD入門：ドメイン駆動設計とはなんだ！

こんにちは！ゆせです！
今回は、「ドメイン駆動設計」（Domain-Driven Design、通称"DDD"）についてアウトプットしておこうと思います。というのも、最近DDDを採用している大きめのプロジェクトにjoinし、DDDがどういうものか全くわからず開発に携わって撃沈してたので久しぶりにqiitaにアウトプットすることにしました。

### どんな人に読んで欲しいか
- DDDって何?(聞いたことあるけど何かよくわかってない人向け)
    - ドメイン, モデル, モデリング, ドメインエキスパートの解像度を高める 
- なぜDDDを最近よく聞くようになったのか
- じゃあそれより前はなぜDDDを聞かなかったのか

### 本記事で書かれていないこと
- 技術的な言及
- ドメイン駆動設計における各層の責務や概要(ドメイン層,コントローラ層, リポジトリ層等々)
(別の記事で書く予定!!!!)

## ドメイン駆動設計(DDD)ってなんだ
結論から言うと、ドメイン駆動設計とはその名の通り、ソフトウェア開発における

**「ドメインの知識に焦点をあてた設計手法」**

です。ここで私は、「そもそもドメインって何。。？」となってしまい、それ以降も初めての用語が多く理解が難しかったのを覚えています。本記事では、そんな方にも読んでいただけるように言語化頑張ってみようと思います笑

## じゃあドメインとは
ドメイン(Domain)とは本来「**領域**」という意味を持っています。ソフトウェア開発においてドメインという用語は様々な場所で使われますが、ドメイン駆動設計でいうドメインは、まさに領域のことを指しています。

例えば、料理レシピを投稿するアプリで考えてみましょう。ここでいうドメインは、「レシピ」や「調理手順」などでしょう。イメージでいうと、今回料理レシピアプリで核となる「モノ・コト」がドメインに値します。

もう一つほど例を出してみます。タスク管理アプリで考えてみると、「タスク」「期限」「ステータス」などでしょうか。(期限やステータスはちょっと無理矢理かも→期限やステータスはタスクの中に存在するものだから→「タスク」の1つの方がより正確だと思います。)

(他の記事は会計システムや物流システムで表現されていて本当はそっちの方がわかりやすい場合もあるのですが、皆さんのより近いソフトウェアで表現してみました)

### ここで一旦整理したいドメイン駆動設計の考え方
つまりドメインとは

「**アプリケーションやプロジェクトが解決しようとする問題領域/業務領域全体**」

のことを指します。

我々エンジニアは、ただコードを書くのではなく、そのコードで**課題解決を実現する価値**を生み出すことが重要です。そのため、ドメインはそのアプリケーションが焦点を当てるビジネスの本質的な部分とも言えます。
ドメインを正しく理解し、設計に反映させることで、実際に**価値を提供するアプリケーション**を開発する、これがドメイン駆動設計の特徴であると思います。

例えば先ほど例に挙げた料理レシピアプリでは、「レシピ」や「調理手順」　はユーザーが「良い料理を作りたい」という**目標を達成するための手段**です。この目標がドメインの中心にあり、その周りに具体的な機能が存在するように思います。

## ドメインエキスパートの存在(余談？)
ドメインに詳しい人をドメインエキスパートと呼びます。ドメインエキスパートの解釈は企業やプロジェクトごとによって違うかもしれませんね(ビズ側、PdM、PM等)。

共通して重要なのは、まずドメインエキスパートや関係者との対話を通じて**ドメインを深く理解**することです。開発者がドメインを部分的にしか理解していない状態で実装を進めると、要件とのズレが生じ、後々大きな修正コストが発生する可能性があります。
例えばエンジニア側からするとユーザー視点で機能を実装しても、ドメインエキスパートからするとユースケースからしてあまり嬉しくない、もしくは想定していなかった機能になってしまい、リリース直前に出戻りが発生するケースもあります。私自身何度か経験はあり、PdMと議論(**ユーザーが抱えている課題、ユースケース等**)を重ねた上で、ストレートにその課題を解決する手段を考え、実装に入ることを意識しています。

ドメインを正確に理解することで、ビジネスや業界の特性、プロセスを把握し、より精度の高いドメインモデルを構築することが可能になります。ここで大切なのは、単に**ドメインエキスパートの意見に迎合するのではなく**、ユーザーの課題を的確に把握し、それを元にエンジニアとしての視点から**ボトムアップでモデリング**することです。
優れたソフトウェアを作るためにはドメインにおいて有益な概念を作らなければなりません。ドメインエキスパートの目線一方通行では、本当に解決すべき点を見逃してしまうことがあります。ソフトウェアがまるで見当違いな方向へ進まないようにするためにも、エンジニア自身が主体的に問題解決に関わり、ユーザーのニーズを深く理解する姿勢を持つことが求められています。　

## それでモデリングって...？
自分が聞いても最初わからなかったような単語はなるべく書かないようにしていたのですが、モデリングを上で出してしまいました。。笑

そもそもモデルとはなんでしょう。[ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本](https://www.amazon.co.jp/%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88%E5%85%A5%E9%96%80-%E3%83%9C%E3%83%88%E3%83%A0%E3%82%A2%E3%83%83%E3%83%97%E3%81%A7%E3%82%8F%E3%81%8B%E3%82%8B-%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88%E3%81%AE%E5%9F%BA%E6%9C%AC-%E6%88%90%E7%80%AC-%E5%85%81%E5%AE%A3/dp/479815072X)(**ドメイン駆動設計を0から勉強したい人に勧める間違いない書籍**)にはこのように書いていました。
> モデルとは現実に事象あるいは概念を抽象化した概念です。抽象は抽出して象るという言葉のとおり、現実を全て忠実に再現しません。必要に応じて取捨選択を行います。何を取捨選択するかはドメインによります。
例えばペンはどのような性質を抽出すべきでしょうか。小説家にとってペンは道具で、文字が書けることこそが大事な性質です。一方、文房具店にとってはペンは商品です。文字が書けることよりも、その値段が重要視されます。このことが指し示すのは、対象が同じものであっても何に重きを置くかは異なるということです。

どうでしょう。とてもわかりやすいですよね。ある概念に対して異なる視点から見ることで、ドメインによって**その解釈や重要視されるポイントが異なる**ということが分かります。
 そして、これをソフトウェアに落とし込むのです。例えばコーヒーメーカーはコーヒーを淹れることが表現できればそれで十分で、**水をタンクに入れてスイッチを押すといったことまでを表現する必要はありません**。つまり、ソフトウェアがその責務を全うするために必要な情報に限定して、それを**コードで表現する**、これがドメイン駆動設計の思想と言ってもおかしくないでしょう。

先ほどの例を使ってみましょう。料理レシピを投稿するアプリでは、「レシピ」というドメインに対して考えてみると、それを作成するユーザーがいるわけですから「ログイン機能」が必要で、ユーザーはそれを投稿したいので「投稿機能」も必要です。「調理手順」というドメインに対しては、詳細説明が必要だとすれば、「200文字以上書けるテキストボックス」が必要かもしれないし、「画像を添付する機能」は必須でしょう。
 
 ### つまりまとめると
こういった事象、あるいは概念を抽象化する作業が**モデリング**で、その結果得られる結果が**モデル**です。ドメイン駆動設計では、ドメインの概念をモデリングして得られたモデルを**ドメインモデル**と呼んでいます。

## 改めて
先述した通り、「ドメインの知識に焦点をあてた設計手法」を改めて言語化してみると、
「**ビジネスやユーザーが直面する課題やニーズを深く理解し、それに基づいてソフトウェアを設計・実装すること**」 ということが言えるでしょう。

これによって、ソフトウェアは単なる技術的なアプローチによるアプリケーションではなく、ビジネス価値を最大化するための有効なアプリケーションとなります。ドメイン駆動設計では、ドメインに基づいたモデリングを行うことで、ビジネスと技術のギャップを埋め、エンジニアとビジネス側が共通の言語で議論できる環境を作り出します。

## そんなの当たり前じゃね？
> ビジネスやユーザーが直面する課題やニーズを深く理解し、それに基づいてソフトウェアを設計・実装すること

超超超超簡潔にまとめると、「ユーザー目線でニーズちゃんと理解して開発しようぜ！」みたいなニュアンスにも聞こえますよね(?)エンジニアとして活躍されている皆様からするとそんなことは当たり前だと思います。ではなぜ、ドメイン駆動設計は今まで採用されにくかったのでしょうか。逆に言えば、なぜ最近は採用されやすくなってきたのでしょうか。


## スピード重視のミニマムスタートの時代ではなくなったソフトウェア界隈
#### *「とにかく価値を提供するためにサービスを最速でリリースすることが最優先!!」*
個人開発やハッカソン、スタートアップ企業なんかではこのような考え方は多くあると思います。実際私も今まで開発してきたほとんどにおいてこのようなマインドで開発していました。言ってしまえば、見切り発車のようなものです。

ソフトウェアは常に変化し続けるものです。それは今の時代、人々の日常は常に変化を繰り返し、いつどうなるかわからない、そんな時代だからです。革新的なサービスやハードウェア、さらには生成AIの登場もあり、世の中の需要と供給は予測することが難しくなっています。

そんな中早期に開発されたシステムは、現代の変化に対応しきれず、修正が繰り返されるうちに複雑で維持困難なものになってしまうことが多いです。思い返してみると私が力を入れた個人開発やチーム開発においてもアプリケーションのスケーラビリティ性に悩むことは何度もありました。
その結果開発者たちは、短期的なスピードよりも長期的な運用の安定性を重視するようになりました。そこで採用されるのがドメイン駆動設計です。

### それでもドメイン駆動設計を採用することがメジャーではない理由
長期的な運用に向いているドメイン駆動設計手法が採用されないパターンが多くあるのは何故でしょうか。それは「**The モデリングに時間がかかる**」からです。「丁寧にモデリングする」≒「設計段階で時間がかかる」と言われているようなものです。「**設計に工数だいぶ割くけど頑張って！やってほしい！**」と頼まれても、コード書くの大好きエンジニアの皆さんなら、ネガティブな受け取り方をしてしまう方も少なくないと思います。勿論そうじゃない方も沢山いると思いますが、学生の自分はまだそう思えなかったため、そもそもドメイン駆動設計の存在すら知らなかったし、学生界隈で採用するモチベーションも無いのだと感じました。

そうなんです、ドメイン駆動設計は簡単に採用出来るものでは無いのです(あくまで学生目線)。採用するにあたっては、**多くのエンジニア**(経験者)は勿論のこと、エンジニアのみならず、モデリングをするために**ドメインエキスパート**も必要になってくるわけです。おまけに、モデリングに時間をかける≒**短期的な成果は出にくい**、すぐに結果は出ないすぐに成果物ができない)ということです。私はスタートアップ企業に長期にわたってコミットしたことがないので分かりませんが、スタートアップ企業においてもこの意思決定は難しいのではと勝手に思っています。
しかし逆の目線で言えば、そこを根気強くチームで作り上げればその効果は**長期的**に見て初めて発揮されます。時間が経つにつれて、そのドメイン領域に対するソフトウェアの価値が明らかになるということですね。

気づけばめちゃくちゃ持論を語りまくってしまいました。ｺﾞﾒﾝﾅｻｲ...

最後に先ほど紹介した成瀬さんの言葉を引用して終わりにします。
> プログラムは動かすだけなら簡単で、しかし動かし続けることは難しい代物です。システムを長期的に運用したいと願うならば、安定定期な飛行機の運用を願うのならば、ドメイン駆動設計をいまこそ学ぶべきでしょう。

## さいごに
実務でドメイン駆動設計と向き合うことはありますが、結論めちゃくちゃ楽しいです。私個人としてはドメイン駆動設計の思想が好き(ユーザーの関心事に向き合い、技術的アプローチをほぼしない)なのでそれが影響してるかもですが。事業のフェーズとしては0→１ではないので、0→１であれば違う感じ方があると思います。

久しぶりすぎる記事は難しかったです笑 が！この記事が誰かのお役に立てればとても嬉しいです！