Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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

nrs
October 28, 2018

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

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

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

nrs

October 28, 2018
Tweet

More Decks by nrs

Other Decks in Programming

Transcript

  1. Masanobu Naruse
    BOTTOM UP DOMAIN DRIVEN DESIGN
    The later part

    View full-size slide

  2. もくじ
    • はじめに
    • 値オブジェクト
    • エンティティ
    • ドメインサービス
    • リポジトリ
    • アプリケーションサービス
    • ファクトリ
    • トランザクション
    • 集約
    • アーキテクチャ
    • ドメイン駆動設計への誘い
    2

    View full-size slide

  3. 閑話休題 3
    アプリケーションが
    作れるようになりました
    ここから後半です

    View full-size slide

  4. ファクトリ
    FACTORY

    View full-size slide

  5. ファクトリ | 採番 5
    サンプルの採番

    View full-size slide

  6. ファクトリ | 採番 6
    独自の採番システムを使いたい

    View full-size slide

  7. ファクトリ | 採番 7
    例えば採番テーブル

    View full-size slide

  8. ファクトリ | 採番 8

    View full-size slide

  9. ファクトリ | 採番 9
    テストできない!

    View full-size slide

  10. ファクトリ | 採番 10
    ユーザがユーザの作り方を
    知っているのはおかしい
    ユーザの知識と
    ユーザを作る知識は別物

    View full-size slide

  11. ファクトリ | 採番 11
    そこで
    ファクトリ

    View full-size slide

  12. ファクトリ | 採番 12

    View full-size slide

  13. ファクトリ | 採番 13
    採番処理

    View full-size slide

  14. ファクトリ | 採番 14
    オブジェクトの構築

    View full-size slide

  15. ファクトリ | 採番 15

    View full-size slide

  16. ファクトリ | 採番 16
    生成処理をカプセル化

    View full-size slide

  17. ファクトリ | 採番 17
    テストも勿論できます

    View full-size slide

  18. ファクトリ | 採番 18
    テストも勿論できます
    メモリ上の値を利用

    View full-size slide

  19. ファクトリ | リポジトリによる採番 19
    リポジトリに
    採番処理を持たせるパターンも
    よく見ます

    View full-size slide

  20. ファクトリ | リポジトリによる採番 20

    View full-size slide

  21. ファクトリ | リポジトリによる採番 21

    View full-size slide

  22. ファクトリ | リポジトリによる採番 22
    シンプル

    View full-size slide

  23. ファクトリ | リポジトリによる採番 23
    反面、採番処理とデータ永続化の技術が
    異なると若干違和感を感じるかも

    View full-size slide

  24. ファクトリ | リポジトリによる採番 24
    反面、採番処理とデータ永続化の技術が
    異なると若干違和感を感じるかも
    APIで採番

    View full-size slide

  25. ファクトリ | リポジトリによる採番 25
    反面、採番処理とデータ永続化の技術が
    異なると若干違和感を感じるかも
    APIで採番 RDBで永続化

    View full-size slide

  26. ファクトリ | 自動採番 26
    ところで
    DB の AutoIncrement 機能
    って便利ですよね

    View full-size slide

  27. ファクトリ | 自動採番 27

    View full-size slide

  28. ファクトリ | 自動採番 28

    View full-size slide

  29. ファクトリ | 自動採番 29

    View full-size slide

  30. ファクトリ | 自動採番 30
    ここで
    SetUserId される

    View full-size slide

  31. ファクトリ | 自動採番 31
    ここで
    SetUserId される
    不安定な状態のエンティティを存在させることになるけど
    統一してあれば大丈夫・・・だと思う

    View full-size slide

  32. トランザクション
    TRANSACTION

    View full-size slide

  33. トランザクション 33
    いわゆる一般的な
    トランザクションの話

    View full-size slide

  34. トランザクション 34
    実はいままでのサンプルコードは
    致命的な不具合があります

    View full-size slide

  35. トランザクション 35

    View full-size slide

  36. トランザクション 36
    ユーザ A

    View full-size slide

  37. トランザクション 37
    User Name: nrs
    で登録
    ユーザ A

    View full-size slide

  38. トランザクション 38
    User Name: nrs
    で登録
    ユーザ A

    View full-size slide

  39. トランザクション 39
    User Name: nrs
    で登録
    ユーザ A ユーザ B

    View full-size slide

  40. トランザクション 40
    User Name: nrs
    で登録
    User Name: nrs
    で登録
    ユーザ A ユーザ B

    View full-size slide

  41. トランザクション 41
    User Name: nrs
    で登録
    User Name: nrs
    で登録
    ユーザ A ユーザ B

    View full-size slide

  42. トランザクション 42
    User Name: nrs
    で登録
    User Name: nrs
    で登録
    ユーザ A ユーザ B
    User Name: nrs のデータが
    二つ出来てしまう

    View full-size slide

  43. トランザクション | ユニークキー 43
    重複してはいけない
    ならば
    UserName カラムに
    ユニークキー制約をつけよう

    View full-size slide

  44. トランザクション | ユニークキー 44

    View full-size slide

  45. トランザクション | ユニークキー 45
    ユニークキーを付けたなら

    View full-size slide

  46. トランザクション | ユニークキー 46
    ユニークキーを付けたなら
    重複確認もいらないのでは?

    View full-size slide

  47. トランザクション | ユニークキー 47

    View full-size slide

  48. トランザクション | ユニークキー 48
    わかりやすい

    View full-size slide

  49. トランザクション | ユニークキー 49
    わかりやすい
    何もわからないコード

    View full-size slide

  50. トランザクション | ユニークキー 50
    わかりやすい
    何もわからないコード
    重複を許さないという情報は重要なファクター

    View full-size slide

  51. トランザクション | トランザクションスコープ 51
    整合性が必要な処理を表す方法
    トランザクションスコープ

    View full-size slide

  52. トランザクション | トランザクションスコープ 52

    View full-size slide

  53. トランザクション | トランザクションスコープ 53

    View full-size slide

  54. トランザクション | トランザクションスコープ 54
    このスコープは整合性が求められる処理と主張している

    View full-size slide

  55. トランザクション | トランザクションスコープ 55
    C# じゃないしなぁ・・・
    と思った方

    View full-size slide

  56. トランザクション | トランザクションスコープ 56
    例えば Spring フレームワーク

    View full-size slide

  57. トランザクション | トランザクションスコープ 57
    例えば Spring フレームワーク

    View full-size slide

  58. トランザクション | トランザクションスコープ 58
    例えば Spring フレームワーク

    View full-size slide

  59. トランザクション | トランザクションスコープ 59
    例えば Spring フレームワーク
    このメソッドは整合性が求めると主張している

    View full-size slide

  60. トランザクション | トランザクションスコープ 60
    言語にもフレームワークにも
    そんな機能ないしなぁ
    と思った方

    View full-size slide

  61. トランザクション | トランザクションスコープ 61
    作ろう
    ※こんな感じのものがあればいけるかな・・・の例です

    View full-size slide

  62. トランザクション | ユニットオブワーク 62
    そこまで大げさな仕組みが嫌なら
    ユニットオブワーク

    View full-size slide

  63. トランザクション | ユニットオブワーク 63
    インターフェースを用意

    View full-size slide

  64. トランザクション | ユニットオブワーク 64
    こんな感じで実装

    View full-size slide

  65. トランザクション | ユニットオブワーク 65

    View full-size slide

  66. トランザクション | ユニットオブワーク 66

    View full-size slide

  67. トランザクション | ユニットオブワーク 67

    View full-size slide

  68. トランザクション | ユニットオブワーク 68
    リポジトリは Connection を受け取る

    View full-size slide

  69. トランザクション | ユニットオブワーク 69

    View full-size slide

  70. トランザクション | ユニットオブワーク 70

    View full-size slide

  71. トランザクション | ユニットオブワーク 71

    View full-size slide

  72. トランザクション | ユニットオブワーク 72
    DBConnection を利用するところを
    UnitOfWork に切り替えるだけなので導入しやすい

    View full-size slide

  73. トランザクション | ユニットオブワーク 73
    デメリット
    リポジトリ増加のたびに
    ユニットオブワークに修正が入る

    View full-size slide

  74. トランザクション | ユニットオブワーク 74

    View full-size slide

  75. トランザクション | ユニットオブワーク 75

    View full-size slide

  76. トランザクション | ユニットオブワーク 76

    View full-size slide

  77. トランザクション | ユニットオブワーク 77

    View full-size slide

  78. トランザクション | ユニットオブワーク 78
    リポジトリを抽象化しちゃえば?

    View full-size slide

  79. トランザクション | ユニットオブワーク 79

    View full-size slide

  80. トランザクション | ユニットオブワーク 80
    特定エンティティの
    リポジトリ取得

    View full-size slide

  81. トランザクション | ユニットオブワーク 81
    例えばサークルの所属ユーザ情報を取得すると
    特定エンティティの
    リポジトリ取得

    View full-size slide

  82. トランザクション | ユニットオブワーク 82
    例えばサークルの所属ユーザ情報を取得すると
    特定エンティティの
    リポジトリ取得

    View full-size slide

  83. トランザクション | ユニットオブワーク 83
    例えばサークルの所属ユーザ情報を取得すると
    特定エンティティの
    リポジトリ取得

    View full-size slide

  84. トランザクション | ユニットオブワーク 84
    例えばサークルの所属ユーザ情報を取得すると
    SELECT * FROM t_user WHERE t_user.id = ‘userId’
    を何度も実行する
    特定エンティティの
    リポジトリ取得

    View full-size slide

  85. トランザクション | ユニットオブワーク 85
    例えばサークルの所属ユーザ情報を取得すると
    SELECT * FROM t_user WHERE t_user.id = ‘userId’
    を何度も実行する
    特定エンティティの
    リポジトリ取得

    View full-size slide

  86. トランザクション | ユニットオブワーク 86
    例えばサークルの所属ユーザ情報を取得すると
    SELECT * FROM t_user WHERE t_user.id = ‘userId’
    を何度も実行する
    特定エンティティの
    リポジトリ取得
    最適化した処理が
    利用できない

    View full-size slide

  87. トランザクション | ユニットオブワーク 87
    ユニットオブワークに
    既視感がある方

    View full-size slide

  88. トランザクション | ユニットオブワーク 88
    ユニットオブワークに
    既視感がある方
    Entity Framework は
    ユニットオブワークの実装です
    ※最適化できない問題は遅延実行による SQL 生成(IQueryable)で解決

    View full-size slide

  89. 集約
    AGGREGATE

    View full-size slide

  90. 集約 90
    集約を学ぶために
    エクササイズ

    View full-size slide

  91. 集約 | エクササイズ 91
    お題はサークル機能

    View full-size slide

  92. 集約 | エクササイズ 92
    お題はサークル機能

    View full-size slide

  93. 集約 | エクササイズ 93
    サークルを作る処理
    注目すべきは

    View full-size slide

  94. 集約 | エクササイズ 94
    サークルを作る処理
    注目すべきは
    getter

    View full-size slide

  95. 集約 | エクササイズ 95

    View full-size slide

  96. 集約 | エクササイズ 96
    メソッドを用意し
    getter を使わないようにした

    View full-size slide

  97. 集約 | エクササイズ 97

    View full-size slide

  98. 集約 | エクササイズ 98

    View full-size slide

  99. 集約 | エクササイズ 99
    getter が消え
    ユーザがサークルを作っている

    View full-size slide

  100. 集約 | エクササイズ 100
    次はこっち

    View full-size slide

  101. 集約 | エクササイズ 101

    View full-size slide

  102. 集約 | エクササイズ 102
    getter

    View full-size slide

  103. 集約 | エクササイズ 103
    最大人数 30 人

    View full-size slide

  104. 集約 | エクササイズ 104
    最大人数 30 人
    このロジックは
    ここ以外にも記述しそう

    View full-size slide

  105. 集約 | エクササイズ 105
    最大人数 30 人
    このロジックは
    ここ以外にも記述しそう
    最大人数を 50 人に
    変更することになったら?

    View full-size slide

  106. 集約 | エクササイズ 106
    最大人数 30 人
    このロジックは
    ここ以外にも記述しそう
    最大人数を 50 人に
    変更することになったら?
    愚直に修正する羽目に

    View full-size slide

  107. 集約 | エクササイズ 107

    View full-size slide

  108. 集約 | エクササイズ 108
    ドメインモデル貧血症

    View full-size slide

  109. 集約 109
    健全なドメインモデルにするために
    集約を学ぶ

    View full-size slide

  110. 集約 110
    集約

    集約ルート

    View full-size slide

  111. 集約 112
    id: CircleId
    users: List
    name: string
    Circle
    users: List
    users: List

    View full-size slide

  112. 集約 113
    User 集約
    id: CircleId
    users: List
    name: string
    Circle
    users: List
    users: List

    View full-size slide

  113. 集約 114
    Circle 集約
    id: CircleId
    users: List
    name: string
    Circle
    users: List
    users: List

    View full-size slide

  114. 集約 115
    Circle 集約の集約ルート
    id: CircleId
    users: List
    name: string
    Circle
    users: List
    users: List

    View full-size slide

  115. 集約 116
    集約は必ず集約ルート越しに触る
    集約の内部のオブジェクトを直接触らない

    View full-size slide

  116. 集約 117
    つまり

    View full-size slide

  117. 集約 118
    アプリケーションサービスは
    集約ルートを
    直接のインターフェースにします

    View full-size slide

  118. 集約 121
    サークル越しにユーザエンティティを触ってる

    View full-size slide

  119. 集約 122
    サークル越しにユーザエンティティを触ってる
    サークルが直接のインターフェースであるべき

    View full-size slide

  120. 集約 125
    最大人数を 50 人に変更したい

    View full-size slide

  121. 集約 126
    最大人数を 50 人に変更したい
    修正はここだけで
    OK

    View full-size slide

  122. 集約 127
    実は
    オブジェクト指向では
    当たり前の発想

    View full-size slide

  123. 集約 128
    デメテルの法則

    View full-size slide

  124. 集約 129
    デメテルの法則

    View full-size slide

  125. 集約 130
    デメテルの法則

    View full-size slide

  126. 集約 | 整合性の境界 131
    集約ってどれぐらいの粒度で作るの?

    View full-size slide

  127. 集約 | 整合性の境界 132
    集約ってどれぐらいの粒度で作るの?
    変更の単位

    View full-size slide

  128. 集約 | 整合性の境界 133
    これまでの集約の概念図

    View full-size slide

  129. 集約 | 整合性の境界 134
    これまでの集約の概念図
    もし Circle 集約で User を変更したら?
    User 集約は Circle 集約に属してない

    View full-size slide

  130. 集約 | 整合性の境界 135
    これまでの集約の概念図
    User 集約は Circle 集約に属してない

    View full-size slide

  131. 集約 | 整合性の境界 136
    ロジックはぎりぎり納得できる

    View full-size slide

  132. 集約 | 整合性の境界 137

    View full-size slide

  133. 集約 | 整合性の境界 138
    Circle のリポジトリなのに User の処理が多い・・・

    View full-size slide

  134. 集約 | 整合性の境界 139
    Circle が Circle 以外の変更は
    担保しない場合

    View full-size slide

  135. 集約 | 整合性の境界 140
    リポジトリは Circle に集中

    View full-size slide

  136. 集約 | 整合性の境界 141
    整合性の境界・変更の単位として集約を設計する

    View full-size slide

  137. 集約 | 整合性の境界 142
    整合性の境界・変更の単位として集約を設計する
    リポジトリは集約毎に作成することになる

    View full-size slide

  138. 集約 | 問題点 143
    問題点

    View full-size slide

  139. 集約 | 問題点 144
    変更できちゃう
    問題点

    View full-size slide

  140. 集約 | 識別子による防衛 145
    そもそもの問題は変更できてしまうこと

    View full-size slide

  141. 集約 | 識別子による防衛 146
    変更できないようにする
    そもそもの問題は変更できてしまうこと

    View full-size slide

  142. 集約 | 識別子による防衛 147
    変更できないようにする
    そもそもの問題は変更できてしまうこと

    View full-size slide

  143. 集約 | 識別子による防衛 148
    識別子にしてしまえば変更できない
    変更できないようにする
    そもそもの問題は変更できてしまうこと

    View full-size slide

  144. 集約 | 識別子による防衛 149
    識別子にしてしまえば変更できない
    変更できないようにする
    そもそもの問題は変更できてしまうこと

    View full-size slide

  145. 集約 | 非公開による防衛 150
    変更をさせない仕組みとしてもう一つ

    View full-size slide

  146. 集約 | 非公開による防衛 151
    そもそも getter だから悪い

    View full-size slide

  147. 集約 | 非公開による防衛 152
    そもそも getter だから悪い

    View full-size slide

  148. 集約 | 非公開による防衛 153
    getter をなくすと

    View full-size slide

  149. 集約 | 非公開による防衛 154
    リポジトリが問題になる

    View full-size slide

  150. 集約 | 非公開による防衛 155
    C# の場合は諦めるか Notification パターンで

    View full-size slide

  151. 集約 | 非公開による防衛 156
    Scala 最強説

    View full-size slide

  152. 集約 | 非公開による防衛 157
    Scala 最強説
    ICircleRepository からはアクセスできる
    他からはアクセスできない

    View full-size slide

  153. ディレクトリ構成例 159
    ディレクトリ構成のイメージ
    明日から採用したい人のために

    View full-size slide

  154. ディレクトリ構成例 160
    Domain Application UserApplicationService
    Model
    CircleApplicationService
    User
    Users
    Circles
    Infrastructure
    UserId
    UserName
    IUserRepository
    ICircleRepository
    CircleRepository
    Presentation(MVC)
    Circle
    CircleId
    UserRepository
    InMemory
    InMemoryCircleRepository
    InMemoryUserRepository
    : package : folder : object

    View full-size slide

  155. アーキテクチャ
    ARCHITECTURE

    View full-size slide

  156. アーキテクチャ 162
    ドメイン駆動設計と
    同時に語られることの多い
    アーキテクチャについて

    View full-size slide

  157. アーキテクチャ 163
    レイヤードアーキテクチャ
    ヘキサゴナルアーキテクチャ
    オニオンアーキテクチャ
    クリーンアーキテクチャ

    View full-size slide

  158. アーキテクチャ | レイヤードアーキテクチャ 164
    レイヤードアーキテクチャ
    ヘキサゴナルアーキテクチャ
    オニオンアーキテクチャ
    クリーンアーキテクチャ

    View full-size slide

  159. アーキテクチャ | レイヤードアーキテクチャ 165
    レイヤードアーキテクチャ
    Presentation
    Application
    Domain
    Infrastructure
    UserApplicationService
    User
    UserRepository
    UserController

    View full-size slide

  160. アーキテクチャ | レイヤードアーキテクチャ 166
    レイヤードアーキテクチャ
    Presentation
    Application
    Domain
    Infrastructure
    UserApplicationService
    User
    UserRepository
    UserController
    依存の方向は下方向

    View full-size slide

  161. アーキテクチャ | ヘキサゴナルアーキテクチャ 167
    レイヤードアーキテクチャ
    ヘキサゴナルアーキテクチャ
    オニオンアーキテクチャ
    クリーンアーキテクチャ

    View full-size slide

  162. アーキテクチャ | ヘキサゴナルアーキテクチャ 168
    ヘキサゴナルアーキテクチャ

    View full-size slide

  163. アーキテクチャ | ヘキサゴナルアーキテクチャ 169
    ヘキサゴナルアーキテクチャ
    UserController
    (Adapter)
    User
    UserApplicationService
    UserRepository

    View full-size slide

  164. UserController
    (Adapter)
    User
    UserApplicationService
    UserRepository
    アーキテクチャ | ヘキサゴナルアーキテクチャ 170
    ヘキサゴナルアーキテクチャ
    ビジネスロジックが中心で依存は内向き

    View full-size slide

  165. アーキテクチャ | オニオンアーキテクチャ 171
    レイヤードアーキテクチャ
    ヘキサゴナルアーキテクチャ
    オニオンアーキテクチャ
    クリーンアーキテクチャ

    View full-size slide

  166. アーキテクチャ | オニオンアーキテクチャ 172
    オニオンアーキテクチャ
    Application Services
    Domain Services
    Domain Model
    UI
    Tests Infrastructure

    View full-size slide

  167. アーキテクチャ | オニオンアーキテクチャ 173
    オニオンアーキテクチャ
    Application Services
    Domain Services
    Domain Model
    UI
    Tests Infrastructure
    User
    UserApplicationService
    UserService ドメイン駆動設計?

    View full-size slide

  168. アーキテクチャ | オニオンアーキテクチャ 174
    オニオンアーキテクチャ
    Application Services
    Domain Services
    Domain Model
    UI
    Tests Infrastructure
    User
    UserApplicationService
    UserService
    ヘキサゴナルアーキテクチャの内側
    ドメイン駆動設計?

    View full-size slide

  169. アーキテクチャ | クリーンアーキテクチャ 175
    レイヤードアーキテクチャ
    ヘキサゴナルアーキテクチャ
    オニオンアーキテクチャ
    クリーンアーキテクチャ

    View full-size slide

  170. アーキテクチャ | クリーンアーキテクチャ 176
    クリーンアーキテクチャ

    View full-size slide

  171. アーキテクチャ | クリーンアーキテクチャ 177
    クリーンアーキテクチャ
    Controllers: UserController
    GateWays: IUserRepository
    UserRepository
    UseCases: IUserApplicationService(InputPort)
    UserApplicationService(Interactor)
    Entities: User

    View full-size slide

  172. アーキテクチャ | クリーンアーキテクチャ 178
    クリーンアーキテクチャ
    ヘキサゴナルアーキテクチャの外側
    Controllers: UserController
    GateWays: IUserRepository
    UserRepository
    UseCases: IUserApplicationService(InputPort)
    UserApplicationService(Interactor)
    Entities: User

    View full-size slide

  173. アーキテクチャ | クリーンアーキテクチャ 179
    クリーンアーキテクチャ
    ヘキサゴナルアーキテクチャの外側
    Controllers: UserController
    GateWays: IUserRepository
    UserRepository
    UseCases: IUserApplicationService(InputPort)
    UserApplicationService(Interactor)
    Entities: User
    ※詳しい話はこちらで
    https://nrslib.com/clean-architecture/
    https://qiita.com/nrslib/items/a5f902c4defc83bd46b8

    View full-size slide

  174. アーキテクチャ | まとめ 180

    View full-size slide

  175. アーキテクチャ | まとめ 181

    View full-size slide

  176. アーキテクチャ | まとめ 182

    View full-size slide

  177. アーキテクチャ | まとめ 183

    View full-size slide

  178. アーキテクチャ | まとめ 184
    レイヤードがあり
    ヘキサゴナルへ変遷
    その実装イメージとして
    ヘキサゴナルの内側がオニオン
    ヘキサゴナルの外側がクリーン
    いずれも依存関係を整理し
    ドメインロジックの防衛を目指している

    View full-size slide

  179. ドメイン
    DOMAIN

    View full-size slide

  180. ドメイン 186
    ドメインとは

    View full-size slide

  181. ドメイン駆動設計への誘い 188
    以上で終了です

    View full-size slide

  182. ドメイン駆動設計への誘い 189
    今回の内容を知らなかった方は
    これらのパターンを実践するだけでも
    よりよいコードを書くことが
    できるでしょう

    View full-size slide

  183. ドメイン駆動設計への誘い 190
    ただパターンを模倣し
    形だけを真似たものは
    軽量 DDD と呼ばれるものです

    View full-size slide

  184. ドメイン駆動設計への誘い 191
    真のドメイン駆動設計とは異なります

    View full-size slide

  185. ドメイン駆動設計への誘い 192
    ではどうすれば
    真のドメイン駆動設計に
    たどり着けるのか

    View full-size slide

  186. ドメイン駆動設計への誘い 193
    最初の方のスライドを見てみましょう

    View full-size slide

  187. ドメイン駆動設計への誘い 194
    マインド パターン
    感じるしかない 実装できる
    用語

    View full-size slide

  188. ドメイン駆動設計への誘い 195
    パターン
    感じるしかない 実装できる
    用語
    マインド

    View full-size slide

  189. ドメイン駆動設計への誘い 196
    マインドは原典で

    View full-size slide

  190. WELCOME TO DDD WORLD

    View full-size slide

  191. おわり 198
    • はじめに
    • 値オブジェクト
    • エンティティ
    • ドメインサービス
    • リポジトリ
    • アプリケーションサービス
    • ファクトリ
    • トランザクション
    • 集約
    • アーキテクチャ
    • ドメイン駆動設計への誘い @nrslib
    https://nrslib.com

    View full-size slide