ボトムアップドメイン駆動設計 前編 / bottomup-ddd-1

E37b4344ef4bfd0fc4826c04971e54fb?s=47 nrs
October 28, 2018

ボトムアップドメイン駆動設計 前編 / bottomup-ddd-1

# URL
後編: https://speakerdeck.com/nrslib/bottomup-ddd-2
解説記事: https://nrslib.com/bottomup-ddd/
勉強会情報: https://ddd-community-jp.connpass.com/event/103428/
Twitter: https://twitter.com/nrslib

# 概要
2018/10/23 GMO Yours で行われた「ボトムアップドメイン駆動設計」の登壇資料前編です
口頭での解説前提のためわかりづらい部分もあるかと思いますがご了承ください。

E37b4344ef4bfd0fc4826c04971e54fb?s=128

nrs

October 28, 2018
Tweet

Transcript

  1. Masanobu Naruse BOTTOM UP DOMAIN DRIVEN DESIGN

  2. もくじ • はじめに • 値オブジェクト • エンティティ • ドメインサービス •

    リポジトリ • アプリケーションサービス • ファクトリ • トランザクション • 集約 • アーキテクチャ • ドメイン駆動設計への誘い 2
  3. はじめに 3 読んだ方はいらっしゃいますか

  4. はじめに 4 読み切った方はいらっしゃいますか

  5. はじめに 5 理解した方はいらっしゃいますか

  6. はじめに | 辛さの原因 6 辛さの原因は?

  7. はじめに | 辛さの原因 7 ユビキタス言語

  8. はじめに | 辛さの原因 8 ユビキタス言語 ドメインエキスパート

  9. はじめに | 辛さの原因 9 ユビキタス言語 ドメインエキスパート エンティティ

  10. はじめに | 辛さの原因 10 ユビキタス言語 ドメインエキスパート エンティティ 値オブジェクト

  11. はじめに | 辛さの原因 11 ユビキタス言語 ドメインエキスパート エンティティ 値オブジェクト ドメインサービス

  12. はじめに | 辛さの原因 12 ユビキタス言語 ドメインエキスパート エンティティ 値オブジェクト ドメインサービス アプリケーションサービス

  13. はじめに | 辛さの原因 13 ユビキタス言語 ドメインエキスパート エンティティ 値オブジェクト リポジトリ ファクトリ

    ドメインサービス アプリケーションサービス 集約
  14. 集約 はじめに | 辛さの原因 14 ユビキタス言語 ドメインエキスパート エンティティ 値オブジェクト ドメインサービス

    アプリケーションサービス リポジトリ ファクトリ 怖い
  15. はじめに | 辛さの原因 15 ドメイン駆動設計 ?

  16. はじめに | 辛さの原因 16 ドメイン駆動設計 オブジェクト指向の実践

  17. はじめに | 辛さの原因 17 敬遠されるのは勿体ない ドメイン駆動設計 オブジェクト指向の実践

  18. はじめに | 辛さの原因 18 怖い ? = 辛さの原因 = ?

    こと だらけ
  19. はじめに | 辛さの原因 19 怖い 知らない = 辛さの原因 = 知らないこと

    だらけ
  20. はじめに | 用語 20 用語

  21. はじめに | 用語 21 用語

  22. はじめに | 用語 22 マインド パターン 用語

  23. はじめに | 用語 23 マインド パターン 感じるしかない 用語

  24. はじめに | 用語 24 マインド パターン 感じるしかない 実装できる 用語

  25. はじめに | 用語 25 用語と実装がイメージできれば 辛さは半分になるのでは?

  26. はじめに | 用語 26 いきなり全容を説明しても 辛いから ボトムアップに解説したら 役に立ちそう

  27. はじめに | 用語 27 いきなり全容を説明しても 辛いから ボトムアップに解説したら 役に立ちそう と考えて早一年 書籍化依頼こないかなー・・・

    とか漠然と思ってました
  28. はじめに | 記事 ボトムアップドメイン駆動設計 28 https://nrslib.com/bottomup-ddd/ https://nrslib.com/bottomup-ddd-2/ というわけで解説記事にしてみた

  29. はじめに | 記事 ボトムアップドメイン駆動設計 29 https://nrslib.com/bottomup-ddd/ https://nrslib.com/bottomup-ddd-2/ というわけで解説記事にしてみた そもそもこの解説記事が辛い

  30. はじめに | 記事 ボトムアップドメイン駆動設計 30 https://nrslib.com/bottomup-ddd/ https://nrslib.com/bottomup-ddd-2/ というわけで解説記事にしてみた そもそもこの解説記事が辛い

  31. はじめに | 趣旨 31 今回のセミナーの趣旨

  32. はじめに | 趣旨 32 イントロダクションはセミナーで 今回のセミナーの趣旨

  33. はじめに | 趣旨 33 イントロダクションはセミナーで 細かい部分は記事で 今回のセミナーの趣旨

  34. はじめに | 趣旨 34 イントロダクションはセミナーで 細かい部分は記事で マインドは書籍で 今回のセミナーの趣旨

  35. はじめに | ゴール 35 ゴール Evans の本を読む下地を作る

  36. 値オブジェクト VALUE OBJECT

  37. 値オブジェクト 37 値って何ですか

  38. 値オブジェクト 38 例えば数値

  39. 値オブジェクト 39

  40. 値オブジェクト 40 ここは何していますか

  41. 値オブジェクト 41 例えば文字列

  42. 値オブジェクト 42

  43. 値オブジェクト 43 ここは何していますか

  44. 値オブジェクト 44 値の変更は代入

  45. 値オブジェクト 45 値の変更は代入 こんなことはしない

  46. 値オブジェクト 46 じゃあ 値を示すオブジェクトも 値らしくしよう

  47. 値オブジェクト 47 じゃあ 値を示すオブジェクトも 値らしくしよう 値オブジェクト

  48. 値オブジェクト | 値の性質 48 状態を不変に保つ 値同士の比較ができる 完全に交換可能である 値の性質

  49. 値オブジェクト | 状態を不変に保つ 49 状態を不変に保つ 値同士の比較ができる 完全に交換可能である 値の性質

  50. 値オブジェクト | 状態を不変に保つ 50 状態とは?

  51. 値オブジェクト | 状態を不変に保つ 51 状態 フィールド =

  52. 値オブジェクト | 状態を不変に保つ 52

  53. 値オブジェクト | 状態を不変に保つ 53 これらがダメなら

  54. 値オブジェクト | 状態を不変に保つ 54 これらがダメなら

  55. 値オブジェクト | 状態を不変に保つ 55 これもダメ これらがダメなら

  56. 値オブジェクト | 状態を不変に保つ 56

  57. 値オブジェクト | 状態を不変に保つ 57 値の変更は代入で

  58. 値オブジェクト | 状態を不変に保つ 58 値の変更は代入で

  59. 値オブジェクト | 状態を不変に保つ 59 メリット 不変であることそれ自体 ・可変な状態は取り扱いが難しい ・並行/並列処理では特に難しい ・キャッシュ可能 etc…

  60. 値オブジェクト | 値同士の比較ができる 60 値の性質 状態を不変に保つ 値同士の比較ができる 完全に交換可能である

  61. 値オブジェクト | 値同士の比較ができる 61 値の比較の仕方は?

  62. 値オブジェクト | 値同士の比較ができる 62 値の比較の仕方は?

  63. 値オブジェクト | 値同士の比較ができる 63 値の比較の仕方は? こうは書かない

  64. 値オブジェクト | 値同士の比較ができる 64 じゃあ値オブジェクトも こう書かない

  65. 値オブジェクト | 値同士の比較ができる 65 値のように表現すべき

  66. 値オブジェクト | 値同士の比較ができる 66 比較のための実装

  67. 値オブジェクト | 値同士の比較ができる 67 比較のための実装

  68. 値オブジェクト | 値同士の比較ができる 68 Snipet や Resharper などの Tool で生成

    比較のための実装
  69. 値オブジェクト | 値同士の比較ができる 69 メリット 値の変更箇所の集約

  70. 値オブジェクト | 値同士の比較ができる 70 変更してみよう 属性比較版 比較メソッド版

  71. 値オブジェクト | 値同士の比較ができる 71 値に属性を追加 変更してみよう 属性比較版 比較メソッド版

  72. 値オブジェクト | 値同士の比較ができる 72 値に属性を追加 変更してみよう 属性比較版 比較メソッド版

  73. 値オブジェクト | 値同士の比較ができる 73 値に属性を追加 変更してみよう 属性比較版 比較メソッド版

  74. 値オブジェクト | 値同士の比較ができる 74 比較する必要ができたら追加でいい

  75. 値オブジェクト | 値同士の比較ができる 75 状態を不変に保つ 値同士の比較ができる 完全に交換可能である 値の性質

  76. 値オブジェクト | 完全に交換可能である 76 復習

  77. 値オブジェクト | 完全に交換可能である 77 Q. 値の変更を行う方法は? 復習

  78. 値オブジェクト | 完全に交換可能である 78 Q. 値の変更を行う方法は? 復習 A. 代入

  79. 値オブジェクト | 完全に交換可能である 79 代入って要するに 交換

  80. 値オブジェクト | 完全に交換可能である 80 代入って要するに 交換 値を不変にしたことで 交換以外の 変更の表現手段がなくなった

  81. 値オブジェクト | モチベーション 81 値オブジェクトにするモチベーションは?

  82. 値オブジェクト | モチベーション 82 表現力が増す 存在しない値を存在させない 誤った代入を防ぐ 値オブジェクトのモチベーション

  83. 値オブジェクト | 表現力が増す 83 表現力が増す 存在しない値を存在させない 誤った代入を防ぐ 値オブジェクトのモチベーション

  84. 値オブジェクト | 表現力が増す 84 表現力が増します

  85. 値オブジェクト | 存在しない値を存在させない 85 表現力が増す 存在しない値を存在させない 誤った代入を防ぐ 値オブジェクトのモチベーション

  86. 値オブジェクト | 存在しない値を存在させない 86 例 ユーザ名の長さは?

  87. 値オブジェクト | 存在しない値を存在させない 87 仮にユーザ名の長さを 50 文字以下とする

  88. 値オブジェクト | 存在しない値を存在させない 88

  89. 値オブジェクト | 存在しない値を存在させない 89 コードで表現

  90. 値オブジェクト | 存在しない値を存在させない 90 コードで表現 50文字を超えるユーザ名という 本来あり得ないものを存在させない

  91. 値オブジェクト | 誤った代入を防ぐ 91 表現力が増す 存在しない値を存在させない 誤った代入を防ぐ 値オブジェクトのモチベーション

  92. 値オブジェクト | 誤った代入を防ぐ 92 代入を間違えたこと ありますか?

  93. 値オブジェクト | 誤った代入を防ぐ 93 こんなクラス

  94. 値オブジェクト | 誤った代入を防ぐ 94 こんなクラス こんなメソッド と

  95. 値オブジェクト | 誤った代入を防ぐ 95 こんなクラス こんなメソッド と Id に name

    を代入してるけど 正しい?
  96. 値オブジェクト | 誤った代入を防ぐ 96 値オブジェクトで表現したら

  97. 値オブジェクト | 誤った代入を防ぐ 97 値オブジェクトで表現したら

  98. 値オブジェクト | 誤った代入を防ぐ 98 値オブジェクトで表現したら

  99. 値オブジェクト | 誤った代入を防ぐ 99 誤った代入が 発生しづらくなる 値オブジェクトで表現したら

  100. 値オブジェクト | まとめ 100 プリミティブな値を無理やり利用せず システム固有の値を作り表現力を増す 実装上の安全性を増す

  101. エンティティ ENTITY

  102. エンティティ 102 次のお題は エンティティ

  103. エンティティ 103 エンティティとは 属性ではなく 同一性によって 識別されるモデル

  104. エンティティ 104 エンティティとは

  105. エンティティ 105 エンティティとは (値オブジェクトの逆)

  106. エンティティ 106 可変 同じ属性でも区別される 同一性を持つ エンティティの性質

  107. エンティティ | 可変 107 可変 同じ属性でも区別される 同一性を持つ エンティティの性質

  108. エンティティ | 可変 108

  109. エンティティ | 可変 109 名前を変更できるようにしたい

  110. エンティティ | 可変 110

  111. エンティティ | 可変 111 属性が可変

  112. エンティティ | 可変 112 可変 同じ属性でも区別される 同一性を持つ エンティティの性質

  113. エンティティ | 同じ属性でも区別される 113 ユーザ A ユーザ B

  114. エンティティ | 同じ属性でも区別される 114 ユーザ A ユーザ B FirstName: taro

    FamilyName: tanaka FirstName: taro FamilyName: tanaka
  115. エンティティ | 同じ属性でも区別される 115 ユーザ A ユーザ B FirstName: taro

    FamilyName: tanaka FirstName: taro FamilyName: tanaka 同じユーザ?
  116. エンティティ | 同じ属性でも区別される 116

  117. エンティティ | 同じ属性でも区別される 117 true or false?

  118. エンティティ | 同じ属性でも区別される 118 属性が同じでも同姓同名かもしれない

  119. エンティティ | 同じ属性でも区別される 119 ユーザを識別する必要がある 属性が同じでも同姓同名かもしれない

  120. エンティティ | 同じ属性でも区別される 120 識別子が必要 属性が同じでも同姓同名かもしれない ユーザを識別する必要がある

  121. エンティティ | 同じ属性でも区別される 121 ID を示す 値オブジェクトを作って

  122. エンティティ | 同じ属性でも区別される 122

  123. エンティティ | 同じ属性でも区別される 123 ユーザ A ユーザ B FirstName: taro

    FamilyName: tanaka Id: A FirstName: taro FamilyName: tanaka Id: B
  124. エンティティ | 同じ属性でも区別される 124 ユーザ A ユーザ B FirstName: taro

    FamilyName: tanaka Id: A FirstName: taro FamilyName: tanaka Id: B IDで識別できるようになった
  125. エンティティ | 可変 125 可変 同じ属性でも区別される 同一性を持つ エンティティの性質

  126. エンティティ | 同一性を持つ 126 FirstName: taro FamilyName: tanaka

  127. エンティティ | 同一性を持つ 127 FirstName: taro FamilyName: tanaka FirstName: taro

    FamilyName: sato
  128. 別人? エンティティ | 同一性を持つ 128 FirstName: taro FamilyName: tanaka FirstName:

    taro FamilyName: sato
  129. 別人? エンティティ | 同一性を持つ 129 FirstName: taro FamilyName: tanaka FirstName:

    taro FamilyName: sato 同一人物
  130. 別人? エンティティ | 同一性を持つ 130 FirstName: taro FamilyName: tanaka Id:

    A FirstName: taro FamilyName: sato Id: A 同一人物
  131. エンティティ | 同一性を持つ 131 ID で比較をする ※これはツールによる実装

  132. エンティティ | 同一性を持つ 132 結果

  133. エンティティ | まとめ 133 属性ではなく 同一性によって 識別されるモデル ライフサイクルを持っている

  134. サービス(ドメインサービス) SERVICE (DOMAIN SERVICE)

  135. ドメインサービス 135 全ての混乱の原因

  136. ドメインサービス 136 サービスという言葉 全ての混乱の原因

  137. ドメインサービス 137 Web サービス サービス指向アーキテクチャ アプリケーションサービス ドメインサービス マイクロサービス Saas Paas

    Iaas
  138. ドメインサービス 138 サービスという言葉の付く単語は 世の中にごまんとある

  139. ドメインサービス 139 ドメインサービスは

  140. ドメインサービス 140 ドメインサービスは エンティティや値オブジェクトに 実装するのが自然でない処理を 実装するオブジェクト

  141. ドメインサービス 141 例えばユーザ登録で 「ユーザ名の重複を許さない」 というケース

  142. ドメインサービス 142 エンティティに定義してみよう

  143. ドメインサービス 143 エンティティに定義してみよう

  144. ドメインサービス 144 エンティティに定義してみよう 使ってみる

  145. ドメインサービス 145 使ってみる 自分に問い合わせ?? エンティティに定義してみよう

  146. ドメインサービス 146 チェック専用オブジェクトを作る

  147. ドメインサービス 147 チェック専用オブジェクトを作る

  148. ドメインサービス 148 チェック専用オブジェクトを作る ‘forcheck’ さんって誰?

  149. ドメインサービス 149 つまりこれは エンティティに 実装するのが自然でない処理

  150. ドメインサービス 150 つまりこれは エンティティに 実装するのが自然でない処理 ドメインサービス

  151. ドメインサービス 151 ドメインサービス 実装は後程

  152. ビジネスロジックを組み立てよう 152 最小限のモデリング要素は学んだので ロジックを組み立ててみよう

  153. ビジネスロジックを組み立てよう 153 最小限のモデリング要素は学んだので ロジックを組み立ててみよう お題はユーザ登録

  154. ビジネスロジックを組み立てよう 154

  155. ビジネスロジックを組み立てよう 155 MySQL を使うとしたら

  156. ビジネスロジックを組み立てよう 156 こんな感じ?

  157. ビジネスロジックを組み立てよう 157 きっとドメインサービスも

  158. ビジネスロジックを組み立てよう 158 こうなる きっとドメインサービスも

  159. ビジネスロジックを組み立てよう 159 データベースは大事

  160. ビジネスロジックを組み立てよう 160 だけど

  161. ビジネスロジックを組み立てよう 161 ユーザ登録処理という ロジックの大半を 占めるべき内容か

  162. リポジトリ REPOSITORY

  163. リポジトリ 163 リポジトリは

  164. リポジトリ 164 リポジトリは データの永続化を担う オブジェクト

  165. リポジトリ 165 リポジトリは データの永続化を担う オブジェクト 永続化の対象 =

  166. リポジトリ 166 リポジトリは データの永続化を担う オブジェクト 永続化の対象 = エンティティ

  167. リポジトリ 167 リポジトリを作ってみよう

  168. リポジトリ 168

  169. リポジトリ 169 永続化装置からの再構築(検索)

  170. リポジトリ 170 永続化装置からの再構築(検索) 永続化

  171. リポジトリ 171

  172. リポジトリ 172 すっきり

  173. リポジトリ 173 きっとドメインサービスも

  174. リポジトリ 174 きっとドメインサービスも こうなる

  175. リポジトリ 175 結果として こうなる

  176. リポジトリ | テスト 176 ところでテストって好きですか?

  177. リポジトリ | テスト 177 どうやってテストする?

  178. リポジトリ | テスト 178 どうやってテストする?

  179. リポジトリ | テスト 179 どうやってテストする? データベースに接続

  180. リポジトリ | テスト 180 どうやってテストする? データベースにデータを用意する・・・ データベースに接続

  181. リポジトリ | テスト 181 ここからがリポジトリの 本領発揮です

  182. リポジトリ | テスト 182 まずはリポジトリの インターフェースを用意 ※インターフェースがない言語は完全抽象クラスで

  183. リポジトリ | テスト 183 本番用リポジトリはインターフェースを実装

  184. リポジトリ | テスト 184 テストのためのリポジトリを用意

  185. リポジトリ | テスト 185 さっきのロジックは

  186. リポジトリ | テスト 186 こうなる

  187. リポジトリ | テスト 187

  188. リポジトリ | テスト 188

  189. リポジトリ | テスト 189 InMemoryUserRepository or UserRepository

  190. リポジトリ | テスト 190 InMemoryUserRepository or UserRepository

  191. リポジトリ | テスト 191 InMemoryUserRepository or UserRepository

  192. リポジトリ | テスト 192 このロジックは依存がなくなった

  193. リポジトリ | テスト 193 このロジックは依存がなくなった 依存 =

  194. リポジトリ | テスト 194 このロジックは依存がなくなった UserRepository への依存 特定のインフラへの依存 依存 =

  195. リポジトリ | 純粋なロジックとして 195 InMemoryUserRepository に 再現したいデータを用意しておけば テストができる

  196. リポジトリ | 純粋なロジックとして 196 InMemoryUserRepository に 再現したいデータを用意しておけば テストができる 特定の具象オブジェクトに依存しないので 本番と同じロジックを使ってテストができる

  197. アプリケーションサービス 197 次のテーマは アプリケーションサービス

  198. アプリケーションサービス 198 アプリケーションサービスは ビジネスロジックの API

  199. アプリケーションサービス 199 アプリケーションサービスは ビジネスロジックの API 何ができるかを表現

  200. アプリケーションサービス 200 ユースケースを表現

  201. アプリケーションサービス 201

  202. アプリケーションサービス 202 どこかで見たことが ありませんか

  203. アプリケーションサービス 203 これまで出てきた Program クラスは 実はアプリケーションサービス

  204. アプリケーションサービス 204 アプリケーションサービスは

  205. アプリケーションサービス 205 エンティティ 値オブジェクト ドメインサービス リポジトリ アプリケーションサービスは

  206. アプリケーションサービス 206 エンティティ 値オブジェクト ドメインサービス リポジトリ これらを協調させて ユースケースを達成する アプリケーションサービスは

  207. アプリケーションサービス 207 ユースケースが達成できる

  208. アプリケーションサービス 208 ユースケースが達成できる アプリが作れる

  209. アプリケーションサービス | MVC 209 MVC フレームワークに組み込もう

  210. アプリケーションサービス | MVC 210

  211. アプリケーションサービス | MVC 211 Dependency Injection

  212. アプリケーションサービス | DI 212 Dependency Injection

  213. アプリケーションサービス | DI 213 Dependency Injection 依存しているオブジェクトを コンストラクタ等から引き渡す(注入)する

  214. アプリケーションサービス | DI 214 Dependency Injection 依存しているオブジェクトを コンストラクタ等から引き渡す(注入)する

  215. アプリケーションサービス | DI 215 MVC フレームワークでは Controller のコンストラクタは フレームワークが呼び出しを行うので IoC

    Container (DI Container) を利用して 依存を設定する
  216. アプリケーションサービス | DI 216 こんな感じ

  217. アプリケーションサービス | セパレートインターフェース 217 ところでこんな風に interface を 用意する場合もあります

  218. アプリケーションサービス | セパレートインターフェース 218 ところでこんな風に interface を 用意する場合もあります セパレートインターフェース と言われます

  219. アプリケーションサービス | セパレートインターフェース 219 ところでこんな風に interface を 用意する場合もあります

  220. アプリケーションサービス | セパレートインターフェース 220 ところでこんな風に interface を 用意する場合もあります

  221. アプリケーションサービス | セパレートインターフェース 221 なんのために?

  222. アプリケーションサービス | セパレートインターフェース 222 例えば例外が発生したときの動作を チェックしたい

  223. アプリケーションサービス | セパレートインターフェース 223 例えば例外が発生したときの動作を チェックしたい インメモリのリポジトリでも 例外を起こすような 整合性のあるデータを 用意するのは大変・・・

  224. アプリケーションサービス | セパレートインターフェース 224 セパレートインターフェースにしておけば

  225. アプリケーションサービス | セパレートインターフェース 225 データを準備しなくても 例外を投げるオブジェクトに差し替えれる セパレートインターフェースにしておけば

  226. 後半へ続く To be continued on the latter half