フューチャー技術ブログ

ドメイン駆動設計の源流のPofEAAを読んでみる

最近、ドメイン駆動設計(以下DDD)とかそのあたりを読みこんでいる人から、DDD本の読み方を教えてもらいました。ここではDDD本はエリック・エヴァンスのドメイン駆動設計の方を参照しました。

@katzchang さんから教わったのは「DDDはパターンランゲージの形式を意識してるよ」ということでした。ただし、きちんとしたパターンランゲージの形式になっておらず、記述が著者のものになってるので、読者は注意して読む必要があるのかもとのことです。

@ryoaitaさんから教わったのは「DDDはエンタープライズアプリケーションアーキテクチャパターン(以下PofEAA)を下敷きにしている本だよ」ということでした。

DDDももう時代的にはかなり古い本です。自分で読んだ限りは全然好きになれなくて、でもきっと何かあるはずだと3-4冊読んでみましたが感想は変わらずでした。ユビキタス言語も「当たり前のものを先頭に持ってきて、イエスセットのテクとして誘導してくる詐欺師のテクニックでは」と思ってたぐらいでした。DDDを理解するよりも、DDD本が出た当時のこの本の立ち位置とか成立の過程というのが最近は気になっていました。

本当はここで紹介する2冊(エリック・エヴァンスのドメイン駆動設計と、エンタープライズアプリケーションアーキテクチャパターン)が半額セールしているうちに書きたかったのですが、5月末で終わってしまったようです。残念。

パターンランゲージとして見る

パターンランゲージは、カタログ集の形式ですが、パターンを選ぶ基準を決める「フォース(場)」が大事です。パターンは順番に適用していくものではなく、その状況にあったものをピックアップして使う、という使い方をします。フォースが合わなければ使っても意味なかったり、逆効果だったりします。なので、基本的にそこに入っているものをすべて適用するということはしない、というのがパターンを意識して書かれた本を読むコツです(XPは全適用が基本ですが)。

モデリング周りのパターンはこんな感じです。DDD本の裏表紙の折り返し部分に書かれているのを引用しました。境界づけられたコンテキストとかあるけど、基本的にはマージできないコンテキストは分けて開始するけど、徐々に統合していくよ、という流れのように見えますね。レガシーシステムラッパー(腐敗防止層)もいつかはリプレースする想定でしょうし。汎用サブドメインはどこの会社でも同じような「銀行振込」みたいなわざわざモデル化すべきでないものだと思うし、統合されたコンテキストとその中で実現するコアドメインというのが最終進化系な気がしますね。まあ単一のモデルで実現できるものであれば、わざわざ分ける必要ないですものね。

スクリーンショット_2022-06-03_8.05.54.png

本文はXPを想定してUMLみたいなモデルを作らずにコードでモデルを表現する方法を推していて、補足的な方法としてアナリシスパターンとか、UMLも紹介していますね。モデリング周りのパターンは、この「単一のモデル(を含むコンテキスト)」をスケーリングする方法として書かれている、という読み方をすればいいということですね。肝心のモデリングする部分が「ドメインエキスパートに聞いてコードに書いて洗練する」とか程度で方法論として薄いなぁ、というのも今までDDDに持っていた不満ポイントでした。

が、DDD本の出版当時に多数あった「既存のモデリング手法」をスケーリングさせるパターンであった考えれば、理解できます。問題は、20年ほど前に流行ったさまざまなモデリング手法が現代で失われてしまったということぐらいですかね。

ちなみに、XP的な設計手法を使う前提だとしても、この説明だけでは実現できず、他のXP本の力が必要でしょう。4重のイテレーション、フィードバックの仕組み、ストーリーなどを使った要求のマッピングなど、お客さんの言葉を引き出すテクニックがきちんと形になっているのがXPですし、メタファーを使って再現とかコードにする前にきちんとチーム内でコミュニケーションする方法論になっていますが、DDD本はそこを端折っています。まあ他の方法論同様、XPをみんなが知っている(という時代だった)という前提だったんだろうな、と思います。

