DDDの正体は実装パターンとモデリングの組み合わせ

@Panda_Program

PoEAA を通して DDD の半分を理解する

マーティン・ファウラーの PoEAA を読んでから、DDD のことを考え続けている。今まで DDD の話題はあえて避けてきた。分厚く難解な書籍、増えるコード量、教祖とその信徒たち(MV)、全てをその視点から解釈しようとする試み、少しでも間違えたら求められる自己批判、無知な者に対する SNS 上のオルグ、いつまでも出てこない総括、それでも信じるものは救われる。「一匹の亡霊がIT界隈を徘徊してる。DDDという亡霊が...」

まあ早まらないでほしい。何も DDD こき下ろそうというわけではない。自分の実力不足が主な原因と思い、深入りする前から「わからないもの」と決めつけていた DDD は、PoEAA というライトに照らされてその姿を私の前に姿を表し始めた。それは亡霊ではなく、確固たる手触りのある実体(Entity)だったのである。

PoEAA は 1990年代の開発現場でのオブジェクト指向の実装パターンをまとめた書籍だ。この書籍のある一文に「エリック・エヴァンスがオブジェクト指向の本を書いている。原稿を読ませてもらったがいい本になるだろう」と書かれている。それが世にも名高いDDD本である。

PoEAA には、「Value Object」「サービスレイヤ」「ドメインモデル」「レポジトリ」など、OOP の実装パターンが掲載されている。現代では当たり前になったこれらのパターンを学び直すには最適だなと思いつつ、ふと思い出した。DDD でもこれらのパターンを使っていたではないかと。

手元にある「ドメイン駆動設計 モデリング/実装ガイド」の目次を開くと、第6章の見出しには「エンティティ」「値オブジェクト」「ドメインサービス」「リポジトリ」「ファクトリー」とある。

マーティン・ファウラーは、「自分はパターンを考案したのではなく、当時の開発で使われていたパターンを PoEAA にまとめただけだ」と書いていた。そして、冒頭のエヴァンスの本に対する感想から、DDD 本は PoEAA の後に出版されていることがわかる。つまり、DDD は PoEAA に含まれているような当時の OOP 開発のベストプラクティスを活用しているのだ。

さらに、DDD Reference の日本語版の謝辞(有志による翻訳) の末尾に、「本の出版から数年後に、ウォード・カニンガム が パターンレポジトリ(Portland Pattern Repository)の仕事の一環として、 DDD 本の要約をクリエイティブ・コモンズで公開することを提案した」との記述がある。

つまり、DDD の半分は実装パターン集だったのだ!もちろん知ってる人は知っている。ただ、自分がこの数年抱き続けていた「DDDとは何か」という疑問が解消されたプロセスを記しておきたい。

ではもう半分は何か。それはドメインに対するモデリングである。実は、冒頭で書いた総括がないというのは嘘だ。PIXTA のラジオ texta.fmの第1回 「 Software Development in 2003 」で、@t_wada 氏が「DDD 本が出版されたのは2003年。だから実装方法は古くなってしまった。しかし、この本は開発者の意識を業務ドメインに向かわせ、ソースコードをインプットにして開発後にもモデルを洗練させるフィードバックループを提示したことに意義がある」と話している(29:53 ~ 34:09)。

このラジオはもっと前に聞いて覚えていた。だから、「DDD の半分はパターン。もう半分はモデリングの話」とわかったのだった。DDD の半分は実装パターンであるということについて、DDD 本の要約である DDD Reference と DDD Quickly を参照しながら紹介する。

DDD の半分は実装パターンである

DDD の図の実装パターンを表したしたところ

これは、DDD Reference に掲載されている図だ。赤い囲みは私が書いている。この囲みの中の要素こそが、DDD における実装パターン集なのである。DDD Reference では、実装というものはこれらの「ビルディングブロック」を組み合わせだと書かれている。そして、OOP の熟練の開発者にはこのような感覚がある。

また、TDD で開発していると「OOP とは、まず信頼できるシンプルなオブジェクトを作り、それらを組み合わせてやりたいことを実現する手段だ」と理解できる。ブロック(オブジェクト)をビルド(組み立て)するのが開発なのだ。

しかし、パターン集だけでは複雑なドメインに立ち向かうソフトウェアを構築することはできない。パターンはある課題とそのコンテキストを考慮しないと、丸い穴に四角い杭を打つように不適切な使い方になってしまう。盲目的にパターンを使って組み上げても、出来上がったものが砂上の楼閣であれば意味がない。

DDD Quickly では、このことを以下のように表現している。少し長いが重要な箇所なので引用する。

ソフトウエアの設計は家を構成するのに似ています。 いわば全体的な展望を作る作業です。一方、コードの設計は詳細部についての作業であり、どの壁にどの絵画を掛けるのかを決めるような作業です。 もちろんコードの設計はとても重要な作業ですが、ソフトウエアの設計のような基礎となる作業ではありません。ほとんどの場合、コードの設計上のミスは簡単に修正できますが、ソフトウエアの設計上の失敗を修正するには、多くのコストがかかります。絵画をもっと左側に掛けるのと、家の側面を取り壊して今までとは違うように改築するのはまったく違う作業です。しかし、優れたコード設計なしによい製品は完成しません。だからこそコード設計のパターン集を手元に置き、必要になったら適用します。 優れたコーディング技術は、きれいで保守しやすいコードを記述する手助けをしてくれます。(DDD Quickly, p.5-6。太字は筆者)

