効果的にDDDを導入するために気をつけるべきこと

# DDDはプロジェクトの期待に応えていますか？

この記事を読み始めたということは、あなたはDDDに興味を持っているか、またはDDDを実際に実践しているのでしょう。
最初に、あなたとDDDの関わり方について質問です。

* あなたが実践しているDDDは、満足度の高いソフトウェアをユーザーに届けるのに、効果的に機能しているでしょうか？

* またはこれからDDDを導入したいと考えているなら、どのようにDDDがあなたの問題を解決するか、イメージできているでしょうか？

どちらかにNoと答えたなら、この記事の内容が役に立つかもしれません。



DDDを学び始めるとき、我々エンジニアは技術的な面に興味が向きがちです。

* レイヤードアーキテクチャ(基本だね!)
* クリーンアーキテクチャ(依存方向は内側だけに向くようにするんだ!)
* CQRSやイベントソーシングなどの手法(ストレージを分けるのか分けないのか...)
* モジュール分けのルール/方法論(僕らはこういう方法でコードを整理してるよ!(ドヤ))
* バリューオブジェクト(大好き!VO!VO!VO!全部VOでええんや!(極論))

これらのDDDのプラクティスはドメインモデルをコードに落とし込むときに有益なものです。
ですが、これらを達成すれば、あなたの問題は解決するのでしょうか？いえ、しません。
整理された、美しいコードは多少なりともメンテナンス性の向上をもたらすでしょう。ですが、それだけではプログラムの対象領域(ドメイン)の問題を解決するのには力不足です。モデルを探求してドメインについて学ぶ必要があります。

ですが我々はエンジニアなので、どうしても技術的な面ばかり興味を持ってしまいます。
DDDは技術面ではなくユーザーの活動に焦点を当てようという取り組みなのに、やはり我々は「DDDをどのように実装したら良いのか？」ということに視点が向いてしまうのです。

コミュニティのやりとりを見ていても、実装方法についての質問がほとんどであり、「ユーザーから効果的にドメイン知識を学ぶにはどうしたら良いのか？」というようなドメインエキスパートとのコミュニケーションについての質問は皆無です。

なぜ我々はモデルの学習に興味を持ちにくいのでしょうか？なぜ技術的な学習にばかり興味を奪われ、モデルの探求をおろそかにしてしまうのでしょうか？

この記事ではメンタルモデル(思考の枠)という面から、この構造の説明を試みます。
また、効果的にDDDを導入するために気をつけるべきいくつかの点を、引用を交えて紹介します。

この内容は私自身のなかでもふわっとした感覚しか持ってないことなのですが、考えを整理しながら書いていきます。



# エリック・エヴァンスによる、DDDの目的、原則

DDDとは何なのでしょうか。何を解決しようとするものなのでしょうか。

DDDを提唱したエリック・エヴァンスによると、DDDはソフトウェアの核心にある複雑さ(ユーザーの活動やビジネス(＝ドメイン)の複雑さ)に立ち向かう活動だそうです。

エンジニアは技術によってソフトウェアの複雑さを解決しようとしがちですが、これはドメインの複雑さを解決しようとしていないので、問題をうまく解決できない(部分最適に陥ってしまう)。替わりにユーザーの活動やビジネスについて焦点を当てて設計すべきだ、というのがDDDのアプローチです。

エヴァンスによると、DDDを駆動するための原則は以下の3つだそうです。

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

コアドメインへの集中は、限りあるリソースを有効に使うために選択と集中をするということです。
また、ユビキタス言語を使うのは、モデルの探求のためでしょう。つまり、DDDにおいて重要な活動は、**モデルの探求** です。
チームがドメインについて学んでモデルを探求し、スマートにモデルの概念を表現できるよう、モデルを洗練させ続けること。
それを通じてビジネス上の価値を生み出すこと。
これがDDDが目指すところです。

