ドメイン駆動設計(DDD)を二つに分けるのは、大切なとこが抜けるのであまり好きじゃない


ステークホルダーと話し合いは必須！とかではなく、アプリケーション実装の観点です。

DDDもある程度普及してきたので、個人的に感じることを。後半はポエム。まずは、分ける二つを定義するところから始めたいと思います。

# 二つに分ける

この辺りは「ドメイン駆動 戦略 戦術」で、ググってもらうのが一番ですが、ざっくりわけると下記のようになります。

* 戦略的設計
* 軽量DDD/戦術的設計/ボトムアップ (以下軽量DDD)

さらに、ざっくり定義していきたいと思います。

### 戦略的設計

* ドメインエキスパートの会話。ビジネス用ドメインの精錬。
* コアドメインの規定。コンテキスト境界。

と、ドメインを中心とする考え方、システムの分割統治の文脈がメインになります。

### 軽量DDD

* エンティティ/バリューオブジェクト/サービスなどのコードパターン
* DIPを適用したレイヤードのパターン

と、アプリケーションのパターンが文脈になります。

# 「好きじゃない」理由も二つ

まあ、うまく分けてるじゃない。と感じるのですが、この分け方があまり好きじゃありません。二つの理由があるので、一つずつ説明して行きたいと思います。

1. "どちらか"を選択する傾向がある
2. 重要な要素がすり抜ける

## 1. "どちらか"を選択する傾向がある

これは分かりやすいかなと思います。

「戦略的設計は、私達ハードルが高いので、軽量DDDとして取り込みましょう。」

もちろん
「全くDDDを取り入れないよりは、軽量DDDでも取り入れてくといいよね。」という、宣伝的な効果はもちろんあるのですが、択一論になりやすくなってる気がします。

「軽量DDDをするだけなので、戦略的設計はしない。」とか。非常にもったいないです。

これらはバランスの問題だと考えたいですよね。「ステークホルダーとの距離があるなら、自分達なりにビジネスドメイン考えてみようか？」「コンテキスト境界とか分解するのは難しいけど、最も重要な要素を意識合わせしよう。」と、取り組んでいくべきかと思います。

なぜかというと、次の理由につながっていきます。


## 2. 重要な要素がすり抜ける

二つ目の理由は、重要な要素がすり抜ける。それは、

「 **ドメインを中心** に考えることで、**ドメインロジックに規律** を定める。」

です。

ドメインロジックなので、アプリケーションの実装の話になります。広義に言えば、軽量DDDに含まれる話になりそうですが、ドメインを中心と捉える思想は、戦略的設計に含まれます。そのため、二つが重なるこの概念は、どちからも抜け落ちてしまいます。

軽量DDDは、"ドメイン"から離れる文脈として使われることが多く、 **コードのデザインパターン** にフォーカスされやすいです。また、"ドメイン層"という **レイヤーの話** で閉じてしまうことも多いのです。

逆に、戦略的設計から"ドメイン"を見た場合、ビジネスとの調和やドメインの精錬を強く押し出すので **全てがドメインを中心** となりやすく、こちらではこちらでドメインロジックへの言及が減ってしまいます。

結果として、「 **ドメインを中心** に考えることで、**ドメインロジックに規律** を定める」という両者に重なる要素が、非常にうまくすり抜けてしまうなと感じます。

### 軽量DDDでも"ドメイン"

軽量DDDだからと、DTOやEnumという言葉、〇〇エンティティを永続化するとか、コメントがドメイン層のコードに入っていませんか。〇〇サービスと言ってただの処理ロジックをまとめていませんか。それは本当にドメインでしょうか。

このぐらいの意識でDDDをはじめてしまうと、薄めのデザパタのために大量のオーバーヘッドを払うことになります。さらに、あいまいさはドメインロジックの規律を徐々に奪っていきます。結果としてつらみが勝るDDDになってしまうかと思います。

