
- 🚀 コードの保守性には気を遣うけど、DB設計は?
- ⚠️ コードは変えられるが、DBは変えにくい
- 📈 スケールしやすい構造を最初から考える
- 🎯 正規化:「無駄を省くこと」
- 🔍 本当に必要な要件かを考える
- 🌟 まとめ
🚀 コードの保守性には気を遣うけど、DB設計は?
開発をしていると、「コードの保守性」というキーワードをよく聞きます。
リファクタリングの重要性、可読性の向上、設計パターンの適用など、コード品質に関しては多くの開発者が意識を向けています。
DB設計はどうでしょうか?
今回は、なぜDB設計が重要なのか、そして実際にどう取り組めばよいのかを整理してみました。
⚠️ コードは変えられるが、DBは変えにくい
🔄 コードはリファクタリングできる
# ❌ 修正前:読みにくいコード
def calc(a, b, c)
if a > 0
return a * b + c
else
return 0
end
end
# ✅ 修正後:読みやすいコード
def calculate_total_price(quantity, unit_price, tax)
return 0 if quantity <= 0
quantity * unit_price + tax
end
コードの場合、このようにリファクタリングという形で後から改善できます。変数名を変更したり、関数を分割したり、設計パターンを適用したりと、運用中でも比較的安全に修正が可能です。
🗄️ DBは運用開始後の変更が困難
一方で、DB設計は運用が始まってから変更するのは結構難しいんです。
-- ❌ 後から気づいた問題のあるテーブル設計
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255),
address TEXT -- 住所を1つのフィールドに格納
);
-- ✅ 理想的だった設計
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255)
);
CREATE TABLE addresses (
id INT PRIMARY KEY,
user_id INT,
prefecture VARCHAR(50),
city VARCHAR(100),
street VARCHAR(255),
postal_code VARCHAR(10),
FOREIGN KEY (user_id) REFERENCES users(id)
);
上記の例で、運用開始後に住所の検索機能が必要になった場合、都道府県別の集計が必要になった場合など、既存のデータがある状態でのテーブル構造変更は:
- データ移行が必要
- ダウンタイムが発生する可能性
- アプリケーションコードの大幅な修正が必要
- バックアップとロールバック計画が必須
📈 スケールしやすい構造を最初から考える
💡 要件からテーブル・カラム設計を考える
DB設計では、しっかりと要件から何をテーブルとして、何をカラムとして持つのかを考える必要があります。
-- 🤔 これで本当に十分?
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(255),
price DECIMAL(10,2),
category VARCHAR(100)
);
-- 🎯 将来を見据えた設計
CREATE TABLE categories (
id INT PRIMARY KEY,
name VARCHAR(100),
parent_id INT,
FOREIGN KEY (parent_id) REFERENCES categories(id)
);
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(255),
description TEXT,
category_id INT,
created_at TIMESTAMP,
updated_at TIMESTAMP,
FOREIGN KEY (category_id) REFERENCES categories(id)
);
CREATE TABLE product_prices (
id INT PRIMARY KEY,
product_id INT,
price DECIMAL(10,2),
effective_from DATE,
effective_to DATE,
FOREIGN KEY (product_id) REFERENCES products(id)
);
この設計により:
- カテゴリの階層構造に対応
- 価格履歴の管理が可能
- 将来的な拡張に対応しやすい
🎯 正規化:「無駄を省くこと」
正規化は難しくない
よく言われるのは正規化ですが、一言でいえば「無駄を省くこと」です。何も難しいことではなく、無駄や重複、論理破綻が起きないように設計していけばよいのです。
-- ❌ 非正規化:データの重複と不整合のリスク
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_name VARCHAR(255),
customer_email VARCHAR(255),
customer_address TEXT,
product_name VARCHAR(255),
product_price DECIMAL(10,2),
quantity INT
);
-- ✅ 正規化:データの重複を排除
CREATE TABLE customers (
id INT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255),
address TEXT
);
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(255),
price DECIMAL(10,2)
);
CREATE TABLE orders (
id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
FOREIGN KEY (customer_id) REFERENCES customers(id)
);
CREATE TABLE order_items (
id INT PRIMARY KEY,
order_id INT,
product_id INT,
quantity INT,
FOREIGN KEY (order_id) REFERENCES orders(id),
FOREIGN KEY (product_id) REFERENCES products(id)
);
正規化のメリット
- データの不整合を防ぐ
- ストレージの効率化
- 更新処理の単純化
- データの整合性担保
🔍 本当に必要な要件かを考える
無駄を作らないために
無駄を作らないためにも、本当に必要な要件なのかをしっかり考えることが大切です。
-- ❌ 「念のため」で追加したフィールド
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255),
email VARCHAR(255),
phone VARCHAR(20),
fax VARCHAR(20), -- 本当に必要?
blood_type VARCHAR(5), -- 本当に必要?
hobby TEXT, -- 本当に必要?
memo TEXT -- 何のためのメモ?
);
-- ✅ 必要最小限から始める
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
🎯 要件整理のポイント
- 現在の必須要件を明確にする
- 将来の拡張可能性を考慮する
- 「念のため」フィールドは避ける
- 実際の使用パターンを想定する
🌟 まとめ
DB設計は、一度決めてしまうと後から変更するのが非常に困難です。だからこそ、最初の設計段階でしっかりと検討することが重要。
🎯 DB設計で意識すべきポイント
- ✅ 要件を深く理解する
- ✅ 正規化で無駄と重複を排除する
- ✅ 将来のスケールを考慮する
- ✅ 本当に必要な機能だけを実装する
- ✅ データの整合性を保つ仕組みを作る
コードのリファクタリングと同じように、DB設計にも時間と労力を投資することで、長期的に保守しやすく、スケールしやすいシステムを構築できます。
皆さんも、次のプロジェクトではDB設計により多くの時間を割いて、後から「あの時ちゃんと設計しておけばよかった...」と後悔しないような設計を心がけてみてください!
🚀 良いDB設計で、より良いアプリケーション開発を!