日々常々

ふつうのプログラマがあたりまえにしたいこと。

ドメイン駆動設計に関する何か

2020-03-13追記: 「ドメイン駆動設計」のハードルを上げる意図はありません。そもそもそんな特殊技能でもないと思っています。「ドメイン駆動設計が合っているか」を測る材料になるかも?くらいの気持ちで読んでいただけると幸いです。

何度目か知りませんがDDDがまたブームを迎えているようで。DDD難民と言う言葉が出た頃を思うと感慨深いですね。実際難民になったわけではないので肌感覚で知らないのが残念なところですが、これはどうでもいい。

DDD、日本語ではドメイン駆動設計となりますが、DDDを冠していてもドメインが語られることは少ないようです。 数ある書籍もドメインモデリングの話ではなく、ドメインモデルをいかに実装に落とし込むかにフォーカスしていると感じています。

これはこれで仕方ないと言うか、ドメインの話って広く語れないんですよね。 ドメインは領域で境界があって範囲が限定されています。特定ドメインの話をすると、それは「DDDの話」ではなく「そのドメインの話」になります。ジレンマ。

仮にドメイン駆動設計を突き詰められ、特定ドメインの「正解」なドメインモデルが作成できたなら、きっと出来上がるのはDSLです。 DSLドメイン特化言語と言うとどうしても何かしらのコードをイメージしてしまうでしょうが、GUIでの設定やモデリングツールもDSLと見なすことができます。 DSLを使用してドメインを記述する物の実例があります。パッケージ製品と呼ばれるものになります。 幸いなことに、様々な業務のパッケージ製品や、サービスが存在します。

と言うことで ドメインモデリングの力を着ける高速道路は、既存のパッケージ製品やサービスがドメインをどう捉えているかを学ぶことです。 参照して自分なりにでも写経すれば、いかに現実の複雑なドメインモデリングしているかがわかってきます。数を見ればパターンも見出せるでしょう。量は質に転嫁する。かも知れない。

1冊の本を読んで「あらゆるドメインの明確なドメインモデルが描けるようになる」なんてことはないと思います。あったら教えてください。

話はいきなり変わりますが、DDDと非DDD(レイヤードアーキテクチャ)のモデルを描いてみました。上がDDDで下が非DDDです。

f:id:irof:20200308234108j:plain

以下、図の中のモデルを指す時は「DomainModel」など図中と同じ英字の記述を使用し、「ドメインモデル」などの表現は図に閉じないものを指すことにします。

矢印は依存線です。依存先が変わったら依存しているものが影響を受けます。

アイコンはネクタイがドメインエキスパートで、ディスプレイが開発者です。 DomainModelは「ドメインに対する認識」くらいに捉えてください。使用する道具はなんでも構いません。 私の使う「モデル」に違和感があれば モデリングのきほん を参照してください。 モデルそのものは表現手段の制約を受けず、文書だろうと図だろうと口頭だろうと、モデルはモデルです。 違和感が拭えない方はDomainModelを「ドメインモデル(脳内)」くらいに読み替えてくれるのがいいと思います。

DomainLogicはApplication内のDomainModelの表現です。これを「ドメインモデル」と呼ぶのが一般的かもしれませんが、私のモデルの認識は前述の通りなのでこの場は許してください。 主にコードで書く部分なのでDomainLogicと呼称していますが、実態はコードの字面だけでなくパッケージ構成やコメントなど、使える物は何でも使ってDomainModelを表現する概念です。 この辺りは「コードをどまんなかに」の「説明できるコード」に該当します。コードの表現力は高くもないですが、そこまで低くもないのです。

ドメインエキスパートしかDomainに直接は関わりません。 開発者はDomainを知りたいですが、Domainには直接触れないのでDomainModelを通じて理解することになります。絵の黄色部分です。 開発者はDomainそのものには触れず、ドメインエキスパート(人に限らず、例えば書籍もドメインエキスパートです)と共にDomainModelを構築します。 仮に自社サービスなどでドメインに直接触れる場合、ドメインエキスパートのロールを演じることになるでしょう。この場合はドメインエキスパートと開発者は同一人物になりますね。

DDDだろうとなかろうとドメインエキスパートと会話してDomainModelを構築する必要は必ずあります。

f:id:irof:20200308235810p:plain

https://twitter.com/irof/status/1236635125460299776

どのような開発スタイルであろうとも、開発対象(ドメイン)は必ずあります。ある、はず。私が思いつかないだけかも知れないけれど、あるってことにして進めます。

