読書メモ：実践ドメイン駆動設計（IDDD）2章

# はじめに

- 実践ドメイン駆動の読書メモです。簡単なまとめと、自身のコメントをまとめています。//から始まる行が私のコメントや考察。
- https://www.amazon.co.jp/dp/479813161X
- 狙い：読んだものの、頭に入ったようでまったく記憶に残らなかったため、あとで自分の記憶を掘り起こすツールとして。

# 第2章 ドメイン、サブドメイン、境界付けられたコンテキスト

## 2.1 全体像

- ドメインとは、組織が行う事業やそれを取り巻く世界のこと
- ドメインモデルとはその事業のドメイン全体をカバーするモデル（＝エンタープライズモデル）ではない
    - DDDが目指すのは複数のサブドメインを組み合わせて、組織のすべてのドメインを作り上げること
- ドメインモデルの開発は、事業のドメイン全体の特定の部分に注目する一つの方法

- サブドメインと境界付けられたコンテキストのはたらき

    - 技術的な複雑さと、業務的な複雑さを持つシステムの例
        - 商品カタログ、注文、請求、発送の４つの主要サブドメインで構成されるECシステムの
        - これとは別に在庫を取り扱う在庫システム
        - サブシステムの数が本来あるべき姿より少なすぎて、ひとつのサブシステムが多くの業務機能を持ちすぎている可能性が示唆

        - 技術的な複雑さ
            - 商品カタログ、注文、請求、発送の４つのモデルが１つの「Eコマースモデル」にまとまっている
            - 多くの開発者は、１つのシステムにあらゆるものをまとめてしまうのが良いと考えている
            - しかし、あらゆる利用者のあらゆるニーズを満たすことはできない
            - まとまってしまっていることで、結合・依存が強いシステムになってしまう

            - DDDの戦略的ツールを使って、実際の機能に基づいたサブドメインに切り分ける

        - 業務的な複雑さ
            - 限られた広さの倉庫の中で調整が頻繁に発生している
            - 売れ筋商品の在庫をあまり確保できない
            - 売れ筋以外の商品の予想外の売れ行きに対しても在庫を確保できない

        - 既存の統合状況に注目して、現状を大まかにつかむことで、見えてくるものがある
            - 外部の需要予測機能を導入することが、新たなコアドメインとなりうる

        - // 現状のサービスを、ドメインやコンテキストの観点で分析することで、技術的な課題や業務的な課題に気づくことができるうえ、その分析結果から、新しいビジネスチャンス（コアドメイン）を見つけることができる、ということだと理解しました。
    
    - DDDを実践する際は、個々の境界づけられたコンテキスト内のドメインモデルで使われるすべての用語の意味の確実な理解と、言葉の境界を気にする。

        - 例えば、「顧客」という用語は、カタログを見ているときの顧客と、注文をするときの顧客は違った意味を持っている。
            - 商品カタログドメインにおける顧客：固定客集め、取扱商品数、割引、発送方法などの概念が関わっている
            - 注文ドメインにおける顧客：名前、発送先、請求書、注文額、支払い方法などの概念が関わっている

            - // 上記が一つのモノリシックなサービスで実現されているとしたら、ありとあらゆるシーンでCustomerというクラスと、関連する膨大な属性、無秩序に書かれたビジネスロジックなどが容易に想像できます。

        - DDDを用いることで、ドメインエキスパートとのコミュニケーションの中で曖昧さをなくしてコンテキストの境界を明確にすることができる

- コアドメインに注目する

    - ドメインの分類
        - コアドメイン：組織を成功に導くために最も重要なもの。最優先で取り組むべきもの。
        - 支援サブドメイン：業務上は不可欠だが、コアドメインとはいえないもの。
        - 汎用サブドメイン：業務上は特別なことをしていないが、ソリューション全体として必要なもの。
        - 支援サブドメインと汎用サブドメインの切り分けは重要ではない。重要なのは、何がコアドメインで、何に注力すべきであるかということ。

    - // ありとあらゆるものにDDDを全力で適用するのではなく、力のかけ具合についてのアドバイスだと理解しました。1章でも述べられているとおり、DDDはコストがかかる一方、もたらす利益も大きい。したがって、コアドメインは全力でやって、その他のドメインはバランスを取りながらやりましょう、ということだと理解しました。