実装周りはこんな感じです。DDD本の表紙の折り返し部分に書かれているのを引用しました。モデルをコードとして表現するには、エンティティ、サービス、値オブジェクトで表現するとありますね(図はモジュールも矢印が伸びているが5章の本文では3要素のみ)。ですが、これらのパターンはどれもふわっとしか書かれてなくて、詳細がいまいち分かりませんでしたが、ここでPofEAAを召喚すると良さそうです。

スクリーンショット_2022-06-03_8.03.08.png

PofEAAのドメインの表現手法のパターン

DDD本で書いてあるコードの部品のパターン名と似たものがDDDにはあります。こちらの方が詳しく説明されているので、DDDの説明を補完するにはこちらも合わせて読むと良さそうです。マーチン・ファウラーのエンタープライズアプリケーションアーキテクチャパターン(PofEAA)には、ドメインロジックの構築方法として、3つのパターンが紹介されています。

DDD本が選んだのは、この中のドメインモデルです。DDD本はエンティティと値オブジェクトと書いていますが、ドメインモデルという言葉では表現していません。ドメインモデル(オブジェクトで表現)という形式に、エンティティと値オブジェクトを重ねている状態かと思います。他の物は重ならないですし。

で、PofEAAはドメインを表現する手段としてはバリューオブジェクトの紹介はしておらず、ドメイン関係ないネジ釘を紹介する「ベースパターン」の中にいます。エンティティという言葉はないですが、12章のオブジェクトリレーショナル構造パターンという章まるごとがエンティティを扱っています。PofEAAでは、実装手段(バリューオブジェクト、OR構造パターン)と、ドメインロジックを持つオブジェクトである、という情報は直交したものとして扱われていますね。

DDD本はテーブルモジュールには触れず、トランザクションスクリプトはアンチパターンで、ドメインモデルが正義のように説明していますが、PofEAAではそれぞれのメリットとデメリットがフラットに紹介されています。トランザクションスクリプトもシンプルでいいよと説明されています。でもって、実装手段とドメインロジックを持つもの、といのが別の軸のものという紹介を省いて、値オブジェクトとエンティティを「ドメインを表現するもの」と紹介してしまっているようです。つまり、ドメインを表現しない値オブジェクトとか、エンティティなんてものはないぞ、という誤解を生み出す源泉はこの魔改造にありそうです。

このあたりとか、DDDとPofEAAの関係は次のエントリーが詳しいです。

DDD本は、すごくシンプルな事例(Ruby on Railsでさっと作ったアプリ的な)向けに、そのシンプルな状況に耐えうるミニマムセットのパターンを取り出し「ドメインを表現するならこの部分に込めるといいよ」と抜き出して説明しているんだろうな、という気がしてきました。ただ、抜き出す基準が、15年前のブームになっていたJava文化基準でピックアップしたのかな、というあたりが気になりました。

ソフトウェアエンジニアリングは全然エンジニアリングじゃない

オブジェクト指向だって、言語によって機能が異なり、同じようなソフトウェアを作る場合に出来上がるクラス構造とかが大きく変わってきます。例えば、DIなんかはリフレクション前提でしょうしね。クラス図ときれいにマッピングできるようなモデルがあって、上流から下流までうまく繋がるというのは幻だったということです。

現在行われているソフトウェアの設計という行為は、レイヤーを絞り込んで、その中だけで行われています。

  • データベースを中心として設計を行うデータ中心設計(DOA)
  • データベースとかフレームワークを切り離しでアプリケーションコード中心に設計するいくつかの方法論
  • ゲームではシーングラフの上で動くアクターを中心にしたイベント駆動

そのレイヤーを定めるのは土台となってるフレームワーク次第なので、フレームワークごとのベストプラクティス的な立場に収まってしまったと言えます。「汎用の設計手法」というのはなくて、土台となる技術が変わって来れば設計手法も影響を受けて変わるということです。

