Slide 1

Slide 1 text

DDDのことはじめ 2026/07/27 坂本 勇⼈

Slide 2

Slide 2 text

⾃⼰紹介 ● 名前 ● ● ● 坂本 勇⼈(Sakamoto Yuto) 所属 ● クラウド事業統括本部 ● モダンアプリコンサルティングチーム 普段のお仕事 ● お客さんのスクラムに参加して要件定義から開発までのお⼿伝いをしてます ● 実装するのが好きですが、アーキ考えてるのも好き

Slide 3

Slide 3 text

本⽇のスコープ

Slide 4

Slide 4 text

はじめに 本⽇は⼩難しいことを、できるだけ⼩難しくなく話すつもりです ⼩難しく感じる部分もあるかもしれませんが、 できるだけわかりやすく説明できるよう頑張ります 構成要素にも触れますが、思想やメリットに重きを置いてます これから⼊⾨したいという⽅を対象としています

Slide 5

Slide 5 text

⽬次 1. オープニング 2. ドメインとは / DDD とは 3. メリット → 本当に守れる?(⼊⼝‧永続化‧Repository) 4. いつ DDD する? 5. 構成要素(Entity → Value Object → Aggregate) 6. 集約の切り⽅ 7. クロージング

Slide 6

Slide 6 text

DDDのイメージ DDDに関して - よく聞くけど難しそう - 学習コスト⾼そう - 維持するの⼤変そう こんなイメージありませんか?

Slide 7

Slide 7 text

DDD できちんと設計するのは難しい

Slide 8

Slide 8 text

なにが難しい? DDD の考え⽅(概念構造として捉える)は共通でも、 設計の答えは⼀つに決まらない (画⼀的な正解がない)

Slide 9

Slide 9 text

なにが難しい? 他にも ● エンジニア間でルールとして徹底するのが難しい ● 技術的課題解決との両⽴には、DDD だけでは⾜りないことも多い

Slide 10

Slide 10 text

だけど...

Slide 11

Slide 11 text

「ドメインを概念構造として捉える」という考え⽅は役にたつ

Slide 12

Slide 12 text

本⽇持ち帰って欲しいもの ● DDD ってどういうもの? ● DDD のメリット ● DDD を始めるための構成要素 ○ Entity ○ Value Object ○ Aggregate(集約)

Slide 13

Slide 13 text

今⽇話さないこと 戦略的 DDD ● サブドメイン ● Bounded Context 集約を跨ぐようなロジックの実現⽅法 ● Domain Service ● Domain Event

Slide 14

Slide 14 text

今⽇話さないこと その他の周辺技術‧実装 ● Repository の具体実装(ORM‧SQL‧UoW など) ● Clean Architecture や CQS などとの組み合わせ

Slide 15

Slide 15 text

考え⽅とメリット

Slide 16

Slide 16 text

ドメインってなに? ビジネス⽤語からイメージする 「お客様のビジネス全体に関する知識」 とは範囲が異なる

Slide 17

Slide 17 text

ドメインってなに? 業界の知識のすべてをコードに⼊れるわけではない

Slide 18

Slide 18 text

ドメインってなに?(例) 例えば 図書館の本の管理システム があったとして… 図書館業務の知識全体 ≠ 本の管理システムが担うドメイン (アプリにとって必要な領域に絞る)

Slide 19

Slide 19 text

ドメイン駆動設計(DDD) とは? ドメイン(システムが扱う問題領域)の概念構造を、ソースコードに反映す るアプローチ → ドメインモデリング ドメインの知識をクラス‧メソッド‧名前で表現する ● プロパティ ● 振る舞い ● 不変条件

Slide 20

Slide 20 text

本棚のアプリのドメインモデリングをしてみる

Slide 21

Slide 21 text

概念の構造化 本棚の管理アプリには 本棚 と 本 の概念がある 別の持つ概念なのでそれぞれを クラス として表現する Bookshelf / Book

Slide 22

Slide 22 text