## 2.2 なぜそれほどまでに戦略的設計を重視するのか

- SaaSOvationの失敗例
    - （補足）SaaSOvationという架空のチームは、グループウェアの開発を行っており、DDDの戦術的な部分だけをつまみぐいした実践（軽量DDD）を行っている、という前提。
    - 戦術的な方法にだけ注目して、ユビキタス言語の構築やコンテキストの境界に頓着しなかった
    - 結果的に、「コラボレーション」というコンテキストの中に、パーミッションという無関係な概念が混ざってしまった
        - 本来、コラボレーションコンテキストの中で登場するのはフォーラムや投稿者だけであり、誰が、どんなことができるのかは関心事の範囲外である。
        - SaaSOvationは、それまでのパーミッションベースの管理から、ロールベースへの管理へと変更を行い、ロールとパーミッションの管理は別で行うことになった

- // 架空のチームの失敗例を出して戦略的設計の重要を主張するVernonさんはどうなんだと思うが、例が「ありそう」な失敗だったのでとりあえず飲み込むことにしました（笑

## 2.3 実世界におけるドメインとサブドメイン

- ドメインは問題空間と解決空間を持っている
    - 問題空間：解決すべきビジネス戦略上の課題を浮き彫りにするもの
    - 解決空間：ソフトウェアをどのように実装してその課題を解決するかに注目するもの
        - 境界づけられたコンテキストのことで、特定のソフトウェアモデルの集合

    - // なんだか複雑な説明をしていますが、問題空間とは、ビジネス全体をドメインで切り分け、何がコアドメインで何がサブドメインであるかを認識すること、解決空間とは、それらをどのようにドメインモデルとして表現し、ソフトウェアに実装するか、ということだと理解しました。

- レガシーシステムにおける問題空間の理解
    - アセスメントビューを使う
    - // アセスメントビューについての説明がないのでよくわからなかったのですが、ググっても出てこないし、他にも「なんのこっちゃ」となっている人が多い様子。どうやら、この記述の後に出てくる、問題空間の分析に関する質問集と、解決空間に関する質問集のことらしいです。おそらく、原著から翻訳された段階で、この単語だけ置き去りになってしまったっぽい。

- 問題空間と解決空間の違い：ERPシステムの例
    - 既存の業務サービスを別のサブドメインと考え、在庫サブドメインと購買サブドメインに分割する。
    - ここで、組織が購買の意思決定を自動化する「最適取得」事業（ドメイン）を検討し始めたとする。
    - コンテキストの境界を明確にしておくことで、これらのドメイン同士が密結合にならないように開発ができる。
    - さらに、購買サブドメインは汎用サブドメイン、つまり別のもので代替可能であるので、別の購買システムに置き換えることができる。
  
- // このERPシステムの例は、問題空間と解決空間、いうなれば、目的と手段、ビジネス的な価値の優先順位を意識することの重要性を述べているのだと思います。この組織が扱うドメインには、在庫・購買・最適取得の３つのドメインがありますが、この３つの問題空間を区別せず、一つのドメインとして扱ってしまうと、良くないのだということです。問題空間を３つのドメインに分け、それぞれに最適な解決空間を考えましょう、ということだと思います。
- // すなわち、この組織がビジネス的な強みを発揮できる「最適取得」事業に注目をしやすい環境を作りましょう、ということだと理解しました。もし、このERPシステムが、モノリシックなシステムであった場合、この最適取得モジュールを組み込もうとしても、複雑に絡み合ったシステムの中に手を入れるのは難しいでしょうし、また、仮に一旦開発できたとしても、今後の機能開発で、他のドメインが制約になって開発の足を引っ張るであろうことが予想されます。これは、マイクロサービスアーキテクチャ的な考えにもなるでしょうが、最適取得モジュールと、購買モジュールがAPI連携のような疎結合な状態であったとすると、購買モジュールを別のシステムに置き換え、開発リソースを最適取得事業だけに集中して投入できるというようなシナリオを描くことができます。