Presentationは使い勝手の影響を受けます。 Infrastructureは使用している実装技術やミドルウェア(ここではBackendService)の影響を受けます。 これらを一緒くたにすることは少ないと思いますので、どちらも分けています。

レイヤードアーキテクチャ(図の下側)が厳しくなるのは、各レイヤーにドメインの知識が散るだけでなく、それぞれが他にも依存するので解決すべき問題が入り混じるからです。 PresentationもInfrastructureもそれだけで複雑性を抱え込みます。そこにドメインの複雑性も持ち込んだ結果が、よくあるFatControllerなどが抱える負債です。 このスタイルだとDomainModelはシステムに依存しない形で構築されることになります。いわゆる上流工程と呼ばれるところで、Applicationと関係なく、書面やホワイトボードで出来上がることでしょう。

「ソフトウェアアーキテクトが知るべき97のこと」の「本質的な複雑さは単純に、 付随的な複雑さは取り除け」に次のようなくだりがあります。

もともとは、数千機もの航空機をコントロールするという本質的に複雑な問題に対処するために作られたものですが、このソリューション自体が複雑になっています。

ソフトウェアアーキテクトが知るべき97のこと

ソフトウェアアーキテクトが知るべき97のこと

  • 発売日: 2009/10/05
  • メディア: 単行本(ソフトカバー)

散らばったDomainLogicは、ソリューションと密結合してしまうでしょう。これにより「システム都合でドメインの変化に追随できない」と言うことが起こります。私もいくつか見たことがありますし、作り込んでしまったこともあります。開発者として「そう言うもの」とは言いたくありません。現実は厳しいけれど、諦めたくない領域です。 私の認識するDDD(図の上側)では、DomainLogicを他のレイヤから独立させます。 これによりDomainLogicはDomainModelにのみ依存する形となり、前者の複雑性の絡み合いによる乗算から逃れられます。 DomainModelの知識を引き込む際にPresentationやInfrastructureの複雑性に振り回されずに済むようになるため、DomainModelとの齟齬が抑えられます。ゼロになるとは言わない。

DDDを冠する話題でApplicationの中の話しかされていないことにもどかしさを覚えますが、それなりに理由もはっきりしています。

  • ドメインそのものの話はしづらい。特定ドメインに特化した話はDDDの話ではなくなってしまいます。
  • ドメインの噛み砕きであれば、要件定義手法などになります。私はRDRA推しですが、手法は山ほどあります。
  • エリック・エヴァンスのドメイン駆動設計に「実践的モデラー」があり、よく知られる書籍も実装技術の話に終始しているように見える。

ドメインで設計を駆動する(絵の黄色部分)あたりの話があまりされないのは当然と言えば当然。残念。

特にDDDの書籍、例えば先日発売された「ドメイン駆動設計入門」などがコードの話に多く割くのは、DDD以前に「そうは言ってもコードにドメインを持ち込むのは夢物語だ」と、これまで付随的複雑性の混濁したコードに慣らされたり、現実の重圧に押し潰されそうになっていたりと言った方に、現実感を持たせる必要があるからなのかなと思っています。

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本

ドメイン駆動設計入門 ボトムアップでわかる! ドメイン駆動設計の基本

  • 作者:成瀬 允宣
  • 発売日: 2020/02/13
  • メディア: 単行本(ソフトカバー)

ドメイン駆動設計の入門と言うよりは、「C#による"エリック・エヴァンスのドメイン駆動設計"入門」のように感じました。)

増田さんがリポジトリ名をisolating the domain(ドメインを独立させる)としているのは、おそらくサンプルリポジトリで語れるのはドメインを独立させる方法だけであり、DDDのサンプルではないからだと思います。確認していませんが(←)。 なお、DDDの片鱗はコミットログにあります。対象ドメイン、ここでは勤怠管理のドメインエキスパートとして、実際に勤怠管理を行っている人へのインタビューや社労士向けの書籍、労働基準法などを参照しながらの現実との試行錯誤、付随的な複雑さの排除を繰り返しており、きっとどこかに埋もれています。コミットログだけで完結させるようなルールは敷いていないので、片鱗とだけ。読み取れるかどうかは知りません。

ドメイン駆動設計の修得に向けて

ドメイン駆動設計だけを勉強してもドメイン駆動設計はできるようになりません。