プロパティの付与 本棚‧本には、それぞれ 固有のプロパティ がある それをクラスに 内包する 例: 本棚 → 容量 ∕ 本 → 管理番号‧タイトル

Slide 23

Slide 23 text

所有関係の整理 本棚の管理アプリでは本は 本棚に⼊っている ものとする (野良の本は存在しない) なので 本は本棚が管理 する Bookshelf.books: Book[]

Slide 24

Slide 24 text

振る舞いの定義 本棚から本を 出し⼊れ できる 出し⼊れできるよう、addBook() / removeBook() という振る舞いを作る

Slide 25

Slide 25 text

不変条件の追加 本棚には容量を超えた本は⼊れられない addBook() で容量を超えていないか検証する 守らなければいけないルール=不変条件

Slide 26

Slide 26 text

寄り道:不変条件(invariant) ビジネス上、絶対に壊してはいけない約束 違反すると、ドメイン的に 「壊れた状態」 本棚の例: 現在の冊数 ≦ 容量 → 容量オーバーした本棚は存在してはいけない

Slide 27

Slide 27 text

全体の流れ

Slide 28

Slide 28 text

完成図

Slide 29

Slide 29 text

何がうれしいか 概念構造を表現したコードの中で、 守るべきルールを コードの中に閉じ込めやすい (どう閉じ込めるか は、後ほど説明)

Slide 30

Slide 30 text

何がうれしいか ● オブジェクトが 「実務上で何を表しているか」 を理解しやすい ● コードとビジネスの構造が近くなることで 変更に強くなる ○ アプリの機能が変わってもドメインは影響を受けづらい

Slide 31

Slide 31 text

不変条件:さっきのコードで本当に守れる? 例えば先ほどBookshelfの addBook() に容量チェックを書いたが、 これで 本当に容量超過は防げる?

Slide 32

Slide 32 text

不変条件:さっきのコードで本当に守れる? → このままでは守れない addBook() を書いただけでは 不⼗分 本と本棚を 別々に 操作 できると、 そのルールを守る処理が コード上で必ず通る形になっていない (どこかでチェックしても、別の更新経路ですり抜けうる)

Slide 33

Slide 33 text

ルールを守るには? ルールをチェックする処理が、必ず通る道を作る必要がある

Slide 34

Slide 34 text

更新可能なまとまりを制限する ● Book / Bookshelf を 別々に 更新できる → addBook() をすり抜けたBookができてしまう ● Bookshelfしか更新できない → Bookを追加するためには addBook() しなければいけない Bookshelfの形でしか更新できなくすることでルールを守らせる → 整合が保証されたまとまり= 集約

Slide 35

Slide 35 text

更新のまとまり

Slide 36

Slide 36 text

Repository とは データの永続化を担うレイヤ 受け取るのは必ず 集約(Aggregate) ● BookshelfRepository.save(bookshelf) → OK ● BookRepository.save(book) → NG

Slide 37

Slide 37 text

ここまでのまとめ ● 守るべきルール(不変条件) がある ● 更新経路が 複数 だとルールが破れる ● 集約 + Repository で守る

Slide 38

Slide 38 text

いつやる? では、この⼿の設計を、いつやる価値があるか?

Slide 39

Slide 39 text

いつ DDD を検討するか 2つの段階に分けて考える 考え方 実装 内容 概念構造として捉える Entity / 集約 / Repository まで整える 度合い 常に 役に立つ 規模・難易度 次第

Slide 40

Slide 40 text

いつ DDD を検討するか 本棚の例は、向いている寄り 観点 向いている 過剰になりやすい ルール 複雑なルールがある (本棚の容量など) 入力チェック程度で足りる 更新 入口が複数ある CRUD 1本で問題ない 知識 仕様が 属人化 している CRUDで回せる程度 寿命 長く運用 する 使い捨て

Slide 41

Slide 41 text