ビジネス分析するだけがドメインではありません。アプリケーションのドメインが何かと考えることも重要です。それがドメインロジックの規律になり、アプリケーションの実装においても保守性の観点で、大きな効果があるからです。

# まとめ

"ドメイン"は、戦略に強く結合することが多い。けど、戦略だと重すぎて離れがち。
"ドメイン"は、ビジネスとのためだけのモノでは無い、**アプリケーションの実装** にも重要な考え。
"ドメイン"は、 **ドメインロジックの規律** を定めるので、アプリケーションの保守性に大きく貢献する。

逆に、雑に言うと、ドメインとビジネスと戦略が結合しすぎてる。ビジネスがいないとドメインの価値が無いように捉えやすくなってしまう。

ドメインロジックの規律を作り、アプリケーションの実装/保守性に大きく貢献する。
このうまみを最初からあきらめてしまって、もったいないなと感じる今日この頃です。まあ言うても、軽量でデザパタオンリーだ！というDDDしてる人は、そこまでいないと思いますが。。

# ポエム「なんで、ドメインで、ドメインロジックの規律が定まるの？」

以下ポエムです。

なぜ、ドメインで、ドメインロジックに規律が定(まる|められる)のか、グダグダ書いていきます。

1. アプリケーションは規律が無いとすぐにカオスになる。
2. アーキテクチャ的方法論では、規律を作るのが限界だと、歴史が言っている。
3. オブジェクト指向プログラミングの練度で、乗り切れると思うのも間違い。
4. 関心毎を分離する前に、そもそも関心毎が統一されてない。
5. そんな長ったらしい前提の上にあるのが「ドメインを中心」としたDDD

伝わる人には、目次だけで伝わる可能性もある気もしますが、順に追っていきたいと思います。

## 1. アプリケーションは規律が無いとすぐにカオスになる。

これは、言わずもがな。な気がします。

アプリケーションを構築する際に、難しいのは方針の存在です。「どこに何を置いて、どこに何を書くか。」です。

この方針が無いと、ベタっと巨大なコードがそのまま記述されます。こうなると、アプリケーションはすぐに混迷し、読むことさえ困難で、修正することはばかれる、複雑で保守性の低いものに突き進んでいきます。このような方針があることを、規律があると呼びたいと思います。

### 長い余談

これはあるあるですよね。プログラマの練度だと思われがちですが、規律が不足して起きています。方針を定義するフェーズが無かったり、全体から見ると重要度が低い。というのがだいたいの原因です。糞コードなのは、書いた人のせいではなく、なるべくしてなったのですが、技術や設計から逃げたプロジェクトのせいです。とも言い切れないのが、次の話。

## 2. アーキテクチャ的方法論では、規律を作るのが限界だと、歴史が。

~~あなたのプロジェクトがそうかは知りませんが~~ ソフトウェア開発全体では「規律」から逃げ出したことはありません。

規律に立ち向かい続けて来ました。アプリケーションフレームワークのようなレイヤードから、DI/ORM/...言い出したら切りがありません。大量の成果物があり、私達の開発でも様々な恩恵を受けています。(というか規律=フレームワーク=アーキテクチャですね)

ですが、限界がありました。それは、ドメインロジックです。ドメインロジックは、アーキテクチャ的方法論では、規律が作れなかったのです。

もちろんチャレンジはありました。時代的にはJavaがイケイケな時代だったので、Javaにはドメインロジックの規律を試みた無残な残骸が非常にたくさん転がっています。JavaBeansとかSOAPとかEJBとか、EEのあれとかそれとか。

ほぼすべてが、
「主目的となるドメインに規律を定めるどころか、ただ無駄にめんどうになるだけ。で、使われなくなる」
となりました。

ドメインロジックとは、所謂ビジネスロジックなわけで、ビジネスの数だけケースバイケースになってしまうのです。規律を持たせるためには、抽象化が必須なので、それが無謀っちゃ無謀だっただけでもあります。~~おじさんだと、アナリシシスパターンとか思い出す話ですね。。難しいよあの本。。~~

