「ドメイン駆動設計」は私の直感に反する。それでも生成 AI と共に理性で理解する。
注意書きとしての「はじめに」
この記事では「ドメイン駆動設計(Domain-Driven Design、以下 DDD)」について、個人的に最近思ったことを書く。DDD 自体の説明はせず、初歩的な知識があるものとするが、どちらかというと本題はマインドセットの話である。
「DDD とは何か」をかなりぼやっと理解している人(それが私)でも問題なく読めると思うし、DDD の部分を別の言葉で置き換えても成立する部分もあるだろう。
この記事で言いたいこと
- DDD の理念はわかりつつあるが、直感としてはまだ納得がいっていない
- AI の登場によって、DDD によく見られる批判は必ずしも真ではなくなったのではないか
- AI との協働を前提にした議論では、人間としての素朴な直感が正しいとはいえない
- どんなに自分が腹落ちできてなくても、理性的に見つめ直した方が良い
立場
かなり立場によるバイアスがかかっているはずなので、それについて明示しておきたい。
状況
- 数人規模の零細受託開発会社に所属
- 受ける案件も比較的小規模
- バス関連業務を専門にしている
- これまで DDD をやったことがないが、直近でそれっぽいことを実際に導入した
- GitHub Copilot を使いながら開発している
DDD への理解度
- DDD にわか
- 雰囲気わかる
- 本を読んで学習したことはない
- 周辺の詳しい友人たちから聞いたりもする
- DDD への批判の方で納得することが多い
本当の「はじめに」
私は DDD の話を聞くたびに、直感に合わない、腑に落ちないという感覚がある。それは今でもそうである。現状ある説明を見聞きしても、オーバーエンジニアリングではないかという疑いが晴れていない。
だからこそ、その構成を真似しようとは思わないし、これまで避けてきた。
だが、AI の利活用を進めていくうちに、もしかすると DDD との相性が良いのではないか、という仮説が立ち始めたので最近少しずつ取り入れようとしている。
この記事はそんな私が「なぜ納得できなくて、それでもなぜ DDD を取り入れようとしているのか」を言語化するものである。
殴り合うための記事ではないので、少々断定的な偏見 / 表現もあるかもしれないが、肩の力を抜いて読んでもらえると良い。
なぜ私は DDD に納得できないのか
以下の記事では「ドメイン駆動設計の課題」の章が立項されており、以下に示す指摘がされている。
- 学習曲線: DDD は、このアプローチに慣れていない開発者にとって、多大な学習努力を必要とする一連の概念と原則を導入します。
- 前払いの投資: DDD を効果的に適用するには、ドメイン知識の収集、モデリング、ドメインエキスパートとのコラボレーションに多くの時間を投資する必要があります。
- オーバーエンジニアリングのリスク: DDD のモデリングと抽象化の重視は、特によりシンプルまたは複雑でないドメインにおいて、オーバーエンジニアリングにつながる可能性があります。
これらは批判として個人的に納得でき、そして DDD に納得できない理由でもある。
これを踏まえつつ私の立場からどう見えているのかを主張していきたい。特に自分が納得できない点について述べる。
オーバーエンジニアリングに見える
小規模な受託開発ということを念頭に置いてほしいのだが、やはり CRUD で案外足りることが多いということである。
引用部分の指摘通り、DDD のモデリングと抽象化の重視は、特によりシンプルまたは複雑でないドメインにおいて、オーバーエンジニアリングにつながるという感覚を持っている。
ドメインが複雑でないのにもかかわらず抽象化されてしまうことで、その抽象化自体がソースコードの複雑さを増してしまっているケースがあると考えている。
別の観点だと、DDD のファイル分割やオブジェクトの分割は、その DDD の文脈を知らなければ複雑に見え、依存関係も不必要に複雑に見える。それが望ましいことに思えない。そもそも DDD の文脈を要求していること自体が認知負荷を増やしているのではないかという疑いがある。「キレイ」にしているというが、それを知らない者にとって雑然として見えるのではないか。
また、抽象化は作業負担としても大きい。本来は直接処理を書けばいいものを、わざわざ依存性を逆転させて抽象化している分、余計な作業等が発生している。またドメイン部分を抜き出すとは何をどこまでの範囲でやればいいかというのも簡単ではなく、受託開発の限られた時間の中で考えることが増えるというのも、キツそうという印象を受ける。
そして、そこまで投資しても投資に見合ったリターンが得られるか分からないように見える。
特に受託開発は納品後そこまで変わることはないので、プロダクト単位で見ると、競争力維持として常に変化し続けなければならないプレッシャーもない。
こういった観点では DDD はオーバーエンジニアリングに見える。
現実には完璧なドメインエキスパートなど存在しない
ドメインエキスパートとして理想的な存在は、今システム化したい業務とその課題(ドメイン)について理解しており、なおかつそれを適切な言語化とフィードバックができる存在のことだ。
受託案件の場合、それに当てはまりそうなのは顧客(法人)の中の業務担当者であるが、これが理想的なドメインエキスパートと言えるかというとかなり難しい。
今関心のある業務が必ずしも一人の担当者とは限らないし、背景となるデータ間のやり取りが、対象とする業務内に閉じていないこともある。つまり断片的な知識しか持ち合わせていない。
あるいは担当者が対象業務全体を理解していたとしても、それを言語化して伝える能力があるかは別問題である。実は重要な条件や課題があるにもかかわらず、それに無自覚あるいは内面化・暗黙知にされてしまっていて「わざわざ伝える必要のない情報」として伝えてもらえないこともある。
そして何より、そもそも顧客との打ち合わせで業務担当者が直接出てくることがない場合もある。
さらには営業を挟んだりして、実際のユーザーから何次も離れているケースだってある。
幸いにも自分の所属する会社は(人数は少ないが一次請けなので)開発者が直接顧客と話せるため、ドメインを理解しようとすればいろいろ聞ける環境にあるが、それでも最初に述べた本質的な難しさ(ドメインエキスパートが完全には頼りきれない)からは逃れられない。
つまり、DDD が求めるドメインエキスパートなど本当に存在するのか疑わしく、納得できていない。
なぜそれでも DDD を取り入れるのか
ここから、その批判を自分が持ちつつも、それでも DDD を取り入れる理由を述べたい。
まずはじめに DDD で個人的に誤解していたことから、DDD が本来議論されるべきポイント / 見るべきポイントを誤っていたことを話し、そこから AI の登場によりどう状況が変わったかを書きたい。
個人的な誤解の解消: DDD は「設計」というより「開発」思想かもしれない
DDD の記事を見ると「どのようにソースコードを管理し、クラス等をどう分離するか」という設計論の範囲内にとどまっているものが目立つ。DDD の初学者のうち、私のような安易な属性の人間は、記事で理解した気になる。にもかかわらず、「そんな抽象化して整理しても保ち続けることは難しいし、現実に即してない!」と反応しがちだ。
きっと本を読めばそこに重点を置かれていないことはわかるのだろうが、単にファイル構成や分割方法の話に見えてしまう。特に私はフロントエンド側での開発が多いので、やるにしても(アプリ全体ではなく)バックエンドの機能実装の"中に"閉じた話と捉えていたところもある。
最近になって私が実際に DDD を体感し、振り返りもやったことで理解したことがある。DDD の根底には「ソフトウェアは課題の解決であり、開発者は課題の理解と解決に集中して考えるべき」という思想がまずあって、その上での設計であることだ。
まさしく「ドメイン」から端を発して設計していく手法であり、ドメイン「駆動」である。
その上で、それを主軸に置いた設計はどのように構成すべきか、という方法論が出てくる。
この思想を考えると「バックエンドの機能実装の中に閉じた話」という誤解は解ける。ドメイン駆動設計の射程は、何かのビルド単位の中に閉じた話ではなく、アプリ全体の話である。
そしてソフトウェアの本質はその「ドメイン」にあるのだから、その表現方法(ウェブアプリ、スタンドアロンのネイティブアプリ等)に本来縛られる必要はなく、切り離して管理すべき、という考えから Domain や Use Case がモジュールとして切り離す話につながっていくのである。
これは単に機能や役割(フロントエンドなのか、バックエンドなのか等)でモジュールを分けるという発想でもない。まずドメイン理解に努め、それをテキスト(最終的にはコード)として表現することを重視する。
しかし、私にとってこの考えは盲点で、受託だと表現方法が先んじて決められがちである。そのあとで「要件 = 機能」を定義し、それを元に分割していく。ただ DDD は機能分割が第一基準ではない。ある業務の課題の理解と明文化を中心にしており、開発もその業務がどのようになっているかを理解しながらコードに反映することを起点にする。
そして究極的にはその業務の課題解決のベストとして、どの表現方法を採用するかをあとで選択しても良いのである。
そう考えると DDD は単なる設計論にとどまらず、開発思想まで波及する。DDD をやるために、そもそも開発のやり方自体を変えなければならない。
DDD の最後の D を Design ではなく Development にしてもらえれば誤解も減るのではないかと思うくらいである。
このように理想としてはわかってきたのだが、とはいえ DDD の難しさは依然として存在するし、そもそも開発文化そのものをこれまでと違うため浸透させるのにも時間がかかるだろう。
確かに思想に共感はできたものの、それが DDD を取り入れる理由にはまだ足りない。
生成 AI というゲームチェンジャー
DDD の私の納得できないポイントの一つはオーバーエンジニアリングによる過剰投資のリスクであった。そして、その投資を受託開発という締切のある時間の中で、そのコストを割ける気がしないという点だ。しかもそれが、誰もがわかりやすいコードになるならともかく、DDD という文脈を踏まえないと理解しづらい構造になっている。
ただこの考え、人間の私、あるいは他の人間がやるという暗黙の前提がある。
- 抽象化やそれに対する作業コストが高く思えてしまうのは、それを実装しようとしているのが人間だから。
- コードをわかりづらいと感じるのは、それをキレイと思わない多様な思想に基づいた多様な人間を想定するから。
つまり、私が「納得できない」「直感に反する」根拠として挙げた内容の一つは、実は暗黙のうちにコードを見るのも書くのも人間がやる前提であったからである。
しかし、昨今の生成 AI の能力と利用を考えると、少なくともこの点においては解消されている可能性がある。
AI は DDD を知っている
"知っている"という表現自体はいろいろなところから怒られそうだが、少なくとも AI の学習元データにはそれなりに DDD の記述が含まれているはずで、学習されている。
これはとても重要で、インターネット上の文献、おそらく DDD とは何か、どうすべきかの議論、そしてさまざまな実装例など、豊富な情報をすでに学習している。したがって、AI に DDD とは何かを聞けばそれなりの精度の答えが返ってくるし、それなりの精度の実装を返してくる。
重要なのは、AI が持つ知識が既に存在することである。「これは DDD で設計します」のようなコンテキストを与えるだけで、その方針に沿ったコード生成が期待できる。
一方、広く知れ渡っている典型的な設計方針ではなく、独自仕様でやっている場合は、その設計や思想をコンテクストとして詳細に与える必要がある。
これはかなり至難の業で、特に「なぜその設計方針なのか」という精神性を教えるのが難しい。また、コンテクストも穴がないように記述しなければならないが、欠陥なく規則を羅列するのは容易ではない。
DDD の場合は、AI が学習したであろう実装例に DDD の精神性が染み付いているはずであり、その結果として AI は DDD の精神性を理解したような振る舞いができると思われる。
これらのコンテクストの問題は、今のコードがどのようになっているかを説明させるときにも効いてくる。
仮に新しく入ってきた人が DDD を知らなかったとしても、AI は丁寧に解説することが可能だろう。DDD という単語にはコンテクストで詳細に与えれていなくとも、AI はそれに関連したさまざまな単語や事例を学習の中で紐づけられているはずだからである。
独自仕様の場合はコンテクストに書かれていることが全てであり、それ以上の説明はなかなか精度良くできないと思われる。
DDD を採用することで、AI は立派な伴走者にもなってくれるのだ。
AI は面倒な仕事を嫌がらない
DDD が面倒だと私が感じる主な要因は、そのルールにある。自分の意思で何の制約もなく自分で考えて自由に開発する楽しい体験を奪われていると思えてしまう。ただ、それは趣味でやればいい話で、仕事としては長期的な観点で、代替可能なコードであり良く知られた設計の方が望ましいというのもわかる。
とはいえ、ルールで縛られているというのは、開発全体が少し作業的で単調なものに感じられ、私としては我慢ならない。できるが、面倒である。
その点でいうと AI はルール通りの実装をこなすのが比較的得意だ。私のように面倒だ、嫌だと言わず、コンテクストと指示を元に数秒で実装してくれる。むしろ実装ルールの制約が厳しいほど暴走しづらいように見える。
仕様変更による書き直しや修正も関連ファイルが多くなるほど面倒で、DDD だとそれが多くなりがちだが、AI がいれば(見落としはあるかもしれないが)そんなに苦にならないで修正できるだろう。
そう考えると、AI によって、少なくとも私が DDD をやる上で不安 / 不便に感じていたことを低コストでやれる可能性がある。
「ドメイン」という人間のやる仕事
AI の登場による開発者の仕事の変化は、DDD という文脈から見るとむしろシンプルであるとも言える。 DDD でまさしく目指したいことである、「ドメイン」に集中すれば良いのだ。
我々は、顧客とのコミュニケーションや理解の検証により時間を割けるようにすべきであり、それは現状 AI には難しく、人間にしかできない部分である。
これは、DDD の問題点として指摘した「現実には完璧なドメインエキスパートなど存在しない」というものが、逆に価値を持ってくるようにも思う。ドメイン理解は価値のある仕事なのである。ドメインエキスパートの言語化できないことや暗黙知を、言語化 / コード化することが今後開発者に、より求められるだろう。
そう考えると、それを主軸に置く DDD というフレームワークは悪くないように思える。
(そして、これはアジャイル開発とも相性が良いかもしれない。)
さいごに: 我々の直感は正しいか
思い出してほしいのは、この私がなぜ最初に DDD から避けていたかということだ。あれこれ理屈として納得できない理由も述べたが、実際にはまず直感・感情の反応として良いものと思えなかったことだ。
正直、いまだに DDD に対する疑念は払拭されてないし、腹落ちしていない。
ただ、DDD が直感に反するのは、DDD が必要とされる事例にまだ出会ってないという、私自身の経験的なバイアスがあるというのは大きい。自身の浅い経験を信じて、巨人の肩の上に立たないのは少々軽率である。
また AI の登場とその扱い方も、人を雇うことと等価ではない。
AI を Copilot として使っていると人間に近い存在として感じるときがある。AI についても人間のアナロジーを使った説明のされ方もする。しかし、内部で動いているアルゴリズムや論理体系などが人間と同じであるわけではないので、人間の直感的で素朴な感想と、AI にとってそれが良いか悪いかは別問題であることを認識する必要がある。
- 人間にとっての良い / 悪い設計が必ずしも AI にとっての良い / 悪い設計と一致するわけではない。
- 人間の直感は AI の存在が前提としてないことがある。
- 「人間にとって 90 点でも AI にとって 50 点である設計」か「人間とAI どちらにとっても 70 点の設計」か。前者は人間にとっていいかもしれないが、後者の方が AI の支援を受けやすい。
だから、これまで使ってきた「人間の直感」という言葉をもう少し正確にすると、「AI が存在する前提が身体感覚にない状況での直感」という条件付きである。これが現在信用ならないのは AI を触っていればよくわかるだろう。
だからこそ、我々は取捨選択する際、理性で考えることが必要である。一旦直感を横に置いて考えてみること。そうしなければできない判断もある。
もちろん、理性で考えればうまくいくわけでもない。とはいえ、直感に反するからといって試さないことは、賢明とはいえないとも思う。
腹落ちしないながらも DDD を今後取り入れていく所存である。
Discussion