Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

ボトムアップドメイン駆動設計 後編

4,364 views

Published on

# URL
前編: https://www.slideshare.net/MasanobuNaruse/bottomup-ddd-1
解説記事: https://nrslib.com/bottomup-ddd/
勉強会情報: https://ddd-community-jp.connpass.com/event/103428/

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

Published in: Technology
  • Be the first to comment

ボトムアップドメイン駆動設計 後編

  1. 1. ボトムアップ ドメイン駆動設計 後編 成瀬 允宣2018/10/23 in GMO Yours 1
  2. 2. 自己紹介 • 成瀬 允宣 - Masanobu Naruse • プログラマ • C#, Scala, Typescript • DDD とかアーキテクチャの話が好きです • @nrslib • https://nrslib.com 2
  3. 3. もくじ • はじめに • 値オブジェクト • エンティティ • ドメインサービス • リポジトリ • アプリケーションサービス • ファクトリ • トランザクション • 集約 • アーキテクチャ • ドメイン駆動設計への誘い 3
  4. 4. 閑話休題 4 アプリケーションが 作れるようになりました ここから後半です
  5. 5. ファクトリ 5 後半最初のテーマは ファクトリ
  6. 6. ファクトリ | 採番 6 サンプルの採番
  7. 7. ファクトリ | 採番 7 独自の採番システムを使いたい
  8. 8. ファクトリ | 採番 8 例えば採番テーブル
  9. 9. ファクトリ | 採番 9
  10. 10. ファクトリ | 採番 10 テストできない!
  11. 11. ファクトリ | 採番 11 ユーザがユーザの作り方を 知っているのはおかしい ユーザの知識と ユーザを作る知識は別物
  12. 12. ファクトリ | 採番 12 そこで ファクトリ
  13. 13. ファクトリ | 採番 13 ファクトリ
  14. 14. ファクトリ | 採番 14
  15. 15. ファクトリ | 採番 15 生成処理をカプセル化
  16. 16. ファクトリ | 採番 16 テストも勿論できます
  17. 17. ファクトリ | リポジトリによる採番 17 リポジトリに 採番処理を持たせるパターンも よく見ます
  18. 18. ファクトリ | リポジトリによる採番 18
  19. 19. ファクトリ | リポジトリによる採番 19
  20. 20. ファクトリ | リポジトリによる採番 20 シンプル
  21. 21. ファクトリ | リポジトリによる採番 21 反面、採番処理とデータ永続化の技術が 異なると若干違和感を感じるかも
  22. 22. ファクトリ | 自動採番 22 ところで DB の AutoIncrement 機能 って便利ですよね
  23. 23. ファクトリ | 自動採番 23
  24. 24. ファクトリ | 自動採番 24
  25. 25. ファクトリ | 自動採番 25 ここで SetUserId される
  26. 26. ファクトリ | 自動採番 26 ここで SetUserId される 不安定な状態のエンティティを存在させることになるけど 統一してあれば大丈夫・・・だと思う
  27. 27. トランザクション 27 パターンじゃありませんが トランザクション の話をします
  28. 28. トランザクション 28 実はいままでのサンプルコードは 致命的な不具合があります
  29. 29. トランザクション 29
  30. 30. トランザクション 30 ユーザ A
  31. 31. トランザクション 31 User Name: nrs で登録 ユーザ A
  32. 32. トランザクション 32 User Name: nrs で登録 ユーザ A
  33. 33. トランザクション 33 User Name: nrs で登録 ユーザ A ユーザ B
  34. 34. トランザクション 34 User Name: nrs で登録 User Name: nrs で登録 ユーザ A ユーザ B
  35. 35. トランザクション 35 User Name: nrs で登録 User Name: nrs で登録 ユーザ A ユーザ B
  36. 36. トランザクション 36 User Name: nrs で登録 User Name: nrs で登録 ユーザ A ユーザ B User Name: nrs のデータが 二つ出来てしまう
  37. 37. トランザクション | ユニークキー 37 重複してはいけない ならば UserName カラムに ユニークキー制約をつけよう
  38. 38. トランザクション | ユニークキー 38
  39. 39. トランザクション | ユニークキー 39 ユニークキーを付けたなら
  40. 40. トランザクション | ユニークキー 40 ユニークキーを付けたなら 重複確認もいらないのでは?
  41. 41. トランザクション | ユニークキー 41
  42. 42. トランザクション | ユニークキー 42 わかりやすい
  43. 43. トランザクション | ユニークキー 43 わかりやすい 何もわからないコード
  44. 44. トランザクション | ユニークキー 44 わかりやすい 何もわからないコード 重複を許さないという情報は重要なファクター
  45. 45. トランザクション | トランザクションスコープ 45 整合性が必要な処理を表す方法 トランザクションスコープ
  46. 46. トランザクション | トランザクションスコープ 46
  47. 47. トランザクション | トランザクションスコープ 47
  48. 48. トランザクション | トランザクションスコープ 48 このスコープは整合性が求められる処理と主張している
  49. 49. トランザクション | トランザクションスコープ 49 C# じゃないしなぁ・・・ と思った方
  50. 50. トランザクション | トランザクションスコープ 50 例えば Spring フレームワーク
  51. 51. トランザクション | トランザクションスコープ 51 例えば Spring フレームワーク
  52. 52. トランザクション | トランザクションスコープ 52 例えば Spring フレームワーク
  53. 53. トランザクション | トランザクションスコープ 53 例えば Spring フレームワーク このメソッドは整合性が求めると主張している
  54. 54. トランザクション | トランザクションスコープ 54 言語にもフレームワークにも そんな機能ないしなぁ と思った方
  55. 55. トランザクション | トランザクションスコープ 55 作ろう ※こんな感じのものがあればいけるかな・・・の例です
  56. 56. トランザクション | ユニットオブワーク 56 そこまで大げさな仕組みが嫌なら ユニットオブワーク
  57. 57. トランザクション | ユニットオブワーク 57 インターフェースを用意
  58. 58. トランザクション | ユニットオブワーク 58 こんな感じで実装
  59. 59. トランザクション | ユニットオブワーク 59 リポジトリは Connection を受け取る
  60. 60. トランザクション | ユニットオブワーク 60
  61. 61. トランザクション | ユニットオブワーク 61
  62. 62. トランザクション | ユニットオブワーク 62
  63. 63. トランザクション | ユニットオブワーク 63 DBConnection を利用するところを UnitOfWork に切り替えるだけなので導入しやすい
  64. 64. トランザクション | ユニットオブワーク 64 デメリット リポジトリ増加のたびに ユニットオブワークに修正が入る
  65. 65. トランザクション | ユニットオブワーク 65
  66. 66. トランザクション | ユニットオブワーク 66
  67. 67. トランザクション | ユニットオブワーク 67
  68. 68. トランザクション | ユニットオブワーク 68
  69. 69. トランザクション | ユニットオブワーク 69 リポジトリを抽象化しちゃえば?
  70. 70. トランザクション | ユニットオブワーク 70
  71. 71. トランザクション | ユニットオブワーク 71 特定エンティティの リポジトリ取得
  72. 72. トランザクション | ユニットオブワーク 72 例えばサークルの所属ユーザ情報を取得すると 特定エンティティの リポジトリ取得
  73. 73. トランザクション | ユニットオブワーク 73 例えばサークルの所属ユーザ情報を取得すると 特定エンティティの リポジトリ取得
  74. 74. トランザクション | ユニットオブワーク 74 例えばサークルの所属ユーザ情報を取得すると 特定エンティティの リポジトリ取得
  75. 75. トランザクション | ユニットオブワーク 75 例えばサークルの所属ユーザ情報を取得すると SELECT * FROM t_user WHERE t_user.id = ‘userId’ を何度も実行する 特定エンティティの リポジトリ取得
  76. 76. トランザクション | ユニットオブワーク 76 例えばサークルの所属ユーザ情報を取得すると SELECT * FROM t_user WHERE t_user.id = ‘userId’ を何度も実行する 特定エンティティの リポジトリ取得
  77. 77. トランザクション | ユニットオブワーク 77 例えばサークルの所属ユーザ情報を取得すると SELECT * FROM t_user WHERE t_user.id = ‘userId’ を何度も実行する 特定エンティティの リポジトリ取得 最適化した処理が 利用できない
  78. 78. トランザクション | ユニットオブワーク 78 ユニットオブワークに 既視感がある方
  79. 79. トランザクション | ユニットオブワーク 79 ユニットオブワークに 既視感がある方 Entity Framework は ユニットオブワークの実装です ※最適化できない問題は IQueryable で解決
  80. 80. 集約 80 集約
  81. 81. 集約 81 集約を学ぶために エクササイズ
  82. 82. 集約 | エクササイズ 82 お題はサークル機能
  83. 83. 集約 | エクササイズ 83 お題はサークル機能
  84. 84. 集約 | エクササイズ 84 サークルを作る処理 注目すべきは
  85. 85. 集約 | エクササイズ 85 サークルを作る処理 注目すべきは getter
  86. 86. 集約 | エクササイズ 86
  87. 87. 集約 | エクササイズ 87
  88. 88. 集約 | エクササイズ 88
  89. 89. 集約 | エクササイズ 89 たったこれだけのこと
  90. 90. 集約 | エクササイズ 90 たったこれだけのこと だけど getter は消え ユーザがサークルを作っている
  91. 91. 集約 | エクササイズ 91 次はこっち
  92. 92. 集約 | エクササイズ 92
  93. 93. 集約 | エクササイズ 93 getter
  94. 94. 集約 | エクササイズ 94 最大人数 30 人
  95. 95. 集約 | エクササイズ 95 最大人数 30 人 このロジックは ここ以外にも記述しそう
  96. 96. 集約 | エクササイズ 96 最大人数 30 人 このロジックは ここ以外にも記述しそう 最大人数を 50 人に 変更することになったら?
  97. 97. 集約 | エクササイズ 97 最大人数 30 人 このロジックは ここ以外にも記述しそう 最大人数を 50 人に 変更することになったら? 愚直に修正する羽目に
  98. 98. 集約 | エクササイズ 98
  99. 99. 集約 | エクササイズ 99 ドメインモデル貧血症
  100. 100. 集約 100 健全なドメインモデルにするために 集約を学ぶ
  101. 101. 集約 101 集約は英語で
  102. 102. 集約 102 集約は英語で Aggregate Root
  103. 103. 集約 103 集約は英語で Aggregate Root 集める 根本
  104. 104. 集約 104 集約は英語で Aggregate Root 集める 根本 アプリケーションサービスは 集約ルートを 直接のインターフェースにします
  105. 105. 集約 105
  106. 106. 集約 106
  107. 107. 集約 107 サークル越しにユーザエンティティを触ってる
  108. 108. 集約 108 サークル越しにユーザエンティティを触ってる サークルが直接のインターフェースであるべき
  109. 109. 集約 109
  110. 110. 集約 110
  111. 111. 集約 111 最大人数を 50 人に変更したい
  112. 112. 集約 112 最大人数を 50 人に変更したい 修正はここだけで OK
  113. 113. 集約 113 実は オブジェクト指向では 当たり前の発想
  114. 114. 集約 114 デメテルの法則
  115. 115. 集約 115 デメテルの法則
  116. 116. 集約 116 デメテルの法則
  117. 117. 集約 | 整合性の境界 117 集約ってどれぐらいの粒度で作るの?
  118. 118. 集約 | 整合性の境界 118 集約ってどれぐらいの粒度で作るの? 変更の単位
  119. 119. 集約 | 整合性の境界 119 これまでの集約の概念図
  120. 120. 集約 | 整合性の境界 120 これまでの集約の概念図 User 集約は Circle 集約に属してない
  121. 121. 集約 | 整合性の境界 121 これまでの集約の概念図 もし Circle 集約で User を変更したら? User 集約は Circle 集約に属してない
  122. 122. 集約 | 整合性の境界 122 ロジックはぎりぎり納得できる
  123. 123. 集約 | 整合性の境界 123
  124. 124. 集約 | 整合性の境界 124 Circle のリポジトリなのに User の処理が多い・・・
  125. 125. 集約 | 整合性の境界 125 Circle が Circle 以外の変更は 担保しない場合
  126. 126. 集約 | 整合性の境界 126 リポジトリは Circle に集中
  127. 127. 集約 | 整合性の境界 127 整合性の境界・変更の単位として集約を設計する
  128. 128. 集約 | 整合性の境界 128 整合性の境界・変更の単位として集約を設計する リポジトリは集約毎に作成することになる
  129. 129. 集約 | 問題点 129 問題点
  130. 130. 集約 | 問題点 130 変更できちゃう 問題点
  131. 131. 集約 | 識別子による防衛 131 そもそもの問題は変更できてしまうこと
  132. 132. 集約 | 識別子による防衛 132 変更できてしまう 変更できないようにする
  133. 133. 集約 | 識別子による防衛 133 変更できてしまう 変更できないようにする
  134. 134. 集約 | 識別子による防衛 134 識別子にしてしまえば変更できない 変更できてしまう 変更できないようにする
  135. 135. 集約 | 非公開による防衛 135 変更をさせない仕組みとしてもう一つ
  136. 136. 集約 | 非公開による防衛 136 そもそも getter だから悪い
  137. 137. 集約 | 非公開による防衛 137 そもそも getter だから悪い
  138. 138. 集約 | 非公開による防衛 138 getter をなくすと
  139. 139. 集約 | 非公開による防衛 139 リポジトリが問題になる
  140. 140. 集約 | 非公開による防衛 140 C# の場合は諦めるか Notification パターンで
  141. 141. 集約 | 非公開による防衛 141 Scala 最強説
  142. 142. 集約 | 非公開による防衛 142 Scala 最強説 ICircleRepository からはアクセスできる 他からはアクセスできない
  143. 143. ディレクトリ構成 143 ディレクトリ構成のイメージ 明日から採用したい人のために
  144. 144. ディレクトリ構成 144 Domain Application UserApplicationService Model CircleApplicationService UserUsers Circles Infrastructure UserId UserName IUserRepository ICircleRepository CircleRepository Presentation(MVC) Circle CircleId UserRepository InMemory InMemoryCircleRepository InMemoryUserRepository : package : folder : object
  145. 145. アーキテクチャ 145 ドメイン駆動設計と 同時に語られることの多い アーキテクチャについて
  146. 146. アーキテクチャ 146 レイヤードアーキテクチャ ヘキサゴナルアーキテクチャ オニオンアーキテクチャ クリーンアーキテクチャ
  147. 147. アーキテクチャ| レイヤードアーキテクチャ 147 レイヤードアーキテクチャ ヘキサゴナルアーキテクチャ オニオンアーキテクチャ クリーンアーキテクチャ
  148. 148. アーキテクチャ| レイヤードアーキテクチャ 148 レイヤードアーキテクチャ Presentation Application Domain Infrastructure UserApplicationService User UserRepository UserController
  149. 149. アーキテクチャ | レイヤードアーキテクチャ 149 レイヤードアーキテクチャ Presentation Application Domain Infrastructure UserApplicationService User UserRepository UserController 依存の方向は下方向
  150. 150. アーキテクチャ| ヘキサゴナルアーキテクチャ 150 レイヤードアーキテクチャ ヘキサゴナルアーキテクチャ オニオンアーキテクチャ クリーンアーキテクチャ
  151. 151. アーキテクチャ | ヘキサゴナルアーキテクチャ 151 ヘキサゴナルアーキテクチャ
  152. 152. アーキテクチャ | ヘキサゴナルアーキテクチャ 152 ヘキサゴナルアーキテクチャ UserController (Adapter) User UserApplicationService UserRepository
  153. 153. UserController (Adapter) User UserApplicationService UserRepository アーキテクチャ | ヘキサゴナルアーキテクチャ 153 ヘキサゴナルアーキテクチャ ビジネスロジックが中心で依存は内向き
  154. 154. アーキテクチャ| オニオンアーキテクチャ 154 レイヤードアーキテクチャ ヘキサゴナルアーキテクチャ オニオンアーキテクチャ クリーンアーキテクチャ
  155. 155. アーキテクチャ | オニオンアーキテクチャ 155 オニオンアーキテクチャ Application Services Domain Services Domain Model UI Tests Infrastructure
  156. 156. アーキテクチャ | オニオンアーキテクチャ 156 オニオンアーキテクチャ Application Services Domain Services Domain Model UI Tests Infrastructure User UserApplicationService UserService ドメイン駆動設計?
  157. 157. アーキテクチャ | オニオンアーキテクチャ 157 オニオンアーキテクチャ Application Services Domain Services Domain Model UI Tests Infrastructure User UserApplicationService UserService ヘキサゴナルアーキテクチャの内側 ドメイン駆動設計?
  158. 158. アーキテクチャ | クリーンアーキテクチャ 158 レイヤードアーキテクチャ ヘキサゴナルアーキテクチャ オニオンアーキテクチャ クリーンアーキテクチャ
  159. 159. アーキテクチャ | クリーンアーキテクチャ 159 クリーンアーキテクチャ
  160. 160. アーキテクチャ | クリーンアーキテクチャ 160 クリーンアーキテクチャ Controllers: UserController GateWays: IUserRepository UserRepository UseCases: IUserApplicationService(InputPort) UserApplicationService(Interactor) Entities: User
  161. 161. アーキテクチャ | クリーンアーキテクチャ 161 クリーンアーキテクチャ ヘキサゴナルアーキテクチャの外側 Controllers: UserController GateWays: IUserRepository UserRepository UseCases: IUserApplicationService(InputPort) UserApplicationService(Interactor) Entities: User
  162. 162. アーキテクチャ | クリーンアーキテクチャ 162 クリーンアーキテクチャ ヘキサゴナルアーキテクチャの外側 Controllers: UserController GateWays: IUserRepository UserRepository UseCases: IUserApplicationService(InputPort) UserApplicationService(Interactor) Entities: User ※詳しい話はこちらで https://nrslib.com/clean-architecture/ https://qiita.com/nrslib/items/a5f902c4defc83bd46b8
  163. 163. アーキテクチャ | まとめ 163 レイヤードからヘキサゴナルへの発想になり ヘキサゴナルを説明するオニオンとクリーンが生まれた
  164. 164. アーキテクチャ | まとめ 164 レイヤードからヘキサゴナルへの発想になり ヘキサゴナルを説明するオニオンとクリーンが生まれた いずれも共通するのは依存関係の整理
  165. 165. アーキテクチャ | まとめ 165 レイヤードからヘキサゴナルへの発想になり ヘキサゴナルを説明するオニオンとクリーンが生まれた いずれも共通するのは依存関係の整理 外界のいざこざに ビジネスロジックが影響を受けないように
  166. 166. アーキテクチャ | まとめ 166 レイヤードからヘキサゴナルへの発想になり ヘキサゴナルを説明するオニオンとクリーンが生まれた いずれも共通するのは依存関係の整理 外界のいざこざに ビジネスロジックが影響を受けないように ビジネスロジックの変更が正しく伝搬するように
  167. 167. アーキテクチャ | まとめ 167 レイヤードからヘキサゴナルへの発想になり ヘキサゴナルを説明するオニオンとクリーンが生まれた いずれも共通するのは依存関係の整理 外界のいざこざに ビジネスロジックが影響を受けないように ビジネスロジックの変更が正しく伝搬するように ビジネスロジックの防衛を目指している
  168. 168. ドメイン駆動設計への誘い 168 以上で終了です
  169. 169. ドメイン駆動設計への誘い 169 今回の内容を知らなかった方は これらのパターンを実践するだけでも よりよいコードを書くことが できるでしょう
  170. 170. ドメイン駆動設計への誘い 170 ただパターンを模倣し 形だけを真似たものは 軽量 DDD と呼ばれるものです
  171. 171. ドメイン駆動設計への誘い 171 真のドメイン駆動設計とは異なります
  172. 172. ドメイン駆動設計への誘い 172 ではどうすれば 真のドメイン駆動設計に たどり着けるのか
  173. 173. ドメイン駆動設計への誘い 173 最初の方のスライドを見てみましょう
  174. 174. ドメイン駆動設計への誘い 174 マインド パターン 感じるしかない 実装できる 用語
  175. 175. ドメイン駆動設計への誘い 175 パターン 感じるしかない 実装できる 用語 マインド
  176. 176. ドメイン駆動設計への誘い 176 マインドは原典で
  177. 177. おわり 177 • はじめに • 値オブジェクト • エンティティ • ドメインサービス • リポジトリ • アプリケーションサービス • ファクトリ • トランザクション • 集約 • アーキテクチャ • ドメイン駆動設計への誘い @nrslib https://nrslib.com

×