全部DDDしないといけない? いきなり「全部 DDD」ではなくても良い ● 容量ルール‧本の所在 がある → 集約までやる価値あり ● 本棚のマスタ登録 → Entity 1個 + CRUD でも⾜りる 複雑なところから。シンプルな部分はシンプルなままでも良い

Slide 42

Slide 42 text

概念構造の構成要素

Slide 43

Slide 43 text

構成要素に名前を付けると 先ほど話題に出した 集約(Aggregate) と呼ばれる構造物は、その中⾝を構 成する要素が存在します 中⾝に名前を付けると… 集約の中⾝ = Entity‧Value Object

Slide 44

Slide 44 text

Entity とは 「もの」 を表す 本棚‧本‧貸出履歴のように、業務上の実体をイメージしやすい (必ずしも現物とは限らない)

Slide 45

Slide 45 text

Entity の特性 ● 同⼀性(ID) で区別される ○ ● 属性を持つ ○ ● IDが同じであれば同⼀のオブジェクト プリミティブな値(例: title: string)、またはValueObject 状態が変わる(Mutable)

Slide 46

Slide 46 text

Entity のコード例(Book)

Slide 47

Slide 47 text

Value Object とは 「値や概念‧ルール」 を表す Entityの属性を、ルール付きの型にするイメージ ● 形式チェックが必要なメールアドレス ● 前後関係の保証が必要な期間(From - To)

Slide 48

Slide 48 text

Value Object の特性 ● 値の等価性で⽐較(ID による同⼀性はない) ● プリミティブな値を 1つ以上 内包し意味とルールを閉じ込める ○ ● 複数の値間で整合をとる必要がある場合2つ以上の値を所有する 値が変わらない(Immutable) ○ Value Objectに内包されている値は直接書き換えない ○ Entityの所有するValue Objectに変更を加えたい場合、新しいValue Objectと差し替え る

Slide 49

Slide 49 text

Value Object のコード例(Capacity)

Slide 50

Slide 50 text

Value Object(補⾜) EntityのIdも Value Object として表現することが多い BookId と BookshelfId の取り違えを防ぐ⽬的がある (TypeScriptの場合要ブランド化)

Slide 51

Slide 51 text

集約(Aggregate)とは 整合性を守るべきまとまりのこと 単⼀のEntityを 集約ルート とし、集約 内の整合性が保証される境界 本棚のアプリでの本棚 Repository で扱える単位

Slide 52

Slide 52 text

集約(Aggregate)の特性 ● 1つの集約につき、集約ルートととなるEntityが必ず1つ存在する ● 外部からの⼦の操作は必ず 集約ルートを経由する ○ ● Bookshelfの books は addBook/removeBook で操作する ⼦となるEntityが存在しないEntityは、そのEntityをルートとする単独の 集約と⾔える ○ 単独で整合が保証されており読み書きが可能である

Slide 53

Slide 53 text

ドメインオブジェクト と物理モデルは別 ドメインオブジェクト は ドメイン上の概念 テーブル‧カラムとは 必ずしも 1:1 にならない 1:1 である必要もない

Slide 54

Slide 54 text

ドメインオブジェクト と物理モデルは別ーズレの例

Slide 55

Slide 55 text

集約のコード例(Bookshelf)

Slide 56

Slide 56 text

集約の切り⽅ 判断基準: 常に⼀緒に整合性を保つべき不変条件があるか 親⼦関係がある ≠ 必ず 1 集約 パターン 例 同一集約内 本棚 + 本 + 容量 分ける 組織とメンバー (跨いだ不変条件がない)

Slide 57

Slide 57 text

本⽇のまとめ 1. DDD = ドメインの概念構造をコードに反映する 2. 守りたいルールは 「必ず通る道」 で守る → 集約 + Repository 3. メリット = バイパスしにくい / 読みやすい / 変更に強い 4. 考え⽅は常に有⽤、実装は複雑なところから 5. 構成要素 = Entity / Value Object / Aggregate 集約は迷ったら 不変条件 で切る

Slide 58

Slide 58 text

No content