「実践ドメイン駆動設計」社内読書会まとめ...
TRANSCRIPT
株式会社ネクストスケープ 御中
青木 淳夫 & 上坂 貴志
Sansan DDD 勉強会 #2http://connpass.com/event/23174/
2015.12.16
「実践ドメイン駆動設計」社内読書会まとめ~ IDDD 本難民に捧げる 1 章から 7 章~
2
本日は、翔泳社さんの書籍「実践ドメイン駆動設計(通称 IDDD 本)」の社内読書会の状況と、書籍のポイントを整理して紹介します。
IDDD 本は、 DDD を解説した書籍の中ではとても読みやすく、実際に活用してみようと思わせる内容となっています。とはいえ、 520 ページ(付録除く)もあるため、個人で読み進めることは容易ではありません。そこで、ネクストスケープ社では、週に一度、読書会を行っています。
今回は、この読書会の様子と、 IDDD 本の章別の要約とポイントをまとめて紹介します。 紹介する内容が、これから IDDD 本を読んでみようと思われる方の道標になれば幸いです。
※このスライドに書いている内容は、独自の理解・見解によるものです。DDD のとらえ方も人それぞれですし、何かありましたら、懇親会等で心優しくご指摘いただけると幸いです。
このセッションでお伝えしたいこと
3
大手 SIer 、テクニカルライター、福井の Web デザイン会社を経て、ネクストスケープ所属。
プログラマーとしてシステム開発の難しさを感じていた2000 年頃、 XP と vbUnit に出会い、アジャイルに傾倒。
その後、 Java での大規模ウォーターフォール案件でチームリーダーを経験したり、 Web 制作会社で PHP を書いてみたり。
最近はデジタルマーケティングやクラウドソリューションに携わったりすることが多い。
Microsoft MVP for Visual Studio(2006 ~ )Sitecore MVP(2012 ~ ) 、 Certified Scrum Master 。.NET 関連の著書 3 冊。
Microsoft 技術と OSS が好き。散歩とラーメンとお酒と甘いものも好き。
青木 淳夫 (@aoki1210)
自己紹介
上坂 貴志 (@takashiuesaka)
長年に渡ったフリーエンジニア稼業に終止符を打ち、ネクストスケープ所属。エバンジェリスト・アーキテクト。
若かりし保守・運用に苦しんでいた時期に XP ・ TDD と出会い、実プロジェクトで何度も実験。そして失敗。
同時期にソフトウェアアーキテクチャの重要性を痛感して修行を開始。様々なプロジェクトで Try & Error を繰り返してきた。
近年は Microsoft Azure との関わりが多く、エバンジェリストという仕事柄、登壇・執筆活動がメイン。
Microsoft MVP for Azure 、 Certified Scrum Master 。Azure Machine Learing の共著 1 冊。
Microsoft 技術とアーキテクチャ、 DDD 、 Scrum が好き。温泉とタイ料理が好き。甘いのも辛いのどっちも好き。
4
1週間で1回開催(ときおり非開催)
1 回で 0.5 章を目安
5月から実施
参加者は社員もパートナーさんも含め 3名から 10名くらい(若手多め)
固定メンバは 5名程度
現在 10 章まで完了
週に 1 回のランチ勉強会
読書会の様子
5
読書会を始めたきっかけは「 IDDD 本の中身を皆でディスカッションして、お互いの理解を深めたい」という意図でした。読書会という名目ですが、若いエンジニアが多いので、開発の課題やアーキテクチャそのものの基礎的な説明が多くなっているため、時間内訳の 95%ほど上坂さんが DDD の話を熱く語る時間になっています。現在の 1周目が終わったら、改めてワンランク上の2周目を行う予定です。
読書会の背景と現状
6
社内での DDD 実践例(勤怠管理アプリケーション)
ピットタッチで登録した勤務情報を編集したり登録管理するアプリケーションを DDD で構築しました。(使用技術→ CentOS / C#, ASP.NET MVC, Azure, SQL Database, Azure Table / Power BI 等)
上坂さん曰く、過去数回にわたって、 C# で DDD を行ったが簡単ではなかったとのこと。この例では DDD でそれなりに上手くいったそうです。
株式会社ネクストスケープ 御中
目次: IDDD 本の構成
8
目次の章で挫折して難民になりかねないので、興味ある章から読んでも良いかもしれません。
IDDD 本の目次
章 タイトル ページ コメント
目次 序文、賛辞、初めに、謝辞、著者、訳者、本書の読み方 24 各章の概要説明があります
1 章 DDDへの誘い 38 DDD を実践するメリットについて
2 章ドメイン、サブドメイン、境界づけられたコンテキスト 40 巨大な泥団子にならによう業務別に分けよう
3 章 コンテキストマップ 24 迷子にならないためのもの
4 章 アーキテクチャ 53 レイヤから、ヘキサゴナルアーキテクチャへ
5 章 エンティティ 45 値オブジェクトとの違いを意識
6 章 値オブジェクト 42 エンティティとの違いを意識
7 章 サービス 19 変換・算出はここで
8 章 ドメインイベント 45 分散&同期のテクニック
9 章 モジュール 11 「内部構成もユビキタス」で可読性アップ
10 章 集約 40 コンテキスト内の最小トランザクション単位
11 章 ファクトリ 11 ファクトリって、 Factory メソッドじゃないんだよ
12 章 リポジトリ 44 いわゆるリポジトリ
13 章 境界づけられたコンテキストの統合 5614 章 アプリケーション 28付録 A 集約とイベントソーシング: A+ES 41付録 B 参考文献 7
9
IDDD 本を読んでみよう
技術書は、最低 3 回読むと著者が伝えたいことを、よく理解できますよ
500 ページもある IDDD 本を 3 回も読むとか、そんなことできるんですか…?
IDDD 本の目的と構成を理解すれば、そんなに難しくないですよ!
10
IDDD 本の目的は「 DDD の理論を実際に適用する」ことで、それらを順序だてて説明しています。また、 SaasOvation(サーズオベイション ) という疑似プロジェクトを例としたサンプルコードも提供されています。
IDDD 本の構成
主題:実践ドメイン駆動設計
副題 (目的 ):エリック・エヴァンスが確立した理論を実際の設計に応用する
著者:ヴァーン・ヴァーノン / 訳者:高木正弘
実現したい未来
DDD を達成するための分類
1 章DDDへの誘い
2 章ドメイン
3 章コンテキスト
設計・モデリング・実装方法
4 章アーキテクチャ
5 章エンティティ
6 章値オブジェクト
7 章サービス
8 章ドメインイベント 9 章モジュール
10 章集約
11 章ファクトリ
12 章リポジトリ
13 章統合コンテキスト 14 章アプリケーション
11
DDD 実装サンプル
IDDD 本のソースコードサンプルの場所
IDDD 本 SaasOvation - Java のサンプル(ヴァーンさん)https://github.com/VaughnVernon/IDDD_Samples
IDDD 本 SaasOvation - C# のサンプル(ヴァーンさん)https://github.com/VaughnVernon/IDDD_Samples_NET
おまけ ASP.NET MVC + C# ミュージックストアの DDD版https://github.com/thiagolunardi/MvcMusicStoreDDD
さらにおまけ、 IDDD 本 C# のサンプルの日本語に適当にいじったものhttps://github.com/aoki1210/IDDD_Samples_NET
株式会社ネクストスケープ 御中
1章: DDDへの誘い
13
1 章の構成は
• 私にもできるの?• あなたが DDD をすべき理由• DDD を行う方法• DDD を採用する事業価値• DDD の導入にあたっての課題• 現実味のあるフィクション
となっています。
DDD (ドメイン駆動開発)を使うとどんなメリットがあるのか、なぜ DDD以外のやり方だと失敗するのか、そして、上司、ドメインエキスパート、技術者への DDDのすばらしさの売り込み方法を紹介しています。
「 1 章:DDDへの誘い」の構成
14
DDD に取り組める人は、若手の開発者、中堅レベルの開発者、ベテラン開発者、アーキテクト、ドメインエキスパート、マネージャ等。学ぶことができる人であれば、だれでもDDD を実践できる。
DDD のメリットは次の 3つ。
1. ドメインエキスパートと開発者は、共同で業務をモデリングし「ユビキタス言語」を確立し、「私たちとあの人たち」ではなく「私たち」のチームを作る。
2. 事業戦略構想に対応するため、サービス指向アーキテクチャやビジネス思考アーキテクチャを実現できる。
3. ソフトウェアの真の技術的要求を満たす。スケーラブルで、 SLA を満たし、アーキテクチャから詳細設計まで様々な問題に対応できる。
逆に複雑なシステムで DDD を使わないと、シンプルに作ることができず開発に失敗する可能性もあります。
「 1 章:DDDへの誘い」のポイント
15
DDD とユビキタス言語は実現できる
お客さんも、ドメインエキスパートも、開発者も、あらゆるところで同じ言葉「ユビキタス言語」で意思疎通できたら最高だと思いませんか?
理想はわかるんですが、昔から存在する UML (統一モデリング言語)ですら
エンジニア以外には普及していないのに、DDD の導入って難しいんじゃないですか ..
これまでは技術的なシステム都合(特に DB と永続化)に引きずられて、業務とシステムの間にギャップが生じていたんです。
これから、 DDD はもっと普及すると考えています。
株式会社ネクストスケープ 御中
2 章:ドメイン、サブドメイン、
境界づけられたコンテキスト
17
2 章の構成は
• 全体像• なぜそれほどまでに戦略的設計を重視する
のか• 実世界におけるドメインとサブドメイン• 境界づけられたコンテキストの意味を知る• サンプルのコンテキスト
となっています。
ここでは DDD固有の主要概念である「ドメイン」「コアドメイン」「サブドメイン」「境界づけられたコンテキスト」の説明が行われています。
「 2 章:ドメイン、サブドメイン、境界づけられたコンテキスト」の構成
※ ドメインの構成を示した図
コアドメイン支援サブドメイン汎用サブドメインコンテキスト
18
技術による戦術的パターンに走らずに、戦略的設計(ドメインとコンテクストに注目し、適切に分けよう)を実践しようという内容です。
ドメインとは、問題空間(問題領域)のこと。業務そのものでアクターのアクションなども含まれる。ビジネス上最も重要なもの、戦略的に不可欠なものをコアドメインと呼び、それらを補助する支援サブドメイン ( 業務的 ) と汎用サブドメイン(非業務的)が存在する。
例えば、「受注」「在庫」などは、同じ言葉で話していても、ドメイン毎に意味合いが違うことがあるので注意が必要。
境界づけられたコンテキストとは、解決空間(解決領域)のこと。言語的な境界を意識し、全部入りの巨大なモデルを作らないようにする。
ドメインエキスパートの声を聴いて、境界づけられたコンテキストを構築する。例えば、「認証アクセスコンテキスト」「在庫コンテキスト」など、大きすぎても小さすぎてもいけない。
「 2 章:ドメイン、サブドメイン、境界づけられたコンテキスト」のポイント
19
複雑なシステムを作らないために、ユビキタス言語の呼び方に敏感になろう
あたりまえですが、複雑でないシンプルなシステムを作りたいですね。
しかし、システムを分割しても、ひとつの DB でデータを管理してしまったことで
分割した意味が無くなってしまったことはありませんか?
それは、ありますね。システムや業務が違うのに、
DB変更時に調整が必要なケースですよね。
そうなんです。 DB をひとつだけで管理するとオブジェクトもひとつしか意味を持てず、巨大な泥団子になりかねません。
システムや業務が変わったら作業者も異なることが多いのでユビキタス言語の境界を意識して
正しいコンテキストで分割したいですね。
株式会社ネクストスケープ 御中
3 章:コンテキストマップ
21
3 章の構成は
• なぜそんなにもコンテキストマップは重要なのか
です。
2 章のドメイン、コンテキストの境界を理解することができ、モデルの統合に役立ちます。
「 3 章:コンテキストマップ」の構成
コンテキストマップ
22
コンテキストマップは、プロジェクトの現状を表す図(アーキテクチャドキュメント)のこと。目的は解決空間(解決領域)の現状を俯瞰できるようにすること。
DDD固有の図で、コンテキストを丸で囲む。コンテキスト間の関係を上流( Upstream )と下流 (Downstream) で示す。例えば基盤チームは上流。それを利用する業務チームは下流となる。
チームの力関係がアーキテクチャに影響を与えてしまうこともあるが、パートナーシップで協力的な関係(顧客/供給者の関係)を築くことが望ましい。残念ながら下流のチームが順応者の関係になってしまうことも多い。
コンテキスト間が蜜に依存しあわないように、上流と下流のコンテキストの間に腐敗防止層を作ることが多い。
なお、あらゆるコンテキストから依存されるような共有カーネルは各チームで相談しないといけないので、やめるべき。
「 3 章:コンテキストマップ」のポイント
23
ドメインとコンテキストの最新状況を「見える化」しよう
ドメインと境界づけられたコンテキストを設計したらコンテキストマップを作りましょう
プログラムの依存関係に似ているから納品時にツールで自動生成とかじゃダメですかね ..
開発の途中で、コンテキストの状態が分からなくなって混乱してしまうことがあるんです。
目立つところに書いておいて、共通認識と正しい理想を描けるようにしましょう。
株式会社ネクストスケープ 御中
4 章:アーキテクチャ
25
4 章の構成は• CIOへのインタビュー• レイヤ• ヘキサゴナル(ポートとアダプター)アーキテクチャ• サービス指向• Representational State Transfer ( REST )• コマンドクエリ責務分離( CQRS )• イベント駆動アーキテクチャ• データファブリック及びグリッドベース分散コンピューティングとなっています。
ここでは、さまざまなアーキテクチャで DDD を実現する方法を検討しています。
「 4 章:アーキテクチャ」の構成
①レイヤアーキテクチャ
③ヘキサゴナルアーキテクチャ( hexagonal は英語で 6角形の意味)
②レイヤアーキテクチャ (DI使用時 )
26
エバンズ本ではレイヤアーキテクチャを中心に説明されていますが、これに対して IDDD 本では、ドメインの独立性を保つものとして、ヘキサゴナルアーキテクチャ(ポート&アダプタ)を提唱しています。
レイヤアーキテクチャでは責務を「 UI層」「 アプリケーション層」「ドメイン層」「インフラストラクチャ層」の分類でしたが、ヘキサゴナルアーキテクチャは、入力元、出力先に依存しないインターフェイスで切り替えられるようになっています。
DDD のアーキテクチャでは、複数のドメインで連携する場合には分散システム的な挙動となるため、分散アーキテクチャが主流です。その例として以下のようなパターンが挙げられています。
・コマンドクエリ責務分離( CQRS )・イベント駆動アーキテクチャ・パイプ&フィルター・イベントソーシング
サービス指向技術( SOA/ マイクロサービス等)との関連性も高いので、クラウドデザインパターンを理解することもお勧めです。
「 4 章:アーキテクチャ」のポイント
27
ヘキサゴナルアーキテクチャのメリットって何
DDD では、ドメイン層が他のレイヤに依存したり汚染されたりしないようにします
なじみ深いレイヤーアーキテクチャとDI じゃ駄目なんですか?
DI を用いればレイヤ間の依存は分離できるんですが、アプリケーション層やインフラストラクチャ層が肥大化しやすいんです。
ヘキサゴナルアーキテクチャにすることでドメイン層以外が綺麗になるメリットがあります。
株式会社ネクストスケープ 御中
5 章:エンティティ
29
5 章の構成は
• なぜエンティティを使うのか• 一意な識別子• エンティティおよびその特性の発見
となっています。
右図の例では、 Person クラス・User クラスが「エンティティ」、TenantID クラスが「識別子」となっています。
「 5 章:エンティティ」の構成
※Entity の例(IDDD 本 C#サンプルソースより )
30
エンティティは、状態が変化していくオブジェクトです。
オブジェクトの「生成・変更・破棄」までを管理する必要があるため、一意性が必要になり、それぞれのオブジェクトが一意な識別子を持ちます。
RDB の識別子はオートナンバーやシーケンスといった DB問い合わせによる数値型の IDが主流ですが、 DDD ではインスタンス生成時にアプリケーション側で識別子を生成します。一意な値は、 128Bit から 32 バイトの文字列の型( UUID や GUID )を使用します。
エンティティのバリデーションを行う実装として、 Entity クラスの責務ではなく、 Validation クラスの責務になる例を紹介しています。(この章は、 OOP のプラクティス的な話が詰まった章です。)
「 5 章:エンティティ」のポイント
31
DDD が表すエンティティとは
あらためてですが、 DDD のエンティティってなんだと思います?
エンティティといえば ER図ですよね。だったら、テーブル構造とかレコードですかね ..?
RDB なら、それでも間違いではないんですが、DDD のエンティティは
「ライフサイクルを管理するオブジェクト」を表します。ライフサイクルを管理する必要があるため、
一意で不変の識別子を持ちます。
株式会社ネクストスケープ 御中
6 章:値オブジェクト
33
6 章の構成は• 値の特徴• ミニマリズムを考慮した結合• 標準型を値として表現する• 値オブジェクトのテスト• 実装• 値オブジェクトの永続化となっています。モデルから値オブジェクトの特性を見つけ出す方法について紹介されています。
「 6 章:値オブジェクト」の構成
※値オブジェクトの例(IDDD 本 C#サンプルソースよ
り )
この図では、前述の Person エンティティが、値オブジェクトである ContactInformationクラスをプロパティに持ちます。さらに、 ContactInformation クラスが値オブジェクトである EmailAddress クラス、Telephone クラス、 PostalAdress クラスをプロパティに持っています。
34
値オブジェクトは「ドメイン内の何かを計測したり、定量化したり、説明したり」するものです。
例)電話番号を数値型( Int型)ではなく Telephone型を使うことで、ドメインの業務を示すことができます。
値オブジェクトは「不変」が望ましいとされています。(エンティティは「状態が変化していくオブジェクト」のため逆ともいえます。)
不変ということは、コンストラクタ呼び出し時だけ値を設定可能です。 Getter はありますが Setter はありません。変更時にはオブジェクトそのものを差し替えます。不変であれば責務がシンプルになり、利用する側としても影響範囲が分かりやすく、バグが入りにくくなるメリットがあります。
永続化の実装方法としては、非正規化するか、もしくは正規化した専用テーブルを使う場合があります。最近の人気は NoSQL です。
「 6 章:値オブジェクト」のポイント
35
値オブジェクトこそ DDD
DDD で一番重要なのは「値オブジェクト」かもしれないですね。
え、そうなんですか?「値オブジェクト」って DTO(DataTransferObject) みたいな
シンプルなクラスっぽいので、簡単かと思っていました。
DDD では「電話番号」のようなユビキタス言語をプリミティブな数値型で済ませてしまうのではなく
「値オブジェクト」として表現します。
そのため業務を理解し、責務を検討し、「オブジェクトの振る舞い(プロパティとメソッド)」を設計する必要があります。
これはオブジェクト指向のモデリングスキルが必要ともいえます。
株式会社ネクストスケープ 御中
7 章:サービス
37
7 章の構成は• ドメインサービスとは何か(…の前にドメインサービスとは何でないのか)• 本当にサービスが必要なのかをたしかめる• ドメインにおけるサービスのモデリング• サービスのテストとなっています。
「 7 章:サービス」の構成
※ ドメインサービスの例(IDDD 本 C#サンプルソースよ
り )
※ アプリケーションサービスの例(IDDD 本 C#サンプルソースよ
り )
38
ドメインモデルの設計をしていると、エンティティや値オブジェクトといった「ドメインオブジェクト」だけではなく、外に出したほうが良いロジックも存在します。その際、ステートレスなクラス「サービス」を使用できます。大きく、サービスは次の2つが存在します。
・ドメインサービス エンティティや値オブジェクトの責務ではないドメインモデルのロジック (ドメインオブジェクトを使う処理やファサード)
・アプリケーションサービス(詳細は 14 章) 非常に薄く、ドメインモデル上のタスクの調整のために使うロジック (腐敗防止層の変換・アダプタ等)
サービスを作るときにミニレイヤのアンチパターンにならないよう注意する必要があります(エンティティや値オブジェクトがデータコンテナに成り下がらないように注意します)。
「 7 章:サービス」のポイント
39
サービスは注意しないと DDD が失敗する
エンティティと値オブジェクトに記述することが適切ではないビジネスロジックは
「サービス」に書いてもいいですよ
了解しました。では、ドメインモデルのロジックは
すべて「サービス」に実装しますね。
あなたのような人が「ドメインモデル貧血症」「トランザクションスクリプト」
だらけのメンテナンスしにくいコードを書くんですよ ..
適切なエンティティと値オブジェクトにロジックを書いて、「サービス」の利用は極力控えてくださいね。
40
■神原さんのスライド「 Implementing Domain-Driven Design: Part 1 」http://www.slideshare.net/atsushikambara/implementing-domaindriven-design-part-1
■DDD 本http://www.amazon.co.jp/dp/4798121967
■ IDDD 本http://www.amazon.co.jp/dp/479813161X
■クラウドデザインパターンhttp://www.amazon.co.jp/dp/4822277372/
■ Azure クラウドデザインパターンhttp://www.amazon.co.jp/dp/4822298337/
■ Developing Core Business Applications with Domain-Driven Design (DDD) and Microsoft .NEThttps://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/DEV-B311
参考文献
ご清聴ありがとうございました。
DDD で良いシステム開発を!