以前、歴史学を専攻している知人から歴史学のエコシステムを教えてもらったことがあります(もう10年以上前の話ですが)。歴史学では遺跡から出た出土品とかさまざまな資料をもとに、仮説検証をおこなって当時の姿を再現したモデルを作ります。で、新しい発見があると、それをもとに新しいモデルを作り直します。特に情報の少ない古代史になればなるほど、1つの発見で既存のモデルが大きく書き換えられていきます。これって、ようするに、自然科学の発展のような過程を何度も何度も繰り返していると言えます。なぜ神の手事件が大きな問題として扱われたのか当時はよくわからなくて「歴史書のそこの記述をちょっと直せばいいだけでは」とか思っていましたが、「そのページ以降すべて書き直し」というインパクトがあったのだな、とそれを聞いて初めて理解できました。

20年ぐらい前に流行ったオブジェクト指向な方法論とかも、当時のJavaとかを想定して組み上げられた方法論ですので、同じような探求活動を、クラスはあるけどほとんど使わない今のTypeScriptとかに対して行えば、当然別の発展が得られるかと思います。歴史学と同じようなリビルドがソフトウェア開発にも起きうるべきですし、ソフトウェア工学の大部分は人文科学なんだなと思います。

プロパティベーステストとか、SIerあたりでよく出てくるソースジェネレータ開発とかスキーマ駆動なやつとかそのあたりは工学感ありますが。パターンランゲージはいい線行っていると思いますが、デザインパターンとかもC++98以前の30年前に伝えられた姿のままでバージョンアップされずに固定化されてしまっているのですよね。パターンは有機的なもので発展し続けるのを想定していたのかもしれませんが、XPのパターン数も12→13→24(11+13)→19だったか変化し続けて、Clean Agileはケント・ベックとまた別の13だったりするが、XPについて触れた記事もどの時代のものについて触れているか情報が失われて議論が発散してしまった感じがあり、パターンランゲージにバージョン番号をつけて改訂していく文化がなかったのが残念だなと。

余談ですが、世の中の「オブジェクト指向」は基本Javaを想定していますが、個人的にはprivateの概念はRubyの方が好きですね。同一インスタンス以外には見せない。C++の「お前のものは俺のもの」という悪いカツアゲしてくる「トモダチ」もひどい概念ですね。

令和時代のDDDを妄想してみると面白いと思う

パターンランゲージについては最初の方に説明しました。パターンは基本的に数が多ければ多いほど、その組み合わせでたくさんの場面に活用できるというものです。比較的多くのパターンを並べていて網羅的に書かれているPofEAAのパターンも、時代に合っていないもの、その後登場して入るべきであろう、というものもありますし、仮に利用可能なパターンがあっても、そのフォースも、20年の歴史の中で大きく変わっています。当然、それをもとに組み上げられてきたDDDはさらに大きな変化があるはずです。

特に、最近のクラウドネイティブなFaaSを駆使したピタゴラスイッチ的なやつ。あれとか旧来のDDDとかだとオーバーヘッドが大きすぎると思うんですよね。モデルはデータベースの構造として表現して、トランザクションスクリプトにドメインロジックとか、そういうのに合わせたDDDとか、いろいろ新しい形が模索できるんじゃないかと思います。

PofEAAで特に古さを感じたのは。ウェブアプリケーションのフロントエンド周りの考え方で、CGIとかそういう時代も考慮したものでSPAとかそういう時代ではないのですが、そういうあたりは微笑ましいなぁ、という感じで読めます。あと、DBにXMLとかを文字列で入れる、みたいな話はJSON型ネイティブサポートとかで解決されるものとかあったりとかするなって思ったりもしました。まあ、このあたり、年長者の人と一緒に読書会でもして、「昔はこうだったけど今はもうこうじゃないよ」とアンラーニングしながらPofEAA本を読むのも良さそうな気がします。