## 2.4 境界づけられたコンテキストの意味を知る

- 境界づけられたコンテキスト：ドメインモデルがどこに属するのかを表す明示的な境界
    - 異なる２つの概念が、同じ名前のオブジェクトを違う意味で使っていることが多い
        - 銀行取引における「口座」と文学における「報告書」は、同じ「アカウント」という言葉で表現される
     - 実際の業務でありがちなのは、似ているが微妙に意味が違うという状況
        - 当座預金コンテキスト、普通預金コンテキストにおけるそれぞれの「口座」
        - 「書籍」は出版前の企画段階、執筆中、出荷後…それぞれで持つ意味合いと、関心事となる情報が異なる
            - ライフサイクルの各段階ごとに、境界づけられたコンテキストを定義すると良い

- 境界づけられたコンテキストは、モデルだけを扱うわけではない。システムやアプリケーション、業務サービスを区切るために使うこともある。

- 境界づけられたコンテキストの大きさ
    - ユビキタス言語の全貌を完全に表現できるだけの大きさ
    - 理想は、ひとつの境界づけられたコンテキストの中には、モデリングすべきドメインの概念が適切な数だけある
    - ドメインモデルを完璧にすることはできず、何度もイテレーションを繰り返しながら変更することになる
    - 境界づけられたコンテキストのサイズを適切に見極められなくなる要因
        - アーキテクチャの事情によって決めてしまう
        - 開発メンバーのタスク割当の事情によって決めてしまう
        - これらは無意識に行われてしまいがちである
        - モジュール(9章)を活用することでより（コンテキストのサイズを理想に近い形に保ちつつ）適切なタスク分散ができるようになる

    - // この辺はすごいあるあるだと思います。一方で、納期やリリース予定日などの兼ね合いや経営的な判断で、この前提を破らなければならないシーンもあるのではないかと思います。今後の章を読み進める中で考えが変わってくるかもしれませんが、現時点では、必ずしも原理原則にとらわれる必要はなく、ビジネスサイドとのバランスを取りながらすすめる必要があるのかなと思いました。例えば、コアドメインに関してはビジネス戦略上重要なので原理原則に従うが、それ以外のサブドメインについては、原理原則を破って帳尻を合わせる、などでしょうか。

- 技術的なコンポーネントとの強調

    - 技術コンポーネントの単位が境界づけられたコンテキストを決めるのはNGだが、境界づけられたコンテキストがコンポーネントを決めるのはOK
        - コンテキスト単位のプロジェクト、コンテキストを構成する複数のJAR,DLLなど
    - 単一の境界づけられたコンテキストは単一のチームが受け持つべき
        - 複数のチームが受け持つと、ユビキタス言語の解釈がチーム間で分かれてしまったり、モデルの変更が必要になったときに競技が必要になってしまう
        - // ここでいう「チーム」とは一体どういうものなのでしょうか。個人の解釈のずれを補正するために小さいまとまりでユビキタス言語を定義すべし、という観点には納得できるのですが、人数が増えれば1つのチームだってまとまりはなくなってしまうのではないでしょうか？DDDにおける適切なチーム人数などがあるのでしょうか…？今後の学習の中で何か答えが見つかれば良いと思います。
        - // 【追記】某所でアドバイス頂いたのですが、これは私の理解が間違っていて、ユビキタス言語が指すのは、個人の解釈で分かれるというレベルのものではなく、ビジネス的に異なる概念の言葉をコンテキストの境界で分けてしまおう、というものです。ですから、チームのサイズを規定するのは、そのコンテキストを対象にした開発にどれだけリソースを投入するのか、ということだと思います（とはいってもチーム運用という意味で、1チームの人数に限界はあるでしょうけれど）。
    