つまり、ソフトウェア設計は全体に関わる物である一方、コード設計は細部の作業である。コード設計は細部のものといえども、疎かにしてはならない。このため、細部の表現であるコードを設計する優れたパターンを使おう。それは、Entity や Value Object などのDDD で紹介している OOP の実装パターンなのだという論法だ。

やはり DDD の半分は実装パターン集なのだ。

「戦術的 DDD」「軽量 DDD」の名前の由来について

なお、DDD が紹介しているパターンを用いて実装をすることは、「戦術的DDD」「軽量DDD」と呼ばれている。確かに、DDD Reference には 1ページ目に Strategy(戦略) と Tactics(戦術) という単語が使われている(Tactics and strategy must be combined to succeed, and DDD addresses both tactical and strategic design.)。

戦略は目的を持った計画立案であり、戦術はその実行に相当する。戦術は戦略より下位の概念であり、DDD ではパターンを用いた実装を戦術、ドメインに対するモデリングを戦略と対応させているようだ。そこから「戦術的DDD」という単語はそのあたりから来ているように思う(おそらく原著の DDD 本にも戦略や戦術といった単語が登場するはずだ)。

そして、専門家との対話を必要とし、絶え間ない洗練を必要とするモデリングより、開発者に閉じて手を動かせばいい実装の方が軽いという感覚が「軽量DDD」という単語を生み出したのだろう。

DDD のもう半分はモデリングである

さて、DDD のもう半分はモデリングについてである。この辺りはまだ自分の中で消化しきれていないため、簡単にだけ今現在の自分の理解を紹介する。

DDD の図のモデリングを表したしたところ

ドメインとはある複雑な業務領域である。その領域で仕事をする人は、ドメインについて知っている。その人をドメインエキスパートやドメインの実践者(domain practitioner)と呼ぶ。

そして、ドメインに対する理解、つまりモデルはドメインエキスパートの頭の中にある。しかし、あるドメイン実践者の頭の中にモデルがあっても、他の人には伝わらない。特にソフトウェアの開発者(software practitioner)がドメインのことを理解しないと、ソフトウェアを設計できない。

特定の業務領域には特有の概念を表す専門用語がある。開発者はドメインエキスパートに寄り添い、彼らと共通言語を使う(ユビキタス言語)。これによりドメインエキスパートと開発者によるコミュニケーションの基盤を確立し、意味の一貫性を保証する。コードのクラス名や変数名にもユビキタス言語を使う。

さらにこのユビキタス言語を用いて、ドメインに関する重要なことを形式化する。形式化の方法は、UML でユースケース図やドメインモデル図を書いたり、文章でもいいし、ポンチ絵でもいい。

最初はドメインに対する理解が浅く、大したモデルにならない。しかし、専門家との対話を重ねることで、ドメインに対する理解が深まる。結果、モデルが洗練されていく。開発、対話、モデルの洗練、開発、モデルのコードへの反映、また対話、モデルの洗練、開発、モデルのコードへの反映。この繰り返し(イテレーション、フィードバックサイクル)がより良いモデルを探求することにつながる。このあたりはアジャイル開発と親和性がある。

モデルを起点として開発は進んでいく。モデル駆動設計というワードが図の中心部にあることから、業務ドメインのモデルとその洗練こそが DDD の本質といえるだろう。

DDD の図のモデル駆動開発の要素

この辺りの説明はまだ読み終えていないので、今書けるのはここまで。

なお、DDD という単語こそ使っていないものの、請求書のソフトウェアを開発している LayerX 社ではエンジニアが簿記を学んでいるそうだ。これこそまさにエヴァンス氏がエンジニアに対して求めていた姿勢と言えるだろう。

本記事の内容は知ってる人にとっては当たり前のこと

ここまで「DDD の正体」と大仰に書いてきたが、何て事はない。知ってる人にとっては当たり前のことだ。だって「ドメイン駆動設計 サンプルコード&FAQ」の冒頭にこう書いている。

DDDの目的は、「ソフトウェアの機能性と保守性の両方を高めること」です。(中略)

そのために、DDDでは次のアプローチを行います。

①ドメインエキスパートと共に行うモデリング

②頻繁なモデルの更新に耐えられる実装パターン

(中略)

2つのアプローチは「ドメインモデル」でつながっており、一緒に適用するとより大きな価値を発揮するようになっています。

まさにDDDを端的に言い表している。

さて、ここまで辿ってきて一つ素朴な疑問が湧いてくる。それは「使う人はドメインの専門家だ。それなら、その人が作ればいいのでは」というものだ。だが、話題があちこちに飛んでしまうので、この疑問の深掘りは別の記事に譲りたい。

なお、この記事の公開3日前に書かれた「ドメイン駆動設計の源流のPofEAAを読んでみる」という記事も面白い。同じ時期に同じ過程で似たようなことを全く別の場所で考えている人がいることに驚いたので最後に紹介しておく。

DDD を学ぶための資料

まず DDD の原著に当たるのではなく、DDD Reference と DDD Quickly を読むとそのエッセンスを感じ取ることができるだろう。IDDD 本は評判が良い(が私は未読)。

実装で困ったら下記の2冊をおすすめする。

DDD Quickly は友人の @TSUCHIYA_Naoki に教えてもらった。松岡さんの本は同僚が勧めてくれた。感謝。

Happy Coding 🎉

パンダのイラスト
パンダ

記事が面白いと思ったらツイートやはてブをお願いします!皆さんの感想が執筆のモチベーションになります。最後まで読んでくれてありがとう。

  • Share on Hatena
  • Share on Twitter
  • Share on Line
  • Copy to clipboard