ですので効果的にDDDを導入するための私からのアドバイスを一言でいうと以下のようになります。

「**モデルの探求にリソースを使いましょう。それを継続的に続けましょう。**」






# ドメインエキスパートとエンジニアの共同作業を阻むメンタルモデル

DDDにはモデルの探求が重要だということを説明しました。
効果的にDDDを導入できていないプロジェクトや組織では、モデルの探求にリソースを割いていないのが原因であることが多いのではないかと思います。

では「よーし、じゃあモデルを探求するぞー！」と意識を変えれば問題は解決するのでしょうか？
残念ながら、こう声掛けをしてもモデル探求に至らないプロジェクトをいくつか見てきました。

私は意識だけを変えようとしてもうまくモデル探求に結びつかない原因の一つとして、ドメインエキスパートとエンジニアの共同作業を阻む、メンタルモデル(思考の枠)の問題があるのではないかと考えています。

そこで、私がこれまでに自分の中に感じたり、実際に遭遇したメンタルモデルを紹介します。




### ドメインエキスパートがいない

ドメインエキスパートがいないので、エンジニアが業務の複雑さを想像してモデリングする。
この手法(制限)はプロジェクトによっては仕方のないケースもありますが、ドメインの知見をチームに提供できるドメインエキスパートが開発に参加するのに比べてビジネスの複雑さが反映されていない、実装に都合の良いようにドメインの面倒な面を無視したモデルが作られる危険があります。

https://airbrake.io/blog/software-design/domain-driven-design
Airbrakeによるこの記事は、ドメインエキスパートがいなければ「全て無駄」と言っています。

「エリック・エヴァンスのドメイン駆動設計」には、ドメインエキスパートとエンジニアの共同作業はプロジェクトの期間中、ずっと継続しなければならないと書かれています。

効果的にDDDを実践するためにはドメインエキスパートがプロジェクトに参加することが必要です。「ドメインエキスパートがいないから仕方がない。自分たちでドメインを分析するか」と安易に考えないでください。これまでにドメインが存在しなかった領域について開発するとき以外は、強力な先達としてドメインエキスパートが必要です。でなければ大きなビハインドを背負ってレースに出場するようなものです。
ドメインエキスパートを見つけることに労力/コストを割いてください。






### ドメインエキスパートが、自分の知見が良いソフトウェアを作るために必要だと信じていない

さて、ドメインエキスパートを見つけてきました。ところでドメインエキスパートとはどういう人でしょうか？

ドメインエキスパートは多くの場合技術に明るい人ではありません。

* あるプロジェクトでは、情報をデジタル化しようとしている配送業務を手配する事務員がドメインエキスパートです。
* 旅行チケットの予約を受け付け、電車、飛行機、ホテルのチケットを手配し顧客に配送するオペレーターがドメインエキスパートです。
* 留学生の在留資格を代理申請する大学職員がドメインエキスパートです。

彼らは上司から、業務を電子化するためにソフトウェアエンジニアと連携してシステム構築を指示されました。

ですが、彼らは自分が良いシステムを作る上でのキーパーソンだとは思っていません。
彼らはこう考えています。「エンジニアはコンピューターや情報工学に詳しいし賢いので(難しそうな言葉もいっぱい使うしね！)、私が知っていたり感じたりする問題点などすぐに理解してしまうだろう。私にはどういうシステムを作ったら業務の役に立つのかが全然わからない。コンピュータのことはよくわからないからね。私の仕事はエンジニアに要件を伝えることだけだ」

効果的にDDDを実践するなら、ドメインエキスパートのこのようなメンタルモデルは改めてもらわなければなりません。
ドメインの複雑さをソフトウェアに反映するには、ドメインエキスパートの経験や知識が必要です。ドメインエキスパートの協力、サポートがなければ、問題を効果的に解決するソフトウェアを作ることはできない、あなたこそがこのプロジェクトのキーパーソンなのだということを丁寧に説明してください。



