「ドメイン駆動設計をはじめよう」を読んだので紹介します
はじめに
#7月にオライリー・ジャパンから「ドメイン駆動設計をはじめよう」が出版されました。
ドメイン駆動設計をはじめよう ―ソフトウェアの実装と事業戦略を結びつける実践技法 Vlad Khononov 著、増田 亨、綿引 琢磨 訳 : オライリー・ジャパン
2021年出版の Learning Domain-Driven Design の邦訳です。
翻訳者の一人である綿引琢磨さん[1]から送って頂いたので拝読させていただきました。本書の構成と概要を紹介したいと思います。
本書の印象
#エヴァンス本の邦訳[2]が出てから13年。「ドメイン駆動設計をはじめよう」はエヴァンス本で提示されたドメイン駆動設計を咀嚼して分かりやすく解説しており、アプリケーションアーキテクチャやマイクロサービスなどのテクノロジーとの関係についても整理されています。各章は簡潔にまとまっていてサクッと読めます。章末の演習問題で自分の理解度を確認することができます。翻訳もこなれており、ドメイン駆動設計を包括的に理解するのにおすすめの書籍に仕上がっています。
第Ⅰ部: 設計の基本方針
#ドメイン駆動設計の基本概念が解説されます。
1章 事業活動を分析する
#事業(ドメインは)、業務領域(サブドメイン)に分解され、業務領域は、「中核」[3]、「一般」、「補完」に分類されます。業務領域は関連するユースケースの集まりで、ソフトウェアの設計ではなく事業の方針によって決まるものと位置付けられます。業務領域の活動に精通した「業務エキスパート」も紹介されます。
2章 業務知識を発見する
#ドメイン駆動設計の土台となる「同じ言葉」[4]が説明されます。事業活動のモデルは「同じ言葉」を育てることで成長するとされます。
3章 事業活動の複雑さに立ち向かう
#業務エキスパートによって業務の捉え方が異なる場合があり、「同じ言葉」が違う意味を持つことがあります。このような不整合を排除し「同じ言葉」の一貫性を保つために「区切られた文脈」[5]が導入されます。これは、ソフトウェア設計の観点で、ソフトウェア技術者が決定します。「区切られた文脈」同士は異なるライフサイクルを持ち、サブシステムやマイクロサービスなど物理的な分割の境界となります。
4章 区切られた文脈同士の連係
#「区切られた文脈」同士の関係が整理されます。
「区切られた文脈」同士の関係を可視化するための「文脈の地図」(コンテキストマップ)が紹介されます。
本書では、エヴァンス本の翻訳とは異なる訳語をあてている箇所がいくつかありました。「ユビキタス言語」ではなく「同じ言葉」としたことで平易さが増した印象は確かにあります。しかし「偏在」というニュアンスが薄れているのと、「同じ」「言葉」というあまりに普通な単語の組み合わせのため字の文に埋もれてしまい、繰り返し出てくるだけに気になりました。
第Ⅱ部: 実装方法の選択
#ドメイン駆動設計に基づく実装方法が解説されます。サンプルコードは C# で書かれているため、少しだけ C# の知識が必要となります。
5章 単純な業務ロジックを実装する
#単純な業務ロジックは、「一般」や「補完」の業務領域の実装で登場し、これらはトランザクションスクリプトやアクティブレコードで実装します。アクティブレコードはデータ構造が複雑である場合採用します。トランザクションスクリプトも、分散システムを考えるとそれほど単純ではなく冪等性を考慮する必要があります。
6章 複雑な業務ロジックに立ち向かう
#中核の業務領域を実装するための「ドメインモデル」が説明されます。ドメインモデルは「値オブジェクト」、「集約」、「業務サービス」からなります[9]。集約はトランザクションの境界を構成し、データの一貫性を保証する責務を担います。集約ルートのエンティティが外部に公開するインターフェース役となります。集約のライフサイクルで発生した出来事は「業務イベント」として集約外部のコンポーネントにメッセージとして配信されます。値オブジェクトや集約に実装することが不自然なロジックはステートレスな「業務サービス」に実装します。
7章 時間軸でモデルを作る
#ドメインモデルにおける集約は最新の状態を表現し業務イベントを発信するものでした。この章で説明される「イベント履歴式ドメインモデル」は、イベントソーシングを実現し、より高度な業務要求(業務の分析と最適化、監査記録)に応えられる実装です。業務イベントを全て記録し、目的に応じたモデルを柔軟に投影可能です。
8章 技術方式
#アプリケーション全体をどのように構成するか(アプリケーションアーキテクチャ)について、「レイヤードアーキテクチャ」と「ポートとアダプター」、「CQRS」が紹介されます。
「レイヤードアーキテクチャ」はトランザクションスクリプトとアクティブレコードに適しているとされています。レイヤードアーキテクチャは業務ロジック層がデータアクセス層に依存しているため、意識して工夫しないと業務ロジックのインフラストラクチャーのから独立を実現できないということです。「ポートとアダプター」はいわゆるヘキサゴナルアーキテクチャやオニオンアーキテクチャと呼ばれるもので、依存関係逆転の原則により業務ロジック層がインフラストラクチャ層に依存しないため、ドメインモデルの実装に適しているとされています。
当サイトで先日まで開催されていた「夏のリレー連載2024」の第1回記事「DDDってなんでオニオンとかといっしょに出てくるの?を社内で聞いてみた」でも関連する議論が展開されています。筆者(私)は「KDさん」として登場し、今見ると見当違いなことを言っている気がします。
9章 通信
#「区切られた文脈」同士の通信方法として、4章で整理された連携方法に対応する通信方式が紹介されます。
「モデル変換装置」や「共用サービス」はプロキシ、API ゲートウェイ、データストリーム、BFFなどの方式にマッピングされます。集約同士の連携として「送信箱(Outbox)」、サーガ、プロセスマネージャーなどが説明されています。
これらはドメイン駆動設計を採用していない場合でも使用される通信方式であり、ドメイン駆動設計との対応を理解すると「区切られた文脈」の維持にも役立つことが分かります。
第Ⅲ部: ドメイン駆動設計の実践
#実際のソフトウェア開発でドメイン駆動設計を活かすための実践的な方法が解説されます。
10章 設計の経験則
#「区切られた文脈」は切り方を間違えると後が厄介になります。「最初は大きく切っておいて後から分けた方がよい」のような指針が示されます。
トランザクションスクリプトやアクティブレコード、ドメインモデルのいずれを採用すべきかを判定するためのフローチャートが提供されています。レイヤードアーキテクチャ、ポートとアダプター、CQRS のどれを選択すべきかを判定するフローチャートも提供されています。
テスト戦略(ピラミッド型、ダイアモンド型、逆ピラミッド型)を選択する指針も示されます。ドメインモデルは単体重視のピラミッド型が適しているそうです。インフラストラクチャーに依存しない業務ロジックだけのテストとして適しているのは確かに単体テストですね。
11章 設計を進化させる
#事業は目まぐるしく変化し、業務領域のカテゴリー(「中核」、「一般」、「補完」)すら変化します。システムの成長に伴い大きな泥団子化が進行します。この章では、実装方法の変更(トランザクションスクリプト → アクティブレコード → ドメインモデル → イベント履歴ドメインモデル)や移行方法が解説されます。開発組織の変更についても触れられています。
12章 イベントストーミング
#ドメイン駆動設計に関わる人が共同でモデリングを行うワークショップ「イベントストーミング」の進め方について解説されています。オフラインでの進め方が中心ですが、昨今の状況から Miro などを用いたリモートでの実施についても触れられています。
13章 現実世界のドメイン駆動設計
#理想的な新規開発ではなく、変更が厄介で危険な「大きな泥団子」のコードベースからなる既存システムに対してドメイン駆動設計を適用する方法が書かれています。事業活動の理解、既存システムの構造理解から始まり、「大きな絵」を描き「小さく始める」(ToBe に向かってスモールスタートを切る)やり方です。方法としては、ストラングラー方式(システム更新時の Blue/Green デプロイに似た方式)、リファクタリングが挙げられています。
この章に書かれていた以下の一文はよく覚えておきたいものです。
集約や値オブジェクトの実装がドメイン駆動設計ではありません。ソフトウェアの「設計」判断を「事業活動(ドメイン)」で駆動するのがドメイン駆動設計です。
第Ⅳ部: 他の方法論や設計技法との関係
#マイクロサービス、イベント駆動、データ分析などの他の方法論との関係について記述されています。
14章 マイクロサービス
#マイクロサービスの適切な粒度が全体最適の観点から説明されています。ドメイン駆動設計とマイクロサービスの境界については、「区切られた文脈」や「集約」 よりも「業務領域」で切るのが適切であるとされています。公開インターフェースが小さく複雑な業務ロジックを隠蔽した「深いサービス」がよいということも言われています。「共用サービス」や「モデル変換装置」も独立したサービスとして実装するとされており、これは API ゲートウェイや BFF などを見るとよく理解できます。
15章 イベント駆動型アーキテクチャ
#イベント駆動型アーキテクチャは、業務領域で発生した変化をイベントとして publish し、他のコンポーネントがそのイベントを subscribe してイベントに応じた動作をするアーキテクチャです。ここでは業務イベントも含めたイベントの種類、一貫性のレベル、それを保証するための設計について説明されています。
16章 データメッシュ
#スタースキーマなどの分析系データモデル、データウェアハウスやデータレイクなどの分析系データの基盤を解説します。これら基盤の課題として ETL スクリプトの乱立、業務データとの密都合によるドメイン駆動設計(データモデルを常に更新し続ける)との相性の悪さが挙げられます。これらの課題を解決するためデータメッシュが紹介されます。データメッシュを分析系データのドメイン駆動設計であると位置付け、モノリシックで巨大なデータモデルではなく、「区切られた文脈」でデータを整合させるアプローチを解説しています。「データをプロダクトとして捉え」、「区切られた文脈」に分析系モデルを提供します。
データメッシュについて筆者は全然知らなかったので、関連知識を得るいいきっかけになりました。ただ、これを実現するのは開発組織として高いリテラシーが要求される、ステージの高い内容だと感じました。
さいごに
#2004年にエヴァンス本の原著が出て、翻訳本が2011年に出るまで DDD 難民という言葉もありました。エヴァンス本は読書苦手な筆者としては珍しく2回くらい読みました[10]し、当時参画していたプロジェクトでもかなり意識して設計・実装をしていた記憶があります[11]。
本書はドメイン駆動設計を見直すよい機会を与えてくれています。特に第Ⅳ部は、現在主流の技術やアーキテクチャとの関係が俯瞰的に書かれており非常に参考になりました。付録に著者のスタートアップでの実践経験が失敗も含めリアルに書かれているのも理解の助けになると思います。
このような書籍が日本語で読めるようになったのは喜ばしいことだと思います。
長年、お仕事でお世話になっております。 ↩︎
エリック・エヴァンスのドメイン駆動設計: ソフトウェアの核心にある複雑さに立ち向かう : エリック エヴァンス, 和智 右桂, 牧野 祐子 ↩︎
エヴァンス本では「コアドメイン」と呼ばれていたもの。他社との差別化、競争優位を生み出す業務領域 ↩︎
エヴァンス本における「ユビキタス言語」 ↩︎
エヴァンス本における「境界づけられたコンテキスト」 ↩︎
エヴァンス本における「共有カーネル」 ↩︎
エヴァンス本における「腐敗防止層」 ↩︎
エヴァンス本における「公開ホストサービス」 ↩︎
エンティティは集約の一部と位置付けられています。 ↩︎
エヴァンス本は本書と比べ「蒸留」という言葉で表現されるコアドメインの実装の洗練化など、もう少しコード中心に説明されていた印象です。 ↩︎
その後は DDD が実装パターンみたいに扱われ、残念なコードのプロジェクトを多く見たのもあり、無邪気に DDD やります的なプロジェクトは敬遠してしまいます。本書にもドメインモデルは他社との差別化のための中核の業務領域に採用すべきであるとありますし、エヴァンス本でもコアドメインに注力し最も才能ある開発者をアサインすべきであると書いてありました。 ↩︎