はじめに
WEB+DB PRESS Vol.130の『イミュータブルデータモデルで始める 実践データモデリング』という記事がめちゃくちゃ勉強になったので、大事だなと思ったところを中心にまとめていきます。 この本読むまではテーブル設計って何をどうすればいいのか全然わからなくて完全に視界が真っ暗だったんですが、この記事のおかげで最低限守るべき原則が自分の中に出来上がりました。 今まで設計したテーブル全部作り直したい。
大原則
- やりたいことは「複雑さへの対処」
- 複雑さを解消し、シンプルな構造にすることで保守性・拡張性を確保したシステムを構築する
なぜ複雑さが生まれるのか?
- 「更新」が複雑さの源泉
- 「変更できること」という要求の裏には、さまざまな業務イベントが存在している
- 変更を意識せずにモデリングすると、一つのオブジェクトに複数の業務イベントが混在することになる
→ これが複雑さにつながる。
複雑性には二種類ある
- 単一のエンティティに内包される複雑さ
- 回避可能(複数の概念や役割を持たないようにすることができる)
- エンティティの数の多さからくる複雑さ
- 回避不可能(対象の業務が持つ生来的な複雑さを示しているため)
→ 記録すべき「事実(イベント)」が何かを明らかにし、「事実」に更新操作が入らないよう設計することで、エンティティに複数の責務を持たせないようにする
シンプル化の基本ルール
- エンティティに複数の概念・責務が混在しないよう分解
- エンティティをグルーピングして、一度に見るべき範囲を狭くする
複雑性を排したモデリングの手順
- エンティティを抽出
- エンティティをイベントとリソースに分類する
- システムが扱う情報は、モノ(リソース)とコト(イベント)に分類できる
- エンティティが日時属性を持っていればイベント、持っていなければリソースである
- 一つのイベントが一つの日時属性を持つ構造にする
- 複数の日時属性を持っているということは、複数の概念・責務が混在しているということ
- リソースに隠されたイベントを抽出
- リソースに「変更日時」を持たせたい要求があるのなら、それはイベントとして切り出す
- 非依存のリレーションシップは交差エンティティで表す
- リソースエンティティ同士で非依存関係があれば、交差エンティティとして表現
一連のイベントで構成される一つの業務をわかりやすく表すには?
- 最新の状態を知りたいという要求があるのなら、ロングタームイベントパターン が適している
- 過去や未来のデータを扱うのに適した3例
- シングル世代テーブルパターン
- 適用開始日と適用終了日を属性として持たせる
- 主キーに適用開始日を含む必要がある
- 有効世代ビューパターン
- 世代管理は必要だが、サブシステムでは最新のデータのみ参照できれば良いという時に有用
- 世代バージョンタグ付けパターン
- 全ての世代でデータを持っておいて、バージョンやタグで必要なものを指し示す
- 乱用するとクエリが複雑に
- シングル世代テーブルパターン
エンティティの種別(ex. 現役社員と退職社員)を区別して扱いたい場合
- サブタイプを実装する
- 単一テーブル継承パターン
- スーパータイプとすべてのサブタイプを一つのテーブルにまとめる
- 具象テーブル継承パターン
- サブタイプごとにテーブルを作る
- クラステーブル継承パターン
- スーパータイプ・サブタイプそれぞれにテーブルを作る
- 全部のサブタイプに対応するテーブルを結合する使い方があると性能問題に
- 単一テーブル継承パターン
感想
- 「複雑さの原因は変更」という説明が非常にわかりやすかった。
- 「一つのイベントには一つの日時属性」というのも然り。この考え方で設計すると自然と正規化がなされるとのこと。次テーブル設計やる時に意識したい。
- 一連のイベントやエンティティの種別を表現するパターンもめちゃくちゃ参考になった。今までこのような悩みを持ちながら削除フラグでお茶を濁してたりしてたのですごいありがたい。