### エンジニアが、ドメインエキスパートとの対話こそが良いソフトウェアを作るために最も価値あることだと信じていない

メンタルモデルに囚われるのはエンジニアも同様です。
エンジニアはコミュニケーションより技術的な活動を好みます。DDDを導入しようとすると、どのようにモデリングするか、どのように実装に落とし込むかということに多くの時間を使いたくなります。
ドメインエキスパートとの会話はモデリングの準備のために必要な分だけ行って、あとはモデリング、コーディングに集中します。DDDに関するクールなテクニックを使うことに喜びや達成感を感じます。

ですが思い出してください。DDDが解決しようとするソフトウェアの複雑さとは、ソフトウェアの対象業務の複雑さです。これに対応するにはドメインエキスパートとエンジニアが共同してドメインモデルを探求することが必要です。

エンジニアがドメインエキスパートとコミュニケーションし、モデルを探求することが重要だと信じていなければ、効果的にDDDを導入することはできないでしょう。

エンジニアが技術的なソリューションを好む傾向については、エヴァンス本でも指摘されています。

> 「しかし、たいていのソフトウェアプロジェクトでは、ドメインに関係した問題の解決が重要視されない。有能な開発者のほとんどは、自分の手がける特定のドメインについて勉強する気があまりなく、ドメインモデリングのスキルを真剣に伸ばすつもりはさらにない。技術指向の開発者は、自分の専門スキルを発揮できる、定量化可能な問題を楽しむものだ。ドメインに関する作業は面倒な上に、入り組んだ新しい知識を大量に必要とするが、そうした知識は開発者にとって、コンピュータ科学者としての能力を向上させるものではないように見えるのだ。その代わり、技術的な才能のある開発者は複雑なフレームワークに取り組み、技術によってドメインの問題を解決しようとする。ドメインを学んだりモデリングしたりするのは他人に任せてしまうのだ。しかし、ソフトウェアの核心にある複雑さには、真正面から立ち向かわなければならない。そうしなければ、的外れなソフトウェアを作ってしまう危険があるのだ。」

我々エンジニアは、技術的な活動を優先する傾向/特性があることを認識しておきましょう。
もちろん技術力がなければ複雑な活動を扱うソフトウェアは開発できません。しかし、DDDは技術面からのアプローチだけでは解決できない問題へのアプローチであることを思い出して、ドメインモデルの学習、探求にもリソースを割くべきです。







# ドメインモデルの探求とは?

ドメインモデルの探求、という言葉を使ってきましたが、具体的にはどういう活動なのでしょうか？
事例をエヴァンス本から引用します。

エヴァンスは銀行のローン業務についてのシステム開発プロジェクトでモデル駆動設計を進めていたが、うまく表現できない概念があり、問題が起きつつありました。その解決のため、ドメインエキスパートとのモデルの探求、リファクタリングを繰り返しました。その末に、問題を解決する概念を発見します。

* 銀行のローンに必要な処理をスマートに表現する「シェアパイ」という概念を見つけ出した。この概念はドメインエキスパートにとっても理解が容易なものだった。(それまでドメインエキスパートは、エンジニアの説明するモデルを「自分たちには専門的すぎる」と言っていた。)
* 新しい概念の導入により、それまで使われていた「ローン出資」という言葉が不要になったことに気づいた。そのときになって始めて「ローン出資」という言葉が銀行用語でないことに気づいた。
* シェアパイという概念はすごく有用だったため、見込み客への説明にもこの言葉を使って機能を説明した。見込み客や顧客はすぐにこの言葉の意味を理解できた。

この話はDDDを導入する目的についての本質を含んでいると感じます。モデルの探求を通じて不要な概念を取り除き、新たなユビキタス言語を発見し、ビジネスにインパクトのある改善を達成しました。

この事例から逆に自分たちのコードについて考えてみましょう。
あなたが作ったモデル、コードは、ドメインエキスパートとのモデルの探求に役立っているでしょうか？
それを達成するためには何をすべきでしょうか？あなたなりの指針を考えてみてください。






