SlideShare a Scribd company logo
イミュータブル
データモデルの
極意
kawasima
Division into cases
aを実数とする。xについての方程式
ax = 1
を解け。
a ≠ 0のとき: x = 1 / a
a = 0 のとき: 解なし
ソフトウェア設計における場合分け
「〇〇って設計手法使ってやってみたんですが、あんまり上手くいかなくて…」
「あー、〇〇が有効なのも、ケースバイケースですからねぇ…」
現状、残念ながら場合分けが形式知となっていないものが多い
ソフトウェア設計における場合分けを形式知にしていこう運動
そんな中で、ここでは「データ」の取り扱いに関しての場合分けをテーマにします
https://scrapbox.io/kawasima/アーキテクチャ大全
Dataの場合分け
Data / Inform / Information
Inform: “to convey knowledge via facts (事実によって知識を伝える)”
Data
(Factの集合)
Information
選択・加工して知識を取り出す
Value of Values (Rich Hickey)
業務システム構築におけるデータモデリング (和田省二)
Dataを場合分けする
Event (コト) Resource (モノ)
日時属性をもつ 日時属性をもたない
非対称性 対称性
ある一時点 ライフサイクルがある
一時点の事実の記録なので、属性は変わる
ことはない。
ライフサイクルにともない属性が変化して
いくこともある。
属性が変化しても同じモノであることを示
すためIdentityが必要。
データは大まかに2種類に分別できる。
リソースとイベントの関係
会員削除
イベント
会員登録
イベント
会員 (会員ID = 1)
会員変更
イベント
イベントによってリソースが生成・更新・削除される
会員変更
イベント
アプリケーション上での扱い
<<domain>>
会員
会員登録
コマンド
会員登録完了
イベント
会員登録
ユースケース
<<persistence>>
会員
<<persistence>>
会員登録
※イベントを永続化するか
どうかは業務設計における
選択
会員登録
イベント
Relationship
場合分けに沿うと3種類考えられる
Event Resource
Event
Resource
Event
Resource
注
ここでの話はあくまでも、データとデータの関連の話であって、RDBのテーブル設計に
限りません。
RDBのテーブル設計を前提とした箇所は、以下の表記を使います。
ID
なんらかの属性
…
エンティティ名
イベント-リソースの関連
When 時期
Where 場所
Who 主体
With Whom 相手
Whom 関係者
What 対象
Why 理由
How 手段
How many 数量
How much 金額
注文
(Order)
顧客
販売員
販路 商品
注文明細
(Order Line)
数量
単価
Event Resource
イベントの7W3Hがリソースと関連を持つ
リソース-リソースの関連
依存関係があるか? ライフサイクルを同じくするかどうか? で場合分け
Resource Resource
都道府県
国
部屋
ホテル
親子関係があって、親が存在なしでは
子が存在し得ない
部門
ユーザ
リソースは非依存でどちらが先に作られ
ても構わない
社員
電子書籍
所属
購読
依存/非依存は絶対的ではない
競走馬
父親
競走馬は父親、母親が明確でないと登録できない (依存関係)
母親
動物園で飼う馬は血統が明らかでなくても登録できなきゃいけな
い(非依存関係)
馬
馬
血縁
(母)
血縁
(父)
馬
イベント-イベントの関連
出荷 請求
時系列的な繋がり。並びが変わると関係が変わる。
出荷
請求
後払い
前払い
Event Event
業務的な時系列的な並びを変えてはならない。
注文 請求
1..*
複数の注文をまとめて請求する
注文ID
請求ID
注文日時
注文
請求ID
請求金額
請求日時
請求
注文ID
注文日時
注文
請求ID
請求金額
請求日時
請求
請求ID
注文ID
注文-請求
✕ ○
Details
細かいところあれこれ
サブタイプ
データに共通の性質があり、それを表現する。
社員
現役社員 退職社員
スーパータイプ
サブタイプ
社員ID
氏名
社員ID
退職社員
現役社員
社員ID
社員区分
社員
社員区分= 現役 | 退職
リソースのサブタイプの場合は「区分」によって分類するとよい。
※イベントのサブタイプは後述します
イベント自体が親子構造をもつケース
{
“注文ID”: 1,
“注文日時”:”2021-10-10T04:50:40”,
“注文者”: {
“ID”: 3
},
“注文明細”: [
{
“注文明細ID”: 1,
”商品ID”: 8
“数量”: 5,
“単価”: 100
}
]
}
RDBのテーブルへの実装を考えなければ、こういう
構造を作って、「明細はイベントだっけ?」とか疑問
を持たないはず。
注文明細ID
商品ID
数量
単価
注文明細
注文ID
注文日時
注文者ID
注文
ひっくるめてイベント
子のイベントに後続のイベントが関連持つ場合もある
注文明細ID
商品ID
数量
単価
なので、注文明細は日時属性は持たないが、イベントみなして扱おう
出荷ID
注文明細ID
出荷日時
注文明細
出荷
注文ID
注文日時
注文者ID
注文
一連のイベントのステータスを知りたい
入会
申込
審査
会員証
発行
免許証
登録
一連のイベントを束ねたロングタームイベント(ex. 入会)を作る
入会
申込
審査
会員証
発行
免許証
登録
入会
アクティビティ
入会
入会
ステータス
アクティビティ日時
入会アクティビティ
入会アクティビティID
入会ID
入会ステータス
最終アクティビティ日時
入会
氏名
社名
…
入会アクティビティID
審査者ID
…
入会アクティビティID
到着予定日
…
入会アクティビティID
入会申込 審査 会員証発行
免許証番号
確認者ID
…
入会アクティビティID
免許証登録
入会ステータス=
入会申込| 審査 | 会員証発行| 免許証登録
リソース同士の関連付けのイベント
部門 社員
所属
所属の関連を作るのに、「配属」イベントがありそれを記録したい
部門 社員
所属
配属
リソースの関連とそれに関するイベントとは別で識別しよう
部門ID
社員ID
社員ID
社員名
所属
社員
部門ID
部門名
部門
配属ID
部門ID
社員ID
配属日
配属
どのFactを記録するか?
まとめ的な話
どのイベントを記録として残すか?
これ自体が、業務設計であり、システム設計である。
● リソースの発生・変更・消滅するところにはイベントがある
→ 変更履歴
● イベント発生からまた次のイベントが生み出されることがある
→ 注文→請求→支払→出荷 などの一連の業務フローイベント
● 非依存のリソース同士が関連付け/解消されるところにはイベントがある。
→ 予約、注文などの業務イベント ; 配属や割当などの操作履歴
全部が全部必要ではない。記録・保管にも金がかかる。
● お金を産むもの
● 記録が無いとお金を失うリスクがあるもの
を取捨選択する
そして記録すると決めたイベントは、Factが失われるので
決して変更されてはならない
(という意味でのイミュータブル)

More Related Content

イミュータブルデータモデルの極意