DDDになぜ失敗するのか - DDDは何を実現したいか
2021年にDDDになぜ失敗するのかというスクラップを書きました。
ただの調査メモで誰かに見せるものでもなかったのですが、思いの外たくさんの人に注目されることになりました。
メモで誤解させるのも良くないし、自分の中の結論をまとめる意味でもちゃんとまとめたほうが良いなということでちょっとずつ記事にしていきたいと思います。
DDDは何を実現したいか
DDDはそもそも、何を実現したいんでしょうか。
エヴァンス本の最初の「まえがき」には、こう書いてあります。
私はこの10年間、...複雑なシステムを開発してきた。
...成功するプロジェクトに共通する特徴は、豊かなドメインモデルがあったということだ。
簡単にいうと「良いドメインモデルがあったときにプロジェクトが成功したぜ!」というわけですね。
つまりDDDは良いドメインモデルを介してプロジェクトを成功させることこそが目的であり、そのために
の2点を適切に行う手法といえます。
「ドメインモデルを実装に落とし込む」は根幹ではない
日本におけるDDDの解説というと、「どう実装するか」のところへの言及が多いです。
なので「DDDをやりましょう」が「ValueObject[1]を定義しましょう」や「DIP[2]しましょう[3]」と受け止められることがあります。
しかしDDDという思想にとって、そこは根幹にあるものではありません。
エヴァンス本の序章には以下のように書かれています。
根本的には、DDDを駆動してる原則は次の3つだけです。
・コアドメインに集中すること
・土面の実践者とソフトウェアの実践者による創造的な共同作業を通じて、モデルを探求すること。
・明示的な境界づけられたコンテキストの内部で、ユビキタス言語を語ること。
つまり守べきはこの3つの原則だけで、それ以外は原則を実現するための手段ということです。
具体例
たとえばLinkedinのDDD教材の章立ては以下のようになっています。
- Domain-Driven Design
- Microservices and Monoliths
- Bounded Contexts and Entities
- Reactive vs. Declarative Systems
- Event Storming
ご覧の通り、「どんなディレクトリ構成で、どうコードを書けば良いか」については全く言及されていません。
いわゆる「レイヤードアーキテクチャ」すら章立てされてないわけですね。
またヨーロッパのDDDコミュニティの公演を見ても、多くの日本人がDDDに対して抱いてる印象とは大きく異なると思われます。
日本では戦略的DDDの部分にオニオンアーキテクチャやクリーンアーキテクチャを採用されることが多いです。
しかしオニオンアーキテクチャを提案した記事にも、クリーンアーキテクチャ本にも、DDDに対する言及は全くないことからわかるように、これらはDDDから独立した設計手法[4]です。
つまりどう実装するかの部分はDDDを実現するにあたり交換可能なものであり、技術背景に合わせて自由に選択可能であるといえます。
ドメイン駆動開発をいつするべきか
いわゆる「ドメインモデルを実装に落とし込む」は根幹ではないことを説明しました。
これはどうでもいいと言っているわけではなく、ドメイン駆動開発の是非とはまた別の話であるということです。
つまり「ドメイン駆動開発をするべきなの?」って議論の論点は、まずドメインモデリングをしてから実装に落とし込むべきなのかになります。
ドメインを駆動すべきか、ドメインに駆動されるべきか
これについて杉本氏は以下のように言及しています。
EricEvansが提唱した「ドメインに駆動される設計」注2が注目されています。エンジニアがドメインを深く理解してユーザーとともにモデルを作り、コードに反映すべしという、傾聴に値する主張です。それでも筆者は、ドメインに駆動されて設計することがエンジニアの本懐だとは思いません。そうではなく、われわれは、自らが生み出すモデルとコードによって、ドメインを駆動するのです。
WEB+DB PRESS Vol.120 (Japanese Edition) (Kindle の位置No.3935-3940). Kindle 版.
「ドメインに駆動される」「ドメインを駆動する」は「すでに存在するドメインモデルを再現するのか」「ドメインモデルを新しく作るのか」と理解し、違いについて考えていきます。
ドメインに駆動されると何が嬉しいか
まずドメインモデルに駆動されると何が嬉しいのでしょうか?
たとえば過去、不動産系のシステムを作っていたことがありました。
目の前の仕様を実現するためにテーブル設計されて作られていき、『BuildingsがStringで住所を持つ』という設計になっていました。
しかし新規機能の実装にあたり、その構造では限界が来たんですね。
本来住所は『土地に対する住所である地番』と『建物に対する住所である住居番号』の2つがあり、それらを区別してモデリングする必要があったからです。
このように目の前の機能を実現しているだけでは実際に運用されているモデルとの乖離が生まれていきます。
それを防ぐ意味でも、その業界の人たちはどういうモデルで認識しているかを理解し、その通りにモデリングするのが重要となるわけです。
ドメインが先行しないとき
ドメインに駆動されるとは、すでにドメインが存在するということです。
つまり今ある業務をシステム化することが前提となります。
そしてそれを線でなぞるように、今行われている通りにモデル化する方法といえます。
3つの原則に「土面の実践者」というワードが入っていることからも、すでに業務が存在している前提が見てとれますね。
・土面の実践者とソフトウェアの実践者による創造的な共同作業を通じて、モデルを探求すること。
これはDDDが生まれた2000年ごろの時代背景もあるかと思われます。
当時のソフトウェア開発の多くは今ある目の前の業務をシステム化するものだったのではないでしょうか。
システムの提供するモデルに業務を合わせてもらう
しかし今、ソフトウェアの多くは不特定多数が利用するものです。
となると特定の誰かに合わせたドメインモデルを再現するのは難しいですよね。
たとえばGoogle Cloudはプロジェクトをフォルダという単位でまとめることができます。
世界中でプロジェクトのまとまりを「フォルダ」と認識してる人はいるのか、と考えるとDDD的にはダメなモデリングです。
しかしあらゆるケースに対応する上で、全く異なる概念で抽象化したほうが良いということなのだと思われます。
全く未知のドメインを開拓する
また今は「すでにある業務をシステム化する」ではなく、新しいビジネスを生み出すことの方が多いのではないでしょうか?
そうなると参考にすべきドメインモデルはなく、ゼロベースで最適なモデルを考えていくことになります。
新しくビジネスを生み出すときにドメイン駆動開発を実践しようにも、「土面の実践者って誰?」「ドメインエキスパートって誰?」ってなりますよね。
単に「企画の人と認識合わせようね」って話になってしまいます。
たとえばSlackを使う前からスレッドだのチャンネルだのって言っていたわけではないですよね。
Slackを使っているからこそスレッドだのチャンネルってモデルが認識されるわけで、これこそが「サービスがドメインを駆動する」ことなのかと思います。
ドメインを開拓するときにDDDは不要か
ではサービスがドメインを駆動していくときに、ドメイン駆動開発は果たして無駄になるのでしょうか。
その場合も、ドメイン駆動開発のエッセンスは役に立つと思われます。
たとえば企画や開発、デザイナーがそれぞれ異なるメンタルモデルでシステムを捉えているのは問題です。
エヴァンスの言うようにドメインモデルを図示しながら会議をすることで、これを防ぐことができるかもしれません。
そもそも開発内に閉じた話でも、フロントエンドとバックエンドで同じモデルに対して異なる命名をしているケースは往々にしてあります。それを防ぐためにも、ユビキタス言語[5]の考え方を取り入れると良いかもしれません。
もちろん、実装面でDDDを参考にして保守性を上げることもできるかもしれません。
つまるところ状況に応じ適切に方法選択していくことが重要ということです。
おわりに
まずは「DDDは何を実現したいか」という切り口でまとめていきました。
歴史的な面からの考察や、実装面、組織面についても後々まとめていければと思います。
Discussion