# 効果的にDDDを導入した時、チームはどういう状態になっているだろうか？

メンタルモデルについての話はここまでです。
次は効果的にDDDを導入できたときに、チームがどのようになっているのかのイメージを共有したいと思います。

私はDDDをプロジェクトに導入するときには、以下のようなチームの状態を目指してプロジェクト体制を整えます。
あくまで私のやり方ですので、あなたは違うチームの状態を目指すかもしれません。


DDDを効果的に導入できたとき、私達のチームは

* エンジニアはドメインにすごく詳しくなっている。さらなる詳細を知るためにドメインエキスパートと対話はするが、自分たちだけでも効果的にドメインの業務の細部を説明できるほどに詳しくなっている。そのためドメインエキスパートが発言する上で意図したことと、エンジニアの理解が食い違うことはほとんどない。
* エンジニアがドメインに詳しくなることで、ドメインエキスパートの要求に対して、技術的な面からも合理的な提案をすることができている。
* ドメインエキスパートと開発者は頻繁にコミュニケーションしている。不明点が出てきたら対話をし、それが関係者全員のあたらしい知見になるような、コミュニケーションを通じた学習インフラが整っている。

理想のチームの形を思い描けたなら、その状態に向かうように作業を計画しましょう。
ドメインエキスパートとドメインモデルの探求をする時間を計画に入れる必要があるはずです。




# 効果的にDDDを導入できているかのチェックリスト

モデルの探求にリソースを割けているか、以下のような自己診断チェックリストで定期的にチェックしましょう。

  * コーディングに集中しすぎていないだろうか？ドメインエキスパートと会話をしているだろうか？
  * ソースコードはドメインエキスパートと効果的なコミュニケーションをするために役立っているだろうか？そうでなければソースコードで表現されたドメインモデルを見たら、ドメインの知識がわかるようにコードを改善しよう。



# DDDというソリューションを持ち込んだらうまくいく、などと考えない

「DDDというデザインパターン、ベストプラクティスを導入したら、自分の会社もいいかんじになる」などと考えてはいけません。
DDDがもたらす効果は外部から与えられるものではなく、自分たちのことをもっとよく知ること、あなたがソフトウェアを作って助けてあげたい人たちの活動、問題、ビジネスのことをもっとよく知ることによって得られるものです。もっと家族と...じゃなかった。もっとドメインエキスパートと話をしてください。


# まとめ

効果的なDDDの実践のためにはドメインエキスパートと協力してモデルの探求を継続的に行う必要があること、それを阻むメンタルモデルや環境についてお話しました。

DDDの主目的はドメインの複雑さに対処することであり、モデルの探求と、その実装はDDDの両輪です。どちらが欠けても、DDDの導入は大した効果を上げられないでしょう。

もしあなたのプロジェクトがモデルの探求を考慮していないなら、ドメインエキスパートとの対話を通じたモデルの探求、ドメインの学習を計画に組み込みましょう。




# 余談: そもそもDDDを導入するに値する、複雑さのあるドメインがソフトウェアの対象だろうか？

この記事ではDDDをどのように効果的に導入するかについて説明しましたが、DDDは全ての問題を解決する銀の弾丸ではありません。
そもそもDDDを導入しても旨味の少ないプロジェクトであれば、DDDを導入すること自体を止めるべきかもしれません。

https://airbrake.io/blog/software-design/domain-driven-design

Airbrakeによるこの記事によると、ドメインの複雑度が少なくて技術的な複雑度の高いアプリケーションはDDDに向いてないとのことです。
DDDを導入すれば、どんなプロジェクトでもスマートに解決できるなどと考えないでください。
DDDは良いソフトウェアを作るための一つのツールです。
あなたのプロジェクトにマッチしたツールかどうか、導入の前に検討してみてください。