ドメインを動力として力を伝えるためには、対象ドメインへの関心を持たねばなりません。ドメイン駆動設計をやりたい(と言う表現もなんだかな、ですが)なら、一つ質問があります。「貴方が現在扱っているドメインドメインの言葉で説明してください」……ラバーダッキングで構いません。これができないのであれば、まずドメインを知ろうと思うところからです。ドメインモデルの構築(図の上下共通する黄色部分)は「ドメイン駆動設計」かどうかに依存しません。

ドメインの知識が不要な開発もあります。例えば要件定義/設計/開発/テスト/運用のように工程分断されている場合、他の知識は無くてもなんとかなる、と言うか、ノイズですらあり得ます。工程を分けることで扱う問題の性質を変え最適化を行っているので当然です。近年は諸悪の根源のように語られる工程分割ですが、妥当な文脈もあります。プロセス自体に善悪はありません。あるのは合う合わないだけです。

もし自身がドメインを全く知らないし、知ることに興味がなく、知っても価値がない(知ることで収入が増えない)のであれば、ドメイン駆動設計を目指すのは時間の無駄だと思います。仮に形はできるようになっても、ドメインの動力を受ける最初の部分がない状態になりますので。

この前提を満たした上で、ドメインと設計を連動させる仕組みが必要です。ここを繋ぐのがドメインモデルとドメインロジックの関連です。エリック・エヴァンスのドメイン駆動設計の実践的モデラーから引用します。

コードを作成する人々がモデルに責任を感じていない場合や、アプリケーションのためにモデルを機能させる方法を理解していない場合、そのモデルはソフトウェアと無関係になってしまう。コードを変更するとモデルも変わることを、開発者が認識していない場合は、開発者によるリファクタリングによって、モデルは力を増すことなく、むしろ力を失うことになる。

コードの変更理由がドメインモデルでなければ、コードのモデルとドメインのモデルは解離していきます。ここをのギャップを可能な限りなくす(完全になくせるとは言わない)ことにより、図で示しているDomainModelとDomainLogicの連動が現実味を帯びてきます。

ドメインに駆動されたドメインモデルと設計を連動させることにより、ドメインへの理解が深まったりドメインが変化することによるドメインモデルの変更に追随するようになります。駆動する、力のあるモデルがでてきます。

実践的モデラーで思い出したのが、組織パターンの「アーキテクトも実装する」です。アーキテクチャの抽象と実装の解離に対応するパターン。実践的モデラーで語られてるものと似ているなと。分たれてしまったものを再び結びつけるのに同じ人の脳に詰め込んでしまうのは、一つのパターンなんでしょう。

ドメイン駆動設計で語られる実装技術は、Applicationの部分に過ぎません。DomainLogicをどのように作るとDomainModelとの解離を避けられるか、そのいくつかの方法が示されています。どうしてもパターンカタログは「それで全てである」かのような誤解を与えてしまいますが、例えば「リファクタリング」にも掲載しているものは一手法であり今後も発見されることを期待していると書かれています。ドメイン駆動設計の実装パターンは無数にありますが、いずれも実装制約によりモデルが力を失うことを避けるための手法に過ぎません。一昔前のGOFデザインパターンブームの頃にあった「このパターンだからヨシ!」を繰り返してはいけません。

f:id:irof:20200309114938j:plain

と言うことで、ドメイン駆動設計文脈で語られる実装技術は、前段このドメインと設計を連動させる際の受け皿の一実装です。上の図の右下のところ。「ドメイン駆動設計のコアドメイン」ではありません。無ければ片手落ちの理想論に終わってしまうので重要ではあるのですが、いずれもドメイン駆動設計でなくても使える技術、使われてきた技術であって、それが適合するから採用されているだけと言うことは理解しておかないと、実装技術の引力に負けて「これをするのがドメイン駆動設計だ」と実装技術部分だけで完全に理解したと思ってしまったり、「ドメイン駆動設計だからこう実装しなければならない」と余計な制約を抱え込んだりして、モデルが力を失います。これは笑い事ではなく、実際起きている現実です。

ドメイン知識を得る方法はドメインに強く依存します。ドメインエキスパートへのインタビューで得られるかもしれませんが、ドメインエキスパートなんてそうそう存在しません。その時は自身がドメインエキスパートになるくらいの気持ちは必要です。なお、業務システム限定で使える普遍的なとっかかりは、金と法律です。あくまでとっかかりなのでブレイクスルーは何度か起きますが。