ドメイン駆動設計 基本を理解する

638
-1

Published on

アジャイル札幌 ドメイン駆動設計 基本を理解する

Published in: Software
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
638
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
5
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide

ドメイン駆動設計 基本を理解する

  1. 1. ドメイン駆動設計 基本を理解する 増田亨(@masuda220) ギルドワークス株式会社 取締役 有限会社システム設計 代表 2016年3月18日(金) 1
  2. 2. 本日の内容 • ドメイン駆動設計の「考え方」 • 「まえがき」を中心に – オブジェクト指向、エクストリームプログラミング • ドメイン駆動設計の「3つの原則」 • 1章 2章 3章から – ドメイン知識の習得、言葉による意図伝達、コードで表現 • ドメイン駆動設計の「基本スキル」 • 4章 5章 6章 7章から – ドメイン層の隔離、ドメインオブジェクトの設計、総合演習 2 ※「基本スキル」は、時間が足りなくなる見込み。あらかじめご了承ください。
  3. 3. はじめに 3
  4. 4. そんな人のために この本の要点を 実践経験をまじえながら 紹介します ⇒読み解くのが困難 ⇒実践でどう活用するか迷っている ⇒やってみたがうまくいかない 4
  5. 5. 5 • 出会ったのは10年前 –よくわからなかった • 現場で取り組み始めて8年 –8つの開発プロジェクト –4つの現場コーチ
  6. 6. ドメイン駆動設計の手ごたえ • 業務を学びながらソフトウェアを開発する 面白さ • ソフトウェアが育っていく楽しさ • 業務知識とコードが一致している時の コードのわかりやすさ • 変更が楽で安全になる気持ちよさ • 正しい仕事をしている安心感 6
  7. 7. ドメイン駆動設計のハードル • 発想の転換 – 「技術」駆動から「ドメイン」駆動へ – 「優れた設計」の基準の変化 • 設計・開発手法の切り替え – オブジェクト指向へ – エクストリームプログラミングへ • 実装の制約との戦い – フレームワークやプログラミング言語の制約 7
  8. 8. ドメイン駆動設計の 考え方 「まえがき」から 8
  9. 9. 「ドメイン駆動設計」とは 厳しい現実の中で、ソフトウェア設計を習 得しようと奮闘してきた技術者の物語。 不完全な状況の中で、抽象的な設計原 則を、現実のソフトウェアに適用するため の助言。 「日本語版への序文」 by エリック・エヴァンス 9
  10. 10. エヴァンスが取組んだ技法 オブジェクト指向 エクストリームプログラミング 10
  11. 11. 想定読者 • オブジェクト指向とエクストリームプログ ラミングに、ある程度の知識がある技術 者 • オブジェクト指向とエクストリームプログ ラミングの原則を、実際のアプリケーショ ン開発に適用しようとして、理屈通りに いかないことを経験した技術者 「まえがき」 11
  12. 12. オブジェクト指向 エクストリームプログラミング 12 私が「ドメイン駆動設計」を初めて読んだ時は、DOA/手続き型/ウォータ フォール系の技術者。OOもXPもある程度の知識はあったが未経験。 「ドメイン駆動設計」を読んでもわからない所がいっぱいあった。 でも「実践的でかつ優れた設計」の香りを感じた。 「オブジェクト指向」と「エクストリームプログラミング」を勉強しながら、 現場でいろいろ挑戦しているうちに「ドメイン駆動設計」の考え方とやり方が だんだんと理解できるようになった。
  13. 13. 勉強になる本 Wabi Sabiを読み解く オブジェクト指向へ エクストリームプログラミングへ 13 ソーシャルチェンジソフトウェアの構造と工法の転換
  14. 14. オブジェクト指向 エクストリームプログラミング 成長と変化を続ける 創発型のソフトウェア開発 この3つの底流にある共通の考え方・価値観 14 ドメイン駆動設計
  15. 15. オブジェクト指向の「変更容易性」 エクストリームプログラミングの「変化適応性」 • 「ドメイン駆動設計」も「エクストリームプログラミング」も、 「オブジェクト指向」のコミュニティで生まれ育った • オブジェクト指向の「変更容易性」が「創発型」の開発をうみだす • 3つは相互に補強しあう 創発型のソフトウェア開発 15 ドメイン駆動設計の「成長を続ける」ソフトウエア
  16. 16. オブジェクト指向 「変更容易性」の工夫 16 ドメイン駆動設計の土台となる技術
  17. 17. オブジェクト指向の「変更容易性」 • 抽象データ型 – 人間の知りたいこと/やりたいことを定義する • 内部の実装(データ型と処理手続き)は見せない • モジュール構造 – 抽象データ型を部品として全体を組み立てる • 「機能」や「手続き」を部品の単位にしない 17
  18. 18. 抽象データ型 18
  19. 19. 抽象データ型の例 : Java 標準API 19 抽象データ型 インタフェース 知りたいこと/やりたいこと 内部に隠された データ型 String 文字列 isEmpty() substring() split() ... char[] value int count BigInteger 任意精度の整数 add() subtract() multiply() …. int[] value int signum … LolcaDate 日付 isBefore() isAfter() plusDays() ... int year short month short day ArrayList 配列 isEmpty() add() contains() … Object[] data int size
  20. 20. LocalDate 「日付」を汎用的に扱うクラス int year; short month; short day; LocalDateの内部 DateOfBirth 「誕生日」に特化したクラス 人間の関心事を表現する抽象データ型を定義する 実装技術 もっと抽象化 人間の関心事に近づける Boolean 今月が誕生月() Days 誕生日まであと何日() plusDays(long days) plusMonths(long months) 20 Java言語仕様 基本データ型 Java標準API 汎用の抽象データ型 ドメインオブジェクト if( day > 31 ) … ;
  21. 21. 抽象データ型による「変更容易性」 • 人間の関心事と、プログラミングの単位が一致 – どこに何が書いてあるかわかりやすい – 関心事の変更と、コードの変更箇所が1対1に対応 • 変更がコードのあちこちに飛火しなくなる • 実装(内部のデータ構造やロジック)を隠す – データ構造やロジックを変更しても外部に波及しない – 変更した時の影響範囲を局所に限定できる 21
  22. 22. モジュール構造と 変更容易性 22
  23. 23. アンチパターン 機能単位にモジュール化 機能単位のモジュール化 機能クラスAと、機能クラスBに、同じデータを扱うロジックが重複する 変更時に、読む範囲が広がり、変更箇所が増え、テスト範囲が広がる 23 ビュー コントローラ サービス データアクセス … ビュー コントローラ サービス データアクセス … カプセル化をしているが 単なるデータ構造体
  24. 24. 抽象データ型によるモジュール化 抽象データ型: ◎知りたいこと/やりたいことだけを公開 ◎内部のデータ構造やロジックは見えない ◎判断・計算・加工のロジックが一箇所に集まる ◎変更時に、一箇所を読み、一箇所を変更し、一箇所テストする 24
  25. 25. オブジェクト指向への道 • 抽象データ型を設計するスキルを磨く • 抽象データ型の「利用者」から「生産者」になる – LocalDateを使って、年齢を計算するロジックを書い てみる(利用者) – LocalDateを持つDateOfBirthクラスを作って、年齢 の計算ロジックを内側に隠す(生産者) – DateOfBirthクラスを利用してみる(利用者) – 使ってみた感触を元に、DateOfBirthクラスを改良 する:コンストラクタの追加とか、今月が誕生月か の判定とか、… (生産者) 25
  26. 26. オブジェクト指向への道 • アンチパターンへの気づき – 言語の基本データ型(int, boolean, [], … ) と、標準API ( LocalDate, BigDecimal, ArrayList, … ) に執着したプログラミング – 「変数名」で意図を表現するプログラミング – コードの重複に無頓着なプログラミング • 処方箋 – 基本データ型、標準APIのクラスをラップした独自の抽象デー タ型を定義して利用することを習慣にする – 変数名ではなく、「型(クラスとインタフェース)」と「メソッド名」で 意図を表現することを習慣にする – コードの重複を減らして、変更が楽で安全になる設計を習慣に する 26
  27. 27. ドメイン駆動設計への道 • 業務の関心事を抽象データ型として表現する • 「顧客」クラス • 「商品」クラス • 「注文」クラス • 「数量」クラス • 「期日」クラス • 業務の「知りたいこと」「やりたいこと」をクラス名と メソッド名で表現する • 実装の詳細は意識しない/させない – 内部のデータ構造とロジックを見せない/推測しない 27 getter/setter を使わない
  28. 28. 「変化に適応する」ソフトウェア開発 28 エクストリームプログラミング ドメイン駆動設計の土台となる技術
  29. 29. 「適応型」のソフトウェア開発 開発 スタイル 方法論 ソフトウェアの 最終形 開発サイクル 予測型 ウォータ フォール 事前に厳密に定義 固定する 分析/設計/製造 反復・ 漸進型 RUP それなりに定義 反復ごとに精緻化 方向付/推敲/作成/移行 各フェーズで分析/設計/製造を、 N回「反復」する 適応 創発型 XP ざっくりと定義 日々更新 日、週、四季 (人間の生活リズム) 29
  30. 30. フェーズに分けない • 分析・設計・実装を「毎日」やる • 分析・設計・実装を「同じ人」がやる • なぜ「毎日」やるのか? – 効率的だから • 経験をもとに次の行動を決めたほうが、予測し事前準備す るより費用対効果が高い • なぜ「同じ人」がやるのか? – 効率的だから • 伝言ゲームをなくせる • 同じ人がやるとドキュメントの必要性が激減 30
  31. 31. 毎日、少しずつ成長する • 最終の着地点と、現在の進行方向を確認しな がら進む – 何か新しいことが起きていないか、「毎日」見直す – 進む方向がずれていないか、「毎日」見直す – 「週」で見直す、「季節」で見直す • 人も、ソフトウェアも、事業も、毎日/毎週/ 春夏秋冬で、少しずつ成長する • それが自然で理にかなったやり方 – 長続きする – 人間らしく暮らせる 31
  32. 32. エクストリームプログラミングへの道 • 効率を追求する – 専門家による分業が効率的か – コードを書かずに図やドキュメントの作成に時間 をかけることが効率的か – ドキュメントのレビューと承認に時間をかけること が効率的か – ルールを詳細に決めることが効率的か – 会議を増やすことが効率的か 32
  33. 33. エクストリームプログラミングへの道 • 「変化」と「成長」を健全性の尺度にする – 人、ドメインの理解、仕様、コード、… – 変化と成長が止まるのは「異常」で「不健全」 • 変化を楽で安全にするためのスキルを磨く – オブジェクト指向 – 抽象データ型によるモジュール化 33
  34. 34. 34 OO+XP=DDD?
  35. 35. OO+XP=ドメイン駆動設計? • YES ! • 「ドメイン駆動設計」は「オブジェクト指向」と 「エクストリームプログラミング」の合わせ技 – エクストリームなオブジェクト指向プログラミング • 「ドメイン駆動設計」は、OO+XPの考え方と やり方の「強調」する点をずらしている by エリック・エヴァンス 35
  36. 36. 「ドメイン駆動設計」が強調する点 • 「ドメインの知識」の継続的な学習 • 「言葉」を使った「モデリング」 • 「モデル」と「コード」を一致させる この三つを重視してソフトウェアを開発する それが「ドメイン駆動設計」 36
  37. 37. ドメインの知識をコードで表現 オブジェクト指向設計 インクリメンタルな設計(XP) ドメイン駆動設計 37
  38. 38. ドメイン駆動設計 ドメインを分析する人がコードを書く 毎日、分析し、毎日、コードを書く コードを書く人がドメインを分析する 分析・設計・実装を「フェーズ」に分けない 分析・設計・実装の「担当者」を別にしない 分析と実装を、同じ人が毎日やるなら、ドキュメントは不要 オブジェクト指向/XP 38 保守の現場ではあたりまえ?
  39. 39. ドメインを学び 学んだことを コードで表現する ドメイン駆動設計 39 オブジェクト指向/XP
  40. 40. 第1部 ドメインモデルを 機能させる 40
  41. 41. 「ドメイン駆動設計」の3原則 • 第1章 知識をかみ砕く(ドメインを学ぶ) • 第2章 コミュニケーションと言葉の使用 • 第3章 モデルと実装を結びつける 41
  42. 42. 言葉の整理 • ドメイン • ドメインとソフトウェア • モデル • ドメインモデル 42
  43. 43. ドメイン • ソフトウェアウェアを利用する人 たちの「活動」と「関心事」 – ソフトウェアの利用は、活動全体の一部 – 関心事の焦点は、ビジネスや業務上の成果 • ドメインではないこと – ソフトウェアを作る活動 – コンピュータの仕組みや挙動 – 画面仕様書/機能一覧/ユーザーストーリー/… 43
  44. 44. ドメインとソフトウェア 利用する人たちの 活動と関心事 ソフトウェア 44
  45. 45. 活動の目的/背景 活動の文脈 ソフトウェア 利用する人たちの 活動と関心事 45 活動の文脈まで視野を広げたほうが、ドメインを早く理解できる
  46. 46. モデル • 膨大な知識を「要約」した シンプルでわかりやすい説明 • モデリングのスキル=「要約力」 –重要な要素を発見する力 –本質的でないものを削る力 –厳密に組み立てる力 ドメイン駆動設計を実践する勘所:「要約力」を磨く 46
  47. 47. ドメインモデル • ソフトウェアを利用する人たちの「活動」 と「関心事」の本質を簡潔に表したもの • 表現 –チームでかわす会話 –ラフスケッチ –コード –(文章や図) 47
  48. 48. ドメインモデルを活用する ドメイン モデル ドメインの 「重要な関心事」を 鋭く説明する 選び抜かれた 重要な関心事を コードで表現する 会話を繰り返して 「要点」を明確にする 「重要な語彙」を チームで合意する 1章 2章 3章 48 第1章 ドメインの知識をかみ砕く 第3章 モデルと実装を結びつける 第2章 言葉を使った意図の伝達
  49. 49. 第1章 知識をかみ砕く 49
  50. 50. ドメインモデルを活用する ドメイン モデル ドメインの 「重要な関心事」を 鋭く説明する 選び抜かれた 重要な関心事を コードで表現する 会話を繰り返して 「要点」を明確にする 「重要な語彙」を チームで合意する 1章 2章 3章 50 第1章 ドメインの知識をかみ砕く 第3章 モデルと実装を結びつける 第2章 言葉を使った意図の伝達
  51. 51. 第1章の基本メッセージ 51 ソフトウェアを作るためには ドメインを学び続けること より広く より深く
  52. 52. 最初は何もわかっていない かろうじて聞き取れた言葉 52
  53. 53. 知識の広がり PCB設計者と会話をしながら 聞き取れる語彙がちょっと増えてきた 53
  54. 54. ある程度理解できたら 「モデル」が役に立つかコードで実験 だいぶ意思疎通ができるようになってきた段階のモデル PCB設計者の関心事をうまく説明し、かつ、 設計として役に立ちそうか実験 54
  55. 55. 本質的な関心事にたどり着いた 深いモデル PCB設計者の本質的な関心事をうまく説明しつつ、 ソフトウェアの基本構造としてそのまま使える「深いモデル」 55
  56. 56. 知識をかみ砕きながら モデルとコードを少しずつ成長させる 56
  57. 57. 第1章 知識をかみ砕く ソフトウェアを作るためにドメインを学び続ける 知識のないところから出発する 語彙を増やす(知識を広げる) コードで表現して確認する 本質的な関心事を探求する(深く理解する) 57
  58. 58. 第2章 コミュニケーションと 言葉の使い方 58
  59. 59. ドメインモデルを活用する ドメイン モデル ドメインの 「重要な関心事」を 鋭く説明する 選び抜かれた 重要な関心事を コードで表現する 会話を繰り返して 「要点」を明確にする 「重要な語彙」を チームで合意する 1章 2章 3章 59 第1章 ドメインの知識をかみ砕く 第3章 モデルと実装を結びつける 第2章 言葉を使った意図の伝達
  60. 60. 第2章の基本メッセージ 60 ソフトウェアを作るために ドメインの言葉を活用する いつでも どこでも 誰とでも
  61. 61. ユビキタス言語 • ドメインの言葉を使う – 技術用語を使わない • いつでも、どこでも、誰とでも – 技術者だけで話をする時もドメインの言葉で – コードもドメインの言葉で • 一つのチームに一つの言語 – 語彙 – 言い回し 61
  62. 62. 一つのチームに一つの言語 • 一つ言葉を同じ意味で – 要求仕様や画面に現れる「用語」と、ソフトウェア を利用する人たちが使う「言葉」の意味の食い違 いに注意 • 一つの意味は同じ言葉で – 同じ意味に思える「別の言葉」に敏感に • 同じ言葉を使うチームが「境界づけられたコ ンテキスト(第14章)」を形作る 62
  63. 63. Not ユビキタス言語 • フレームワークやプログラミングの用語は、ユ ビキタス言語ではない – String や LocalDate はユビキタス言語ではない – Boolean もユビキタス言語ではない – Stream も Optional もユビキタス言語ではない – null はユビキタス言語ではない – Entity や Value Object はユビキタス言語ではない • こういうものがドメイン層のクラスに表だって 登場してはいけない 63
  64. 64. 声に出してモデリングする • 良いモデルを見つける実践的な方法 – しゃべりにくい⇒良いモデルではない – 耳障りが悪い⇒良いモデルではない • 言葉の不一致を手掛かりに適切なモデルを探す – もう一回しゃべる 同じ言葉、同じ言い回しにならない – 会話にでてくる「話し言葉」と、コード/コミットログ/ チャット/メールなどに「書かれた言葉」が一致しない – 最初は、笑っちゃうくらう一致していない – チームのドメインの学習が進むにつれて、言葉とコー ドが一致してくる 64
  65. 65. 言葉たいせつ • 「エクストリームプログラミング」では、言葉を 使った会話がドキュメントの代わり – 意図伝達のもっとも効率的な手段 • 「言葉」が、そのままクラス/メソッド/パッ ケージの候補になる • あらゆる場所で同じ「言葉」を、同じ「意図」で – 会話/チャット/メール/コミットログ/ソースコード – 品質保証のもっとも効率的な手段 65
  66. 66. 言葉たいせつ •開発者が、利用者の「重要 な関心事」をよどみなく語 り始める安心感 •技術用語ばかり使う開発 者が書くコードへの恐怖感 66
  67. 67. 第3章 モデルと実装を結びつける 67
  68. 68. ドメインモデルを活用する ドメイン モデル ドメインの 「重要な関心事」を 鋭く説明する 選び抜かれた 重要な関心事を コードで表現する 会話を繰り返して 「要点」を明確にする 「重要な語彙」を チームで合意する 1章 2章 3章 68 第1章 ドメインの知識をかみ砕く 第3章 モデルと実装を結びつける 第2章 言葉を使った意図の伝達
  69. 69. 第3章の基本メッセージ 69 ソフトウェアを作るために 分析モデルと実装モデルを 一致させる
  70. 70. ドメイン駆動設計が求めるモデル • 初期の分析を支援するだけでなく、設計にお いて土台になるモデル • 分析と設計の両方に役に立つモデルを探す – 簡単には見つからない – 少しずつ学習し、実験し、良いモデルに育てる – 言葉による実験/コードによる実験 70
  71. 71. モデリングのパラダイム • オブジェクト指向 – 分析と実装を一致させる • 分析クラス=実装クラス – しかし、理屈通りにはなかなかうまくいかない – そこで「ドメイン駆動設計」 • 手続き型プログラミング – 基本データ型と、その操作になりがち – 動かすだけならてっとり早い – プログラムの構造と、人間の関心事が一致しない – 変更コストが膨らむ 71 ※論理型プログラミングは「述語論理」と一致する。 しかし、広くは採用されていない
  72. 72. ドメイン層の骨格を見せる • 「モデル」が、利用者の「重要な関心事」を反 映していれば、ドメイン層の主要なクラスを、 利用者がそのまま理解できる – 利用者自身にドメイン層の設計をレビューしても らう効果は大きい 72 クラスのスケッチ図を、画面レイアウトや画面遷移風に説明すると 意図が伝わりやすい 画面はドメインオブジェクトのビュー 主要な画面=主要なドメインオブジェクト
  73. 73. 実践的モデラ • コードを書く人がドメインを学び、業 務の重要な関心事を正しく理解する • それが、もっとも確実で、もっとも効 果的なソフトウェア開発手法 73 コードを書かない人が、利用者の活動や関心事 をどんなに理解しても、良いソフトウェアは生ま れない
  74. 74. 第1部のまとめ 74
  75. 75. ドメインモデルを活用する ドメイン モデル ドメインの 「重要な関心事」を 鋭く説明する 選び抜かれた 重要な関心事を コードで表現する 会話を繰り返して 「要点」を明確にする 「重要な語彙」を チームで合意する 1章 2章 3章 75 第1章 ドメインの知識をかみ砕く 第3章 モデルと実装を結びつける 第2章 言葉を使った意図の伝達
  76. 76. 第2部 モデル駆動設計の 構成要素 76 第3章 「モデルと実装を結びつける」 ための実践スキル
  77. 77. 第2部 モデル駆動設計の構成要素 • 第4章 ドメインを隔離する • 第5章 ソフトウェアで表現されたモデル • 第6章 ドメインオブジェクトのライフサイクル • 第7章 言語を使用する:応用例 77
  78. 78. モデルと実装の一致 • モデルと実装の一致は非常に難しい • では何をすべきか? –ドメインの隔離 –モデルをコードで表現する基本スキル –ドメインオブジェクトのライフサイクル –モデル駆動設計の進め方 78
  79. 79. 第2部は基礎練習 • ボールを蹴って止める基本の練習 • 相手に囲まれても確実にできる • 90分走りぬいたあとでも確実できる • ぬかるんだピッチでも確実にできる • 第2部の基本スキルを、厳しい現実やさまざまな 制約の中で、確実に使えるようになることが、 「第3部 深いモデル」、「第4部 戦略的設計」 を実践する土台になる。 79
  80. 80. 第4章 ドメインを隔離する 80
  81. 81. 第4章の基本メッセージ 81 ソフトウェアを作るために ドメインの複雑な知識を ドメイン層に集約して 整理する
  82. 82. レイヤ化アーキテクチャ 82
  83. 83. ドメインの「隔離」 • ドメイン層を「しっかり」分離する • 業務知識の他の層へのまぎれこみを防ぐ – プレゼンテーション層の業務ルール • ビュー定義内の if 文 – 太ったサービスクラス • トランザクションスクリプト • データの入れものだけのドメイン層のクラス – データソース層の業務知識 • where 句に埋め込まれた業務ルール • 動的SQLの組み立てに埋め込まれた業務ルール – テーブルの区分やフラグ • アンチパターンの宝庫 83
  84. 84. 継続的にドメイン層に移動する • てっとり早く修正するために、コントローラや ビューに業務知識を記述するアンチパターンが 横行する • 地道に、業務知識をプレゼンテーション層から抽 出して、ドメイン層に移動する努力を続ける • ドメイン層の業務知識が豊かになるほど、他の 層はすっきりしてくる – コードを複雑にする主因は、ドメインの複雑さ – その複雑さを、ドメイン層に集約して整理する 84
  85. 85. 第4章のまとめ • ドメイン層にドメインの知識を集め続ける • ドメイン層が膨らみ複雑になってくる – 良い兆候 • ドメイン層の整理を繰り返す – 「重要」な関心事と「些細」な関心事を、クラスやパッ ケージを使って分離する工夫を続ける – 関係性(クラスやパッケージの依存関係)をシンプル にする工夫を続ける – その過程で業務モデルの基本構造を発見できる • ドメインを深く理解したモデルとコードに成長する 85
  86. 86. 第5章 ソフトウェアで表現されたモデル 86
  87. 87. 第5章の基本メッセージ 87 ソフトウェアを作るために 分析と実装を一致させる そのための基本テクニック ドメインの関心事の抽出
  88. 88. 関心事を抽出する 88
  89. 89. 何が違うのか? 89
  90. 90. 関心事を分けて深堀する • 「顧客」 – 基本属性は何か – どうやって識別するか • 「住所」 – どう表現するか – 住所がない場合? – 複数の住所? – 住所が変わる時? 90
  91. 91. 第5章に登場する 関心事の抽出のテクニック エンティティ(参照オブジェクト) 値オブジェクト ドメインサービス モジュール(package) 91
  92. 92. エンティティ (参照オブジェクト) 92
  93. 93. 参照オブジェクト ドメイン駆動設計の Entity 93 集約のルート オブジェクトのコラボレーションの元締め 関心事への参照点 顧客との会話の語彙の起点 参照オブジェクト 値オブジェクト
  94. 94. 参照オブジェクトの設計 • 「識別」という関心事に集中する – 関心の対象の特定方法や発見方法 • 一覧の表示順 • 重要な検索軸の特定 – 技術的な一意識別とは別の視点 – 関心の対象の「内容」「状態」は「値オブジェクト」 にまかせる • 異なる関心事 • 別クラスに分けて議論し設計する 94
  95. 95. 値オブジェクト 95 ドメイン駆動設計の基本中の基本
  96. 96. 値オブジェクト String List<String> BigDecimal Integer … LocalDate Long 起算日 InitialDate 期限 DueDate 有効期間 ValidTerm 金額 Money 数量 Quantity 単位 Unit 品名 ProductName 備考 Remarks 摘要 Abstract 言語で用意された「型」 (汎用) 独自に定義した「型」 (目的特化) 96
  97. 97. 値オブジェクトの設計 • 完全コンストラクタ – すべてのインスタンス変数は、生成時に設定 • 不変 – setter を書かない(状態を変えない) – 値を変更する時は、別のオブジェクトを生成して返す – 不変による「安定」 • ロジックの置き場所 – インスタンス変数を使った、判断・加工・計算 – 何もしないで素のデータを返す getter はNG 97
  98. 98. 値オブジェクト • 業務の関心事の基本語彙の抽出手段 目的を限定した抽象データ型 – String, BigDecimal, LocalDateの値の範囲、文字 種、形式、計算範囲を業務に合わせて制限する – 用途を限定するとプログラムが安定する – コードの重複がなくなり、変更が楽になる • 関心事を豊かに表現する手段 – メソッドの戻す値の「型」 – メソッドの引数の「型」 98
  99. 99. ドメイン層のサービスクラス 99
  100. 100. ドメイン層のサービス • 「参照オブジェクト」や「値オブジェクト」に置く べき場所に迷う業務知識 • その業務知識に名前を付けてクラスとして抽 出してみる(実験) – XxxPolicy – XxxRule – XxxProcedure … 100
  101. 101. ドメイン層のサービス 危険! • 「手続き」にドメインの「関心事」が隠ぺいされがち – 深いモデルの探求の手掛りを見失う • 同じ「ロジック」が複数サービスに重複しがち – 変更コストがあがる – モデルとコードの成長の障害になる • 処方箋 – メソッドの引数と型は「ドメインオブジェクト」にする • long や Stringを使わない – 基本用途は区分オブジェクトの振る舞いの実装 • 区分ごとのビジネスルールを記述するクラス – それ以外の場合、リファクタリングの候補としておく • より適切な置き場所を模索する 101
  102. 102. モジュール(パッケージ) 102
  103. 103. モジュール(Packages) • 関心事の抽出手段 – 関連するドメインオブジェクトのグループ化 – 利用者の関心事の「境界」の表現 – 業務上の依存関係の表現(パッケージ依存関係) • リファクタリングの対象 – 業務知識が増え、業務の理解が深まるたびに、 パッケージ名/パッケージ構成を変更する 103 第4部「戦略的設計」の主要ツール
  104. 104. そのほかの関心事の抽出テクニック 一覧オブジェクト (ファーストクラスコレクション) 区分オブジェクト (場合ごとのビジネスルールの表現) HowよりWhat (意図の明白なインタフェース) 104
  105. 105. 一覧オブジェクト (ファーストクラスコレクション) 105
  106. 106. 一覧オブジェクト (ファーストクラスコレクション) • ListやSetをラップしたドメインオブジェクト • Offers • MailBox • SkillSet • 「一覧」や「履歴」という関心事の表現 – 「一覧」は利用者の関心事が集中する場所 – 「一覧」の議論は、重要な関心事の発見の良い機会 • コレクションの操作は、コードがごちゃごちゃしや すく、変更の副作用が多い – クラスとして独立させ、そのクラスに閉じ込める 106 9章 概念を掘り出す 10章 概念の輪郭
  107. 107. 区分オブジェクト (場合ごとのビジネスルールの表現) 107
  108. 108. 区分オブジェクト • 振る舞いを持った Enum • 区分ごとのロジックを別クラスに記述 • Java言語使用に組み込まれた Strategy/Stateパターン 説明とコード例は、googleで 「場合わけの書き方あれこれ」で検索。 または「オブジェクト指向をきちんと使 いたいあなたへ」 場合ごとのビジネスルールの表現 108
  109. 109. 区分オブジェクトの効果 • 関心事の明示的なコード表現 • 複雑な if文記述の解消 – 区分ごとの分岐記述( if文 or switch文 )は、一箇所 になる – 場合によっては、まったく書かなくてよくなる • どこに何が書いてあるかわかりやすくなる – 区分ごとの業務ルールや知識のロジックの置き場所 をクラス単位で分離 • 区分の追加や削除をした時の、変更の副作用が 少ない 109 9章 概念を掘り出す 10章 概念の輪郭
  110. 110. How より What (意図の明確なインタフェース) 110
  111. 111. expireDate.add(-1); expireDate.previousDay(); expireDate.dayOfFinalAlert (); 業務要件:期限切れの前日にアラートメールを送る How より What 業務の関心事を明示的に表現する 111
  112. 112. 課金ポリシー 適用する() シーズン料金 レート() 夏料金 レート() 冬料金 レート() 料金 計算() <<interface>> 計算方法(How)を記述 料金の用語(What)をクラスで表現 計算()メソッドに埋もれ、 暗黙化する業務知識 シンプルな設計に見えるが、 ルールの変更・追加のたびに 計算()メソッドが肥大化し、 if 文が増殖する 業務知識をそのまま、クラスとして表現 複雑に見えるが、ルール変更・追加が、 楽で安全になる How より What 112 9章 概念を掘り出す 10章 概念の輪郭
  113. 113. モデリングパラダイム 113 第5章 ソフトウェアで表現されたモデル
  114. 114. • なぜオブジェクトパラダイムが主流なのか – モデリングの手法としても実装の手法としてもうま く使える実践的な技法だから – 広範囲に使われ成熟してきたから • ツール、モデリングや設計のノウハウ、実例 • オブジェクト世界のオブジェクトではないもの – 述語論理、ワークフロー、関係データベース、… • オブジェクト指向を軸にして非オブジェクトの 要素を混ぜ合わせる4つの経験則 – パラダイムの混在には慎重にかつ保守的に 114
  115. 115. 第5章のまとめ • 「モデル」と「実装」の一致は難しい • オブジェクト指向の基本を学び、体で覚えな がら、関心事の分離とコード表現のスキルを 磨く • それが第3部、第4部の土台になる – 役に立つのは「深いモデル」を見つけた時 – 大きな効果がでるのは「戦略的」に取り組んだ時 115
  116. 116. 第6章 ドメインオブジェクトの ライフサイクル 116
  117. 117. 第6章の基本メッセージ 117 オブジェクトの生成と永続化は コードを複雑にしがち ドメインオブジェクトの 意図と役割を明確にする工夫 (生成や永続化を分離する)
  118. 118. 第6章の問題意識と解決方法 • 複雑になりがち – オブジェクトのライフサイクル管理 • 生成/格納・再構成/修正/削除 • オブジェクト間の整合性 • 「モデル」をこの複雑さから守る – ドメインオブジェクトを「集約」としてグルーピング – オブジェクトの生成は「ファクトリ」にまかせる – オブジェクトの永続化は「リポジトリ」にまかせる 118
  119. 119. 「集約」 • ドメインオブジェクトのネットワーク – 利用者の「活動」や「関心事」の結びつきを反映 – 必然的に複雑になる • 「集約」してオブジェクトのグループとして扱う – 「ひとかたまり」として扱うべきオブジェクトの集合を探 す – 他のオブジェクトグループ(集約)との境界を検討す る – 独立性の高い、意図の明確な「集約」の発見が、ドメ イン層の見通しをよくし、プログラムを安定させる 119
  120. 120. 生成を「ファクトリ」にまかせる • オブジェクトの集約の生成 – エンティティ(集約のルート)が、自分で生成に責任を 持ち始めると、エンティティ本来の関心事(識別)があ いまいになる • 生成ロジックの置き場所の選択肢 – 「集約のルート」の static なファクトリメソッド – 「集約の生成」に関わるオブジェクトのファクトリメソッ ド – コンストラクタ – 独立したファクトリクラス … 120
  121. 121. 永続化を「リポジトリ」にまかせる • 必要なオブジェクトの集約を入手する • あたかもすべてのドメインオブジェクトがメモリ上 にあるように設計する – データベース設計やORマッピングをいったん忘れる – interface 宣言で実装を分離する • やりたいことをシンプルに宣言する • 注文 findBy(管理番号) • 注文一覧 lookFor(検索条件) • void register(注文) 121
  122. 122. 第7章 言語を使用する:応用例 122
  123. 123. 第7章 言語を使用する:応用例 • 4章、5章、6章の「基本構成要素」を組み合わ せる実戦に近い練習 • 仮想的なチームが要求と実装の問題に対処しな がら「モデル駆動設計」で開発をしていく例 • その過程で生じる「さまざまな問題」と「どう解決」 されるかを見ていく • 第7章の書かれた意図を読み取るのはたいへん – その分、ドメイン駆動設計の考え方とやり方の発見と 学びが多い章 123
  124. 124. 第7章のストーリ展開 1. 貨物輸送システムの概要 2. ドメインを隔離する:アプリケーション層の導入 3. エンティティと値オブジェクトを区別する 4. 輸送ドメインの「関連」を設計する 5. 「集約」の境界を検討する 6. 「リポジトリ」を選択する 7. シナリオをウォークスルーする 8. オブジェクトの生成 9. リファクタリングのために立ち止まる 10. 輸送モデルにおける「モジュール」 11. 新機能を導入する:配分チェック 12. 最後に 124
  125. 125. 第7章はより実戦に近い練習 • 「モデル」と「実装」が育っていく過程とリズム • 「モデル駆動」で設計するということ – まず「アプリケーション層」を導入する • 「ドメイン層」の議論を「機能」視点から隔離する • 機能(処理)の詳細化からの設計ではない – 入出力項目(画面帳票)の定義は登場しない • プレゼンテーション層無しのドメイン層の設計と実装 – データモデル/テーブル設計は登場しない • データモデルから独立したドメイン層の設計と実装 125
  126. 126. 関連・集約・リポジトリ • 第7章の議論のハイライト • 「関連」を設計する – 関連の方向の議論はドメインに対する洞察 – 複雑な実装を避ける(成長容易性の確保) • 「集約」の境界を検討する – ドメインオブジェクトの「かたまり」の定義 – 概念(関心事)の境界の明確化 – 開発単位 • 「リポジトリ」を選択する – 機能視点が登場するタイミング • 検索/選択/登録 … 126
  127. 127. 本日のまとめ 127
  128. 128. ドメイン駆動設計 エクストリームなオブジェクト指向プログラミングでドメイン層を構築する 少しずつソフトウェアを成長させる「適応創発型」の開発スタイル オブジェクト指向 エクストリームプログラミング 128 ドメインの知識をコードで表現する
  129. 129. ドメインモデル活用する ドメイン モデル ドメインの 「重要な関心事」を 鋭く説明する 選び抜かれた 重要な関心事を コードで表現する 会話を繰り返して 「要点」を明確にする 「重要な語彙」を チームで合意する 1章 2章 3章 129 第1章 ドメインの知識をかみ砕く 第3章 モデルと実装を結びつける 第2章 言葉を使った意図の伝達
  130. 130. より深く、より広く 第3部 「より深い洞察に向かうリファクタリング」 深いモデルの価値 ドメイン知識の表現力を改良するリファクタリング 第4部 「戦略的設計」 より広い範囲で長期的に実践するための工夫 130
  131. 131. ドメイン駆動設計への道 131
  132. 132. できない理由? • 今のプロジェクトでは無理 • 今のチームでは無理 • 今の会社では無理 • 今の自分の力では無理 … 132
  133. 133. • どんな状況でも改善できる • どんなときでも「あなた」から改善を始められる • どんなときでも「今日」から改善を始められる ケント・ベックのメッセージ 133
  134. 134. ドメイン駆動設計への道 134 どんな状況でも「ドメインの知識」を学ぶことはできる どんな時でも「ドメインの言葉」で話すことはできる どんな時でもドメインの言葉を「コード」に反映できる

×