本記事は
【Advent Calendar 2025】
16日目①の記事です。
🌟🎄
15日目
▶▶ 本記事 ▶▶
16日目②
🎅🎁
- はじめに
- ドメイン駆動設計(DDD: Domain-Driven Design)とは
- ドメイン(Domain, 事業領域)とは
- サブドメイン(Subdomain, 業務領域)とは
- ユビキタス言語(Ubiquitous Language, 同じ言葉)とは
- 境界づけられたコンテキスト(Bounded Context, 区切られた文脈)とは
- まとめ
はじめに
こんにちは。入社3年目の山田駿斗です。
先日アーキテクチャカンファレンス 2025に参加してきました。
アーキテクチャと言ってもシステム構成のような技術的な話だけでなく、組織の設計やチーム間の連携といったテーマもあり、とても学びが多いイベントでした。
中でも印象に残っているのが、Vlad Khononovさんのキーノート『DDDが導く戦略的トレードオフのアート』です。
「DDDって聞いたことがあるけど、よく分からない」という状態でこのキーノートを聞いたため、一度では理解しきれませんでした。。。
そこで、会場で販売されていた著書『ドメイン駆動設計をはじめよう』を購入し、改めて学び直しました。
この記事ではキーノートや書籍を参考にしながら、ドメイン駆動設計の基本的な部分をスーパーマーケットを例として挙げながら整理したいと思います。
また、キーワードについて一般的に和訳で使用されているものをメインに記載しますが、()の中で英単語の記載と『ドメイン駆動設計をはじめよう』で使用されている単語を記載していますので、適宜読み替えていただければと思います。
ドメイン駆動設計(DDD: Domain-Driven Design)とは
ドメイン駆動設計とは、ソフトウェア開発において対象となる業務領域(ドメイン)を深く理解し、その知識を反映したドメインモデルを中心にシステムを設計する考え方です。
ソフトウェア開発の目的は事業課題の解決であるため、事業内容を理解せずに開発すると価値の低いシステムになる恐れがあります。
意味のあるシステムを作るために、対象の事業内容について理解した上でシステムを作っていくことが重要です。
ドメイン駆動設計は2つの側面があります。
- 戦略的設計:ビジネス価値に基づいてシステムを分割する
- 戦術的設計:コードレベルの設計(例:エンティティ、値オブジェクト、集約など)
今回は戦略的設計に焦点を当てます。
ドメイン(Domain, 事業領域)とは
ドメインとは、企業が事業活動を行う範囲のことです。
スーパーマーケットの場合、食品販売や鮮度管理、物流、接客などが該当します。
サブドメイン(Subdomain, 業務領域)とは
サブドメインとは、ドメインの領域全体を細分化した一つ一つの要素です。
スーパーマーケットの場合、在庫管理や発注管理、販売管理、決済処理などがサブドメインになります。
サブドメインは以下の3つに分けられます。
- コアサブドメイン
- 汎用サブドメイン
- 支援サブドメイン
コアサブドメイン(Core Subdomain, 中核の業務領域)とは
コアサブドメインとは、競合他社との差別化を図る領域で、競争優位性の源泉となる最も重要なサブドメインのことです。ここに最もリソースを集中させます。
スーパーマーケットの場合、在庫管理や発注管理、販売管理が該当します。
他社が簡単に真似できない独自の仕組みが必要になり、結果としてシステムが複雑になりやすく、優秀な技術者をアサインすることが重要になります。
また、コアサブドメインは事業方針と関連が強く、要件が頻繁に変更されるため、継続的なプロダクト開発体制が必須となります。
汎用サブドメイン(Generic Subdomain, 一般的な業務領域)とは
汎用サブドメインとは、多くの企業に共通しているサブドメインのことです。
スーパーマーケットの場合、会計や決済処理が該当します。
汎用サブドメインは自社で開発するのではなくSaaSで代替することが多く、これによってより多くのリソースをコアサブドメインに集中させることができます。
支援サブドメイン(Supporting Subdomain, 補完的な業務領域)とは
支援サブドメインとは、競争優位性には影響しないものの、業務遂行には不可欠であり、かつSaaSでは代替できないサブドメインのことです。
スーパーマーケットの場合、人事や顧客ロイヤリティ管理が該当します。
支援サブドメインは比較的シンプルなETL操作やCRUD機能で済むことが多く、若手育成のために用いられることがよくあります。
このようにドメインをサブドメインに分割することにより、ビジネス上の重要度や特徴を整理し、リソース配分を決めるのに役立てることができます。
ユビキタス言語(Ubiquitous Language, 同じ言葉)とは
ユビキタス言語とは、業務担当者が使用している言葉のことで、ソフトウェア開発時にも同じように使用します。
ユビキタス言語は会話やドキュメント、コードの中で一貫して使われ、関係者同士が認識齟齬なく意思疎通を図ることができます。
スーパーマーケットの場合、担当者が「商品」という言葉を使っていれば、開発者も同様に「商品」と言う言葉を使い、設計書やコード上でも「商品」と記載します。
つまり、「製品」など他の言葉を混同させないことが重要になります。
日本語環境におけるコードでの扱い
コードについて、ユビキタス言語が「アカウント」のようなカタカナ用語の場合は、対応する英単語(Account)をそのままコード上でも使います。
一方で「商品」のように漢字の言葉である場合、そのままローマ字にするか英単語にするか悩みどころです。
一般的には、事前に「商品 = Product」とチーム内で対訳の定義(辞書)を決めておき、クラス名には英単語(Product)を採用します。
その上で、ドキュメンテーションコメント(Javadocなど)で日本語名(商品)を併記して対応づける、といった工夫を行うことで、コードとユビキタス言語の乖離を防ぎます。
境界づけられたコンテキスト(Bounded Context, 区切られた文脈)とは
では、次のようなケースを考えてみましょう。
スーパーマーケットの在庫管理部門の担当者が使用する「商品」という言葉と、販売管理部門の担当者が使用する「商品」という言葉はどちらも同じ意味でしょうか。
いいえ、違う意味になります。
在庫管理部門における「商品」は物理的な在庫単位を指し、この文脈における「商品」ではSKUやロット、数量、保管場所などの項目が重要になります。
販売管理部門における「商品」は販売可能なアイテムを指し、この文脈における「商品」では価格やプロモーション、カテゴリ、表示名などの項目が重要になります。
このようにユビキタス言語の意味は部門ごとに変わることがあります。
ユビキタス言語が異なる意味を持つ在庫管理部門と販売管理部門を同じシステムで扱うとコードが複雑になったり、予期せぬバグを引き起こす可能性があります。
そこで重要となる別の考え方として境界づけられたコンテキストがあります。
境界づけられたコンテキストとは、ユビキタス言語の意味が混同しないように、ユビキタス言語を使用する境界を適切に設定しようとする考え方です。
先ほどの在庫管理部門と販売管理部門のケースでは、それぞれの部門ごとにコンテキスト(システム)を分けるようにします。
こうすることで、それぞれの部門の中で同じ「商品」という言葉を用いながらも、部門をまたがないことによりコード設計をシンプルにすることができ、予期せぬバグを防ぐことができます。
ドメイン駆動設計における理想的な境界
境界づけられたコンテキストは、単にユビキタス言語の意味を統一するだけでなく、以下の3つの境界が一致している状態が最も理想的であり、開発効率を最大化します。
1. モデルの境界(Model Boundary)
ユビキタス言語の特定の言葉が特定の意味を持つ限界点のことです。
先ほどの例に挙げた、在庫管理部門と販売管理部門における「商品」は部門によって意味が異なるため、この意味の切れ目(=部門)がモデルの境界になります。
2. 所有権の境界(Ownership Boundary)
どのチームがそのコードベースと運用に責任を持つかという境界です。
一つのコンテキストの責任を複数チームで共有すると、コミュニケーションコストが跳ね上がるため、「複数のチームが1つのコンテキストを共有する」のは避けるべきとされます。
コンウェイの法則に基づき、組織の切れ目がソフトウェアの境界になることがよくあります。
- 所有権の例
- 在庫管理部門が使用するシステムをチームAが担当する・・・OK(責任が明確)
- 販売管理部門が使用するシステムをチームBとチームCが担当する・・・NG(チーム間でのコミュニケーションコストが上がる、認識齟齬が発生する可能性がある)
- 複数システムをチームDが担当する・・・OK(ユビキタス言語の意味が混在していない、もしくは異なるコンテキストを扱う場合は境界を明確にし、ユビキタス言語の混在を防ぐ)
3. ライフサイクルの境界(Lifecycle Boundary)
他のコンテキストに依存せずに、独立して開発、デプロイできるかどうかを示す境界です。
もし二つのコンテキストのライフサイクルが結合していると、片方を変更する際に、もう一方も同時に変更・デプロイしなければならず、開発スピードの低下を招きます。
この場合、コンテキストを分けることで、担当チームは他チームを待つことなく自律的に改善を行えます。
ただ現実的にはこの3つの境界を一致させることが難しい場合があります。
そのため、競争優位性やモジュール間の結合の強度、チーム間の距離のバランスを見極めてシステム設計を行うことが重要になります。
この部分が『DDDが導く戦略的トレードオフのアート』の核となる部分ですが、ブログが長くなってきたため(まだ私自身理解しきれていないため)また別の機会にまとめてみようと思います。
まとめ
ドメイン駆動設計の基本を整理しました。ポイントは以下の通りです。
- ドメイン駆動設計: 業務領域(ドメイン)を深く理解し、その知識を反映したドメインモデルを中心にシステムを設計する考え方
- ドメイン: 企業が事業活動を行う範囲
- サブドメイン: ドメインを細分化した要素で、事業方針に応じて「コア」「汎用」「支援」に分類される
- ユビキタス言語: 業務担当者が使う言葉を会話やドキュメント、コードで統一し、関係者同士の認識齟齬を防ぐ
- 境界づけられたコンテキスト: ユビキタス言語の意味が混同しないよう、開発者がコンテキストを適切に設計する
システム設計では多くの要素を考慮する必要がありますが、ドメイン駆動設計の考え方も取り入れることでより価値のあるシステムを作れると思いました。
特に「認識齟齬を防ぐ」という視点は、どんなシステム開発でも重要だと感じています。どのようにコンテキストを分けるのか――これがエンジニアの腕の見せ所ですね。
今後もこうした知識を深めるために、様々なカンファレンスに参加して学び続けたいと思います。