イミュータルデータモデルって美味しいの？（基本編）

# この記事は
この記事は[「WEB+DB PRESS VOL.130 特集1実践データモデリング」](https://gihyo.jp/magazine/wdpress/archive/2022/vol130)を読んでのまとめになります。これまでテーブル設計などはしたことはあるが、会社の伝統や社内ルールなどに則ったものばかりで、論理からデータモデルを設計をしたことがない、「イミュータブルデータモデルってなに？」って状態の筆者が書いています。このまとめを「基本編」、実際に稼働しているシステムのデータモデルを参考に、イミュータブルデータモデル的に考えていくとどうなるかを考える「適用編」を後日執筆する予定です。

# 第1章　良いデータモデルの条件
- モデリングは、最終的に出来上がったモデルもさることながら、モデリングの過程でより深く業務要求を分析し顧客やチームとの対話を生むことが本質的価値です。
- システム開発に関わる多様な人々の共通認識を作ることがプロジェクトの成功には欠かせないことです。この共通認識を作るには、今ある業務や誰かの頭の中にあるコンセプトの抽象化が必要になります。そのために何を同じとみなし何を違うと判断するかの議論が共通認識の核となります。
- データモデルはその議論のベースとなるように作成していきます。そのため、実際のRDBのテーブルやクラスと1対1で紐づくものではなく、原則的にはエンジニア以外も含む関係者全員が見て議論できるデータモデルを書くことを目標として作成していきます。
- データモデルを作成していく際の1つの単位が **「エンティティ」** です。エンティティは1つのものを識別するために何らかの識別子が存在し、これに関するいくつかの属性で構成されるものです。また、エンティティを設計するには、主観的な立ち位置で業務の中でどう取り扱っていくかを定めなければならない場合があり、しっかりと関係者で対話して認識をあわせていかなければなりません。データモデルはそのための媒体として使用します。
-  表現するデータモデルは問題領域と解決領域の2つがあり、問題領域は現状の業務モデルを表現したもので、解決領域はこの問題領域を情報システムで実現するときのモデルです。データモデルを作成する際には概念と実装を切り離して考えることが重要です。どう実装するのかはおいておき、まずはデータモデルでエンティティのあいまいさを問題領域でどう記述するかを議論することから始めます。
- データモデルを使って業務に関わっている人々が暗にしか認識してない事業活動や、保有しているデータの活用性やリスクを洗い出すことができます。 なにかしらの情報について「変更できること」には隠された要求があり、変更のイベントについて関係者で議論する必要があります。また、エンティティが区別や種別のような属性をもつのであれば、ここにも深堀りポイントがあります。区別や種別の実装はアプリケーションによって扱いが変わったりするので、こうした違いをアプリケーションの詳細設計まで持ち越さずにデータモデルで表現しておけば、扱いの違いの分析を早い段階で行い、共通認識を形成することができます。

# 第2章　イミュータブルモデルとはなにか
## 「更新」が複雑さの源泉である
- 1つのデータに複数の業務からの更新が発生すると、伴って更新する際のルールが発生します。この更新ルールの意義が後の保守開発者に伝わりにくければ、バグ混入の要因となる可能性が高まります。また、どのプログラムから更新されているのかの把握が難しくなり、改修時の影響調査などの時間が増加します。そもそも、更新が不要に設計できればデータのライフサイクルはシンプルでほとんど自明なものになるはずです。
- 1つのデータに複数の業務からの書き込みが発生すると、整合性を保つための仕組みが必要になります。ロックなどにより他の処理を待機させたりすると、夜間バッチなどの処理時間が長くなる可能性があります。
## 複雑とはなんなのか
- 複雑さをもつエンティティは、複数の概念が混在しており、そこには更新ルールが存在しています。複数の責務が混ざったものはさらに柔軟性を失います。
- 1つの概念、1つの責務に分割して作成しておくことで、エンティティがシンプルになり、わかりやすさと同時に変更容易性を生み出すことに繋がります。
- 「複雑だ」というときに、 **単一のエンティティに内包される複雑さ** と、 **エンティティの数の多さからくる複雑さ**の2つがあります。これまでの方法は、単一のエンティティに内包される複雑さを解消することを推奨するアイディアです。これを実践するとエンティティの数の多さからくる複雑さが増加します。単一のエンティティが内包する複雑さは、整理することで回避可能な複雑さですが、エンティティの数の多さは、ある対象の業務がもともと持っている複雑さなので、回避することができないものです。回避可能かどうかの点で2つの複雑さは単純にトレードオフできるものではありません。
- 単一のエンティティが内包する複雑さを解消しても、エンティティの数の多さからくる複雑さが増えるだけなので、複雑さを変換するだけで同じ結果になるように感じますが、エンティティの数からくる複雑さは本来の業務が持つ複雑さなので、複雑さが可視化され、業務をシンプル化することに役に立ちます。
- 増加したエンティティに対する対処としては、一度に考える範囲を分割する分割統治がよく使用されてきました。業務上結びつきの強いエンティティをグルーピングして分割しましょう。
- これまでの話から、シンプル化のルールを次のように定めます
 **①エンティティに複数の概念、役割、責務が混在しないように分解する**
 **②エンティティをグルーピングして、1度に見る範囲尾を狭める**

## 事実は更新されてはならない
- システムが扱う情報は、モノ（ **リソース**）とコト（ **イベント**）に分類できます。イベントは事業活動において発生した動かせない「事実」であり、6W2Hを属性として正確に記録し、以降は更新されることがあってはなりません。この **「イベントは更新してはならない」** ということを強調するために、作成後その状態を変えられないことを意味するイミュータブルを冠して **「イミュータブルデータモデル」** という名をつけました。すなわち実装においてもイベントを表すテーブルに対する更新をしてはならないことを意味してます。一方でリソースは性質上ライフサイクルがあり、属性が変わったり存在そのものが消滅することもあり得ます。
- 例えば「社員」というエンティティを考えたときに、「入社」というイベントがあり、「社員」というリソースが作成されます。その後「出世」というイベントで「社員」の「役職」という属性が変更され、「退職」というイベントで「社員」リソースが削除されます。時間経過につれ「社員」の属性は変化していきますが、「入社」などのイベントがなかったことになることはありません。

# 第3章 イミュータブルデータモデルの基本
## ステップ1：エンティティを抽出する
- 要求を文章化してそこから動詞、名詞に下線を引き、それらがエンティティの候補になります。
- エンティティは、なんらかの識別子が存在しこれに関数従属するいくつかの属性で構成されます
- 識別子を見つけられない場合は、必ず一緒に使用される、必ず一緒に更新されるなどデータ間になんらかの強い繋がりがあるものを属性として持つエンティティを見出しましょう。
- 設計全般に言えることですが、短くて意味の取れる名前をつけます。中でもエンティティの名前は、これに接頭辞、接尾辞がつけて使用されることも多いので、特に短く命名することが重要です。
- エンティティの単一性やカテゴリを検討する中で、異なるエンティティとみなしたほうがよいと判断したものは、スーパータイプやサブタイプのエンティティで表現します。
## ステップ2：エンティティをイベントとリソースに分類する
- エンティティにはリソースとイベントがあり、 **日時属性を持てばイベント、持たなければリソースと判断します**。
- エンティティの伝統的な分類に「マスタ」と「トランザクション」がありますが、この分類は曖昧なものなので使わないようにします。
## ステップ3：イベントには日時属性を1つだけ持つようにする
- 複数の日時属性をもつ場合、複数のエンティティに分解します。この日時属性で分割することはイベント（事実）ごとにエンティティを作成することになり、正規形の原則「1つの事実は1つの場所に」を満たしていることにもなります。
## ステップ4：リソースに隠されたイベントを抽出する
- リソースとして分類したエンティティを着目し、更新する業務イベントがないか考え、その更新を記録して置きたいなどの要求がある場合、イベントエンティティとして抽出します。
- 「登録日時」や「変更日時」はエンティティに一律もたせる必要はありません。むしろ持たせたいと思ったときは、設計を見直し、隠されたイベントの抽出やエンティティの分離をおこなう必要があると思われます。
- データのライフサイクルに注目すると単一のエンティティの複雑さを洗い出すことができます。エンティティの属性が異なるタイミングで生成、変更されるいくつかのグループに分かれているとしたら、1つのエンティティの中に複数の概念を含んでいる可能性があります。
## ステップ5：非依存のリレーションシップを交差エンティティで表す
- リソースエンティティどうしで非依存関係があれば、それを交差エンティティとして表現します。
- イベントエンティティどうしでは時系列の逆転した関係があればそれを交差エンティティとします。
# 基本編はここまで
第4章 イミュータブルデータモデルの実践 
第5章 ドメインモデルへの応用
実際のシステムのデータモデルへの適用
を次回書きたいと思います。