※自己解釈です

概要

ドメイン駆動設計とは、

「複雑なドメインの設計は、モデルベースで行うべき」であり、また「大半のソフトウェアプロジェクトでは、システムを実装するための特定の技術ではなく、ドメインそのものとドメインのロジックに焦点を置くべき」

https://ja.wikipedia.org/wiki/%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E9%A7%86%E5%8B%95%E8%A8%AD%E8%A8%88

という前提で行うソフトウェアの開発手法である。

ドメインとは領域のことであり、この場合の領域というのは、プログラムを適用する対象となる領域のことである。
またその領域とは何を指すかというと、対象システムにおける特有の知識である。
通常プログラマーは(固有のプロダクトの専属となる以外は)汎用的な知識を身につけることで、それを応用しシステムを開発することが多い。
そのため開発するシステムに詳しくなくても、要求定義を行えば、実装は可能だ。
例えば物流システムを作成する場合、さほど物流システムに詳しくなくても問題なく実装は可能なのだ。

ドメイン駆動設計はこのような状態を悪とし、ドメイン、つまり物流システムの場合は物流システムのあり方をコードに落とし込むことで、物流システムを実際に使用する人と実装を結びつけることを目的にしている。
より具体的にはコードベースで、ストレージではなく倉庫、オブジェクトではなく貨物といった概念を用いて実装する。

これによって、ただ要求を鵜呑みにしたコードよりも未来で直面する問題解決がスムーズになったり、より整理されたコードライティングができるとされている。

ドメインの概念や事象を理解し、その中から問題解決に役立つものを抽出してコードに反映することを徹底するといったことが重要である。
一見当たり前にも見えるが、技術ばかり追いかける思考の場合はそれが疎かになりやすく、それは同時に汎用性を失うことにもつながるからだ。

プログラミング言語とは違うが、CSSで理解すると概要がわかりやすい。
例えば Tailwind CSS や Bootstrap などのフレームワークを使用して、ECサイトの商品アイテムをデザインすると、下記のようなHTMLになることだろう。

<div class="card text-center mb-4">〜</div>

一方、ドメイン駆動の場合は下記のようになる。

<div class="product-item">〜</div>

どちらがCSS的にいいかはさておき、つまりそういうことである。

プログラミングコードベースのメリット

少し深掘りしていく。
ドメインを中心に置くことにより、プログラミングコードには意図が書き込まれる。
なぜならドメインをモデル化する際に、そのモデルはドメイン自体の説明書となるからだ。
これはJavaScriptコーディングがTypeScriptが主流になっていったのと同様、コードがドキュメントになるということに違いと考える。

コードに意図がない場合について考えてみると、そのコードはたとえオブジェクト思考で書いたつもりでも、モデルの抽象化(抽象構造の発見)に失敗しているといえる。
このような場合、上述したように未来で直面する問題解決が難しくなる。

逆に言えば、クライアントサイドが要求を述べる際、事実だけを伝えるのではなく、意図も伝えるべきである。

下記の例がわかりやすい。

https://qiita.com/hirokidaichi/items/61ad129eae43771d0fc3

たとえば、次のような要求があったとします。

– 利用アカウントは、メールアドレスと電話番号を持つ。
– メールアドレスは必須ではなく任意。電話番号は必須ではなく任意である。
– ただし、作成時、追加時、編集時にどちらもない場合はエラーとする。
– どちらも入力されている場合はメールアドレスのほうにメッセージを送る。

このような要求があった場合、一般的なエンジニアはメールアドレスと電話番号を持つクラスを定義し、どちらもオプショナルな値(必須ではない)にするような設計をするかと思います。そして、作成時・追加時・編集時にどちらもなければエラーにするというバリデーションを実装することでしょう。つまり、要求をそのままに実装に落としていくという意味です。要求自体はかなり具体的に書いてありますから、そのまま実装に落とすこと自体が悪いとは言い難いでしょう。

一方、なぜメールアドレスと電話番号の2つが利用アカウントが持っているのかという「意図」をよりはっきりと記述してもらった次のような要求を見てみましょう。

– 利用アカウントには、最低1つは運営からのメッセージが送信できる連絡先がほしい。
– 連絡先手段としては、メールアドレス、電話番号の2つがある。
– 連絡先手段のうち1つをメッセージを送信するプライマリ連絡先とする。デフォルトはメール。

(中略)

このような要求定義の場合、利用アカウントが持つべき実装として「連絡先」があり、そのリストの1つとしてメールアドレスと電話番号があるのだとすぐに理解することができます。その結果、連絡先という抽象構造を利用アカウントに持たせるのが自然な実装になります。

もし、「意図」が要求定義にはっきりと記述され、それを理解した上での実装がされていると、このような「意図」に基づいた新たな要求に対するレジリエンス(耐久性)が上がります。

たとえば、
・新たに連絡先としてLINEアカウントを足したい
・複数のメールアドレスを登録できるようにしたい
・連絡先が認証済みかを管理できるようにしたい
といった要求が新しくきても「連絡先」と「最低一つは連絡先が欲しい」という意図はなんらかの抽象構造が存在するコードであれば対応は比較的容易になります。

一方で、意図が喪失してしまった要求で実装された場合、連絡先という抽象構造が見出されずに純粋に利用アカウントの各フィールドとして実装することが自然になるでしょうから、他の多くの場所でメールアドレスが一つしかないという前提の実装が各所に入ってしまい、なかなか修正しづらいという現象が発生してしまいます。

このように要求定義において意図の明確化は、「未来を予言して拡張性を組み込む」ことができない場合においても、「将来の不確実性」に対応する手段になるのです。ですから、マーケットが不確実で途中でさまざまな施策を考えなければならないケースであっても、ビジネスオーナーや関連するステークホルダーのシステムにそのような要求をする「意図」が発見できるようなコミュニケーションが重要になります。

https://qiita.com/hirokidaichi/items/61ad129eae43771d0fc3
https://qiita.com/hirokidaichi/items/61ad129eae43771d0fc3
https://qiita.com/hirokidaichi/items/61ad129eae43771d0fc3

よい文章だったので、たくさん引用してしまった。

逆に、委託先で実装するシステムはどういったものか、その根本を知る気概のあるエンジニアは良い会社であるといえる(当たり前のことだが、それが難しい)。
一見質問の少ないエンジニアは優秀であるように見えるが、そういった専門外の知識について聞いてくるようなエンジニアこそが真に優秀である。