## 3. オブジェクト指向プログラミングの練度で、乗り切れると思うのも間違い。

アーキテクチャ的方法論での規律が難しいとなると、個別のケースで方針を作り規律を定める必要があります。そこで期待(というか勘違い)されたのが、オブジェクト指向プログラミングです。ドメイン欠乏症とかファットモデルとか、言葉を出すとピンときますでしょうか。

OOPがすごく出来る人なら、アプリケーションに規律をもたらすことが出来る。と思ったことありませんか？私は思い続けてました。OODとか、いろいろいろいろ学習し、俺も規律を作るぜ～と頑張りました。が、そうそううまくはいきません。

そして気づきます。
「うまくクラスが作れないのは、技術というより、少し異なるところにある。気がする」

## 4. 関心毎を分離する前に、そもそも関心毎が統一されない。

たとえ話をしたいと思います。「新幹線に乗る」とは、どういうことかについて、考えてみてください。

* レールの上に、車輪の付いた鉄の塊に人をのせる。
* 電車の中でも、速度に特化した特殊な車両に乗る。
* 子供に大人気な乗り物に乗る。

と、色々解釈することが出来るかと思います。

この解釈を実装時のクラス定義として考えてみましょう、同じことに対し上記の3つのクラスがありえることになります。クラスの役割は、解釈によって様々に変わってしまう。これこそが、ドメインロジックに規律を作る際に、最も難しい部分になります。

次に、新幹線にのる目的に、"子供のおでかけのため"と、付け加えるとどうでしょうか。ふさわしいもの。ふさわしくないもの。が、明確になりやすいかと思います。

この付け加えたものこそ、**関心毎** です。

* 非常に大きなロジックなので、分割したい。
* 順序や手順が大事なロジックなので、分割したい。
* 永続化のデータ構造をうまく表現したい。
* 複雑なクラス構造なので、分割したい。
* うまく分割すると、変更に強いので、分けておきたい。
* 業務で、複雑なルールなので、明示的にしたい。
* 業務で、重要な処理なので、分けておきたい。
* よくある処理なので、分けておきたい。

関心毎は、レイヤーの文脈で良く使われます。レイヤーは、はっきりと明暗を分離します。ですが、ビジネスロジックという、おなじレイヤーの中でも、関心毎は、さまざまにあります。関心毎を統一せずにクラスを作ってしまうと、アプリケーションの規律は次第に失われて行きます。

### 長い余談2

単一責任の原則として、責任が大事だー大事だーとうるさく言われます。そもそも"関心毎"の時点で、認識が異なっていたら、責任が単一でも、全体としての規律は、簡単に崩れてしまうのです。関心の分離という概念は、SOLID原則等のオブジェクト指向設計論では、根底になるお話だったりします。


## 5. 長ったらしい前提の上にあるのが「ドメインを中心」としたDDD

ここまでお付き合いありがとうございました。
こんな長ったらしい歴史的な前提があり、ドメイン駆動設計が生まれました。

「じゃあ、ドメインロジックの関心毎は、ドメインだけにしよう」
そう言い出したのがDDDです。アプリケーションアーキテクチャに対しての解法でもあるのです。(その補足が秀逸すぎてデザパタになっていったわけですが。。)

色々ある関心毎のうち、なぜドメインだったのかは、それぞれの書籍をご覧いただければと思います。

## まとめ

最後に、振り返りさせてください。

ドメインはビジネスだけのモノではありません。 **アプリケーションの実装のため** にもあります。コードのパターンだけ真似ても、関心毎が統一されてなければ、規律は失われて行きます。歴史的な学習の結果、関心毎をドメインで統一することで、**ドメインロジックに規律** を定めたのもDDDの利点です。

せっかくのうまみを捨ててしまうのはもったいないですよ～という話でした。規律が失われるってどういうことなの。とか具体的なコードも無く、ちょっと直感的ではないのですが、だるいので、ここらで終わりにしたいと思います。

おわり