## 2.5 サンプルのコンテキスト

- コラボレーションコンテキスト
    - このコンテキストに関係のないセキュリティ・権限に関する概念が混ざってしまっている
    - Evans本に書かれているDDDの戦術的なテクニックである、集約やリポジトリ、ドメインサービスなどを活用していたにもかかわらず、理想的なコンテキスト・ドメインの設計になっていなかった
    - 第3部の「より深い洞察へ向かうリファクタリング」や第4部の「戦略的設計」をヒントに次のような改良案を考えた。
        - 責務のレイヤにまとめる
            - 権限制御に関する処理を既存のドメインモデルより下の論理的レイヤに分割する
            - ただし、これはコアドメインと無関係の概念が混ざることなので最適な手段ではない
        - 隔離されたコアをめざす
            - コラボレーションコンテキストから、権限に関する概念を切り離す。
            - これは、境界づけられたコンテキストを作るという結果に近づく
    - コラボレーションコンテキストから、認証・アクセスコンテキストを切り出す選択をとった
        - 組織的にもこのコンテキストが新しいSaaSプロダクトになる可能性を認めた
        - 汎用的なモデルとすることで、他のアプリケーションからの利用や、サードパーティのプロダクトを導入して顧客専用の統合をすることもできる
    - // ここで重要なのは、認証・アクセスコンテキストを切り出すという判断に、ビジネス的なチャンスの見込みがあったことだと思います。アーキテクチャ的にこうした方が美しいから、ということではなく、ビジネス的に価値の育てることができるから、別の境界づけられたコンテキストとして成立するということですね。

- 認証・アクセスコンテキスト

    - 深く考えずにセキュリティ機能を組み込むと、個々のシステムの中で個別に実装することになり、連携のないシステムとなる
    - このような場合、システム間のユーザーの関連付けができない

- アジャイルプロジェクト管理コンテキスト

    - 当初、このコンテキストはコラボレーションコンテキストの開発リポジトリ内にブランチを作って開発しようとしていたが、ここまでの失敗から、別のコンテキストに分けるべきであると判断した
    - このコンテキストにおける利用者は、「ユーザー」というようなものではなく、「プロダクトオーナー」と「チームメンバー」であると判断できた
    - スクラムを実践する際の、ユーザー・ロールの管理は認証・アクセスコンテキストに任せる

- // はっきり明言されていないのですが、このサンプルとなったSaaSOvationは、DDDを導入して適切にコンテキストの境界を見つけることで、そうでなかった場合には１つの巨大で複雑な製品が生まれていたのに対して、コラボレーションコンテキストから成るCollabOvation、認証・アクセスコンテキストから成るIdOvation、アジャイルプロジェクト管理コンテキストから成るProjectOvationという３つの製品を手に入れることができた、ということだと理解しました。AWSやGCPなんかもそうですが、全部入りの巨大なサービスというより、個々の要件に特化した小さなサービスが連携する形が多いですね。

## 2.6 まとめ

- 以下、本章を読んだ個人的見解のまとめです。
    - // アーキテクチャ的な観点や、タスク分割の観点でコンテキストの境界を決めてはいけない。あくまで対象としているシステムがビジネス的な視点で、どこに重要な価値を持っているのかがコンテキストの境界を決めるという点がとてもしっくりきました。
    - // 美しいアーキテクチャ、美しい設計、美しいコードに関するテクニックはたくさんありますが、戦術的な視点に目を奪われるあまり、ビジネス的に適切ではない判断をしてしまうケースも多いのではないでしょうか。また一つ、DDDの素晴らしさに気づくことができました。