正規化と情報アーキテクチャの違いを考察する
概要
- 日程: Day 3 / セッション 6
- 時間: [13:30-14:15]
- 形式: 演習
- ゴール: Day 2で作成した自分の情報モデルを(条件)第3正規形を目安にRDBのテーブルに変換(正規化)し(行動)、情報モデルと正規化済みテーブルの違いを「誰のための設計か」の観点で3点以上挙げられる(基準)
- 学習形式: ハンズオン実習(AIサポートあり)
導入(5分)
前のセッションの最後にこう予告しました。
情報モデルはペルソナのため、正規化はコンピュータのため。
言葉としては簡単です。でも、本当にそうなのでしょうか。
ここで少し考えてみてください。同じ「支出」という情報を、ペルソナ向けに描いた図と、コンピュータ向けに描いた図。
本当に姿が変わるのでしょうか。変わるとしたら、どこが、なぜ変わるのでしょうか。
この演習では、それを他人の教科書ではなくあなた自身の成果物で確かめます。
Day 2で作った情報モデルを、実際に正規化してテーブルに変換します。
そして変換の前後を並べて、「誰のための設計か」という観点で違いを言語化します。
実はこれが、本研修の看板である**「情報の設計とシステムの設計の分離」の核心**です。
分離できるのは、そもそも2つが別物だからです。別物であることを自分の目で見るのが、この45分です。
本編(10分)
1. 同じ情報の二つの姿 家計簿の通し例
まず家計簿システムの通し例で、変換の全体像を見ます。
Day 2で作った「支出記録」の情報モデルは、こういう形でした。
情報モデル名: 支出記録(ペルソナ: 節約したい佐藤さん)
属性:
- 日付(必須)
- 金額(0以上・必須)
- カテゴリ(食費・交際費など、名前で選ぶ)
- メモ(任意)
- 支払方法(現金・クレジットカードなど)
関係:
- 支出記録は1つのカテゴリに属する
制約条件:
- 金額は0以上の整数
佐藤さんの頭の中の「支出」が、そのまま1つのまとまりになっています。
これを正規化すると、3つのテーブルに分解されます。
(日付・金額・カテゴリ・メモ・支払方法)
ペルソナ視点のひとまとまり"] IM -->|正規化(システム視点への変換)| E["expenses
(id, spent_on, amount, memo,
category_id, payment_method_id)"] IM -->|カテゴリを分離| C["categories
(id, name)"] IM -->|支払方法を分離| P["payment_methods
(id, name)"] E -->|category_id で参照| C E -->|payment_method_id で参照| P
同じ「支出」なのに、姿がまるで違います。違いを3つだけ、考察の例として見せます。
- まとまりの数: 情報モデルは1つのまとまりでしたが、テーブルは3つに分かれました。佐藤さんは支出を3つに分けて考えたりしません。分けたのはコンピュータの都合(重複の排除)です
- IDの出現: 佐藤さんは「食費」という名前で考えます。テーブルは category_id=10 という番号で繋ぎます。IDはペルソナの世界には存在しなかった、純粋にシステム側の住人です
- 重複の扱い: 情報モデルでは「カテゴリ=食費」と何度書いても気になりません。テーブルでは「食費」という文字列は categories に1回だけ書かれます
これは翻訳のようなものです。同じ内容でも、日本語の手紙と英語の手紙では語順も敬語も変わります。
読み手が変われば、正しい形が変わるのです。読み手は誰か。情報モデルはペルソナ、テーブルはコンピュータ(RDB)です。
コード例・実例
正規化後のテーブルをSQLにするとこうなります。前セッションのCREATE TABLEの実戦版です。
CREATE TABLE categories (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE
);
CREATE TABLE payment_methods (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL UNIQUE
);
CREATE TABLE expenses (
id INTEGER PRIMARY KEY,
spent_on DATE NOT NULL,
amount INTEGER NOT NULL CHECK (amount >= 0),
memo TEXT,
category_id INTEGER NOT NULL REFERENCES categories(id),
payment_method_id INTEGER NOT NULL REFERENCES payment_methods(id)
);
情報モデルの制約条件「金額は0以上」がCHECK制約として生き残っている点にも注目してください。
消えるものと生き残るものがある。それも考察の材料です。
ここがポイント
- 同じ情報でも、情報モデル(ペルソナ視点)と正規化テーブル(システム視点)は別の姿になる
- どちらかが正しくてどちらかが間違いなのではない。読み手が違うだけ
- 情報モデルを捨ててテーブルだけ持てばよい、にはならない。ペルソナと会話する言葉はテーブルにはない
コラム
現場では、あえて正規化を崩す
「第3正規形まできっちり正規化するのが常に正義」と思いきや、実務では非正規化という逆方向の判断が普通にあります。たとえば支出一覧を表示するたびに3テーブルを結合(JOIN)すると、データが数千万行の規模では遅くなることがあります。そこで「カテゴリ名をexpensesにもコピーして持つ」と、重複と引き換えに速度を買うのです。もちろん更新不整合のリスクは戻ってきます。つまり正規化の度合いは、正しさの階段ではなくトレードオフの選択です。判断基準はここでもペルソナに戻ります。「佐藤さんにとって、一覧が2秒遅いのと、まれにカテゴリ名がずれるのと、どちらが致命的か」。Day 2で書いた非機能要件が、こういう場面で効いてきます。
2. 考察の観点 「誰のための設計か」で見る
このあと自分の情報モデルを正規化したら、違いを3点以上書き出します。
答えは自分で見つけてほしいので、観点だけ渡します。次の5つのレンズで前後を見比べてください。
- 分解のされ方: 何が1つのまとまりで、何が別の表に切り出されたか。切り出しの理由は誰の都合か
- IDの有無: 変換後に現れた id や 〜_id は、ペルソナの世界に存在したか
- 重複の扱い: 情報モデルで気にしなかった重複が、テーブルではどう処理されたか
- 変更への強さ: 「カテゴリ名を『食費』から『食料品費』に変える」とき、それぞれの世界で何か所直すか
- 読み手: その図・表を見て一目で意味が取れるのは、佐藤さんか、RDBか
「テーブルが3つに増えた」は考察の入口には該当しますが、それだけでは考察に該当しません。
なぜなら基準は「誰のための設計かの観点で」だからです。「増えた。それはコンピュータの更新不整合を防ぐためで、佐藤さんには関係ない都合だ」まで書けて考察です。
考察に詰まったら、無理にひねり出す前にAIに観点の壁打ちを頼んでみましょう。ただし考察文そのものはAIに書かせないこと。ここはDay 3成果物の心臓部です。
コード例・実例
考察メモの書きぶりの見本を1つだけ示します(家計簿の例)。
違い1: ペルソナは「カテゴリ名」で考えるが、テーブルは category_id で繋ぐ。
名前は人間の言葉、IDはコンピュータが取り違えないための言葉。
→ 情報モデルはペルソナのため、IDはコンピュータのための設計だと分かる。
この「事実 → 理由 → 誰のためか」という3段構えを、自分の言葉で3本以上書きます。
ここがポイント
- 考察は「事実(違い)→ 理由 → 誰のためか」の3段で書く
- 5つのレンズ(分解・ID・重複・変更への強さ・読み手)のどれかに必ず引っかかる
- 表面的な違い(数が増えた・英語になった)で止めない。「なぜ」を1回は掘る
コラム
NoSQLは「正規化への反乱」から生まれた
2000年代後半、GoogleやAmazonのようなWeb企業は、世界中から秒間数十万のアクセスを受ける規模に達しました。正規化されたRDBは矛盾のなさと引き換えに、サーバを何百台にも分散させることが苦手です。そこで彼らは「多少の重複や一時的な不整合は許す。その代わり無限に分散できる形にする」と割り切ったデータストア(BigTable、Dynamo)を自作しました。これがKey-ValueストアをはじめとするNoSQLムーブメントの源流です。面白いのは、これも結局「誰のための設計か」の話だという点です。RDBの正規化は一貫性を求めるコンピュータのため、NoSQLの非正規な構造は地球規模のトラフィックというビジネスのため。設計の形は、仕える相手が決めるのです。
💬 AIに聞いてみよう
- 「正規化で私の情報モデルが3つのテーブルに分かれました。ペルソナ(家計簿ユーザ)にこの3テーブルをそのまま見せるべきでない理由を説明してください」
- 「『変更への強さ』の観点で、情報モデルと正規化済みテーブルを比較する具体例を、カテゴリ名の変更を題材に作ってください」
- 「私の考察(貼り付ける)は『誰のための設計か』の観点になっていますか。表面的な指摘があれば、どこを掘るべきか質問で返してください」
実習・演習
課題
自分の開発テーマの情報モデル(Day 2の成果物)を使って、次の3ステップを行ってください(目安35分)。
- 正規化する(15分): 主要な情報モデル1つ以上をRDBのテーブルに変換する。第3正規形を目安に、重複しうる属性(カテゴリ・種別・名前のマスタ的なもの)を別テーブルに切り出す。CREATE TABLE文または表形式で書く
- 前後を並べる(5分): 情報モデル(変換前)とテーブル設計(変換後)を1画面に並べ、変わった箇所に印を付ける
- 考察を書く(15分): 「誰のための設計か」の観点で違いを3点以上、「事実 → 理由 → 誰のためか」の3段構えで書く
ステップ1では、AIに答えを丸ごと出させず、対話しながら進めるのがコツです。次のプロンプトをコピペして使ってください。
以下は私の開発テーマ「(テーマ名)」の情報モデルです。
(情報モデルを貼り付ける)
この情報モデルを第3正規形まで正規化してください。
ただし一気に答えを出さず、分解の各ステップで
「なぜここで分解するのか」を私に質問しながら進めてください。
私が答えてから次のステップに進んでください。
ステップ3の壁打ちにはこちらを使います。
情報モデル(変換前)と正規化済みテーブル(変換後)を貼ります。
(両方を貼り付ける)
私はこの2つの違いを「誰のための設計か」の観点で考察します。
まだ答えは言わないでください。
私が見落としそうな観点を、ヒントの質問の形で3つください。
成果物
- テーブル設計(正規化済み): CREATE TABLE文または表形式。本日の成果物「テーブル設計(正規化済み)」そのもの
- 考察メモ: 情報モデルとの違い3点以上(各点を「事実 → 理由 → 誰のためか」で記述)
テーブル設計はこの後のセッション8(RESTful API設計)と明日の実装の土台になります。
ヒント
- 切り出し候補が見つからないときは、属性の中の「名前で選ぶもの」「種類・区分」を探す。それがマスタテーブルの種
- 情報モデルとそっくり同じ形のテーブルが1枚できただけなら、正規化されていないサイン。重複しうる属性をAIと一緒に探す
- id を導入することに気持ち悪さを感じたら、それ自体をメモする。その違和感こそ「ペルソナの世界にIDは無い」という考察の一級素材
- 逆にやり過ぎにも注意。「メモ」欄まで別テーブルに切り出す必要はあるか? 迷ったら「重複して矛盾する危険があるか」で判定する
まとめ(5分)
今回学んだことを一言でまとめると「同じ情報でも、ペルソナのための情報モデルとコンピュータのための正規化テーブルは別の姿になる。だから情報の設計とシステムの設計は分離できるし、分離すべき」です。
- 情報モデルは1つのまとまり、正規化テーブルは重複を排した複数の表。読み手が違うから形が違う
- IDはシステム側の住人。ペルソナは名前で考える
- 正規化の度合いすらトレードオフ。判断の基準は最後はペルソナに戻る
- 変換前後の両方を持ち続けることに意味がある。片方はペルソナとの会話用、片方は実装用
これで「情報の設計」と「システムの設計」が本当に別物だと、自分の成果物で確認できました。
別物なら、間を繋ぐ通り道が要ります。次のセッション7は、まさにその通り道、UIと機能の通信(HTTP、REST)です。
今日作ったテーブルの中の情報が、どうやって画面まで旅をするのか。分離の物語の続きを見に行きましょう。
🔄 振り返りチェック
- 自分のテーブル設計を指差しながら、「ここはコンピュータの都合で分けた」と説明できる箇所を言えますか?
- 情報モデルと正規化テーブルの違いを、他人の例ではなく自分の成果物で3点言えますか?
- 「正規化したのだから情報モデルはもう不要」という主張に、反論を一文で言えますか?
補足資料
- 参考リンク:
- SQLiteで手軽に試す: https://www.sqlite.org/ (ブラウザ実行なら https://sqliteonline.com/ )
- Martin Fowler「OrmHate」(ORMと設計の分離について): https://martinfowler.com/bliki/OrmHate.html
- 発展課題:
- 自分のテーブルにサンプルデータをINSERTし、「支出一覧をカテゴリ名付きで出す」SELECT文(JOIN)をAIと書いてみましょう。3テーブルの情報が1つの見た目に戻る瞬間が観察できます
- あえて非正規化する案(カテゴリ名をexpensesにも持つ)を作り、メリット・デメリットを自分の非機能要件一覧書と照らして評価してみましょう
学習ガイド
想定される質問と回答例
| 質問 | ヒント |
|---|---|
| 情報モデルが小さくて、正規化しても1テーブルのままになる | それ自体は誤りではない。ただし「カテゴリ」「種別」など名前で選ぶ属性が1つでもあれば切り出し候補。無ければ隣の情報モデル(複数モデルの関係)まで範囲を広げて正規化する |
| 第3正規形になっているか自信が持てない | AIに「このテーブル設計は第3正規形ですか。違反箇所があれば、どの属性がどの属性に依存しているかを指摘してください」と検査させる。本演習の主目的は考察なので、厳密さより違いの言語化を優先 |
| 考察が2点までしか出てこない | 5つのレンズ(分解・ID・重複・変更への強さ・読み手)のうち、まだ使っていないレンズを確認する。特に「変更への強さ」はカテゴリ名の変更を想像すると必ず1点出る |
| テーブル設計ができたら情報モデルは捨ててよい? | 捨てない。ペルソナと要件を確認する言葉は情報モデル側にしかない。テーブルだけ残すと、Day 4で「この画面はなぜ要るのか」に答えられなくなる |
つまずきやすいポイント
| つまずきポイント | ヒント |
|---|---|
| 情報モデルと同じ形の表を1枚作って「正規化した」と思ってしまう | 正規化は形の写し替えではなく分解。カテゴリ名・支払方法名のような「繰り返し登場しうる値」が支出の表の中に残っていたら、まだ分解の余地がある |
| id や category_id の導入に抵抗を感じ、手が止まる | その違和感は正しい。ペルソナの世界にIDは無いのだから。違和感を消すのではなく考察メモに書く。IDは「コンピュータが名前の重複や変更に惑わされないための道具」と割り切る |
| 考察が「テーブルが増えた」「英語になった」など表面的な違いで止まる | 「事実 → 理由 → 誰のためか」の3段構えを機械的に埋める。理由(更新不整合を防ぐ等)と受益者(コンピュータかペルソナか)まで書いて1点と数える |
| 正規化テーブルを「情報モデルの完成版・上位互換」と誤解する | 2つは目的の違う並列の成果物。情報モデルはペルソナとの会話用、テーブルはRDBとの会話用。片方で他方を代用すると、要件か実装のどちらかが壊れる |