Database Design
DB の命名は、タスクに名前を付けることではない。永続化する概念を抽象化し、その概念に名前を付けることである。名前が特定用途に結びつきすぎると、用途が増えた時点で名前が嘘になり、局所最適化されたテーブルやカラムが増える。
テーゼ
- 何であるかで名付ける。 命名前に処理目的・画面名・連携元・入出力形式をいったん取り除き、残った概念に名付ける。名前に取得方法・利用先・表示都合・同期都合・ジョブ都合・入出力都合が残っていたら、それが本当にドメイン概念かを疑う。別の用途・別の作成経路・別の参照経路でも成立し意味が変わらないなら、概念名として再利用に耐える。
- 分離はモデル構造で判断する。 正規化やテーブル分割は、用途があるからではなく、独立した entity・属性・関係・ライフサイクル・制約・cardinality を表す必要があるときに行う。テーブルが増えること自体は問題ではない。問題は、分離の理由がデータモデルではなく一時的な処理都合になっていることである。
good / bad 例
以下はテーゼを説明するための例であり、そのまま命名規約として固定するものではない。
ユーザーのメールアドレスを取り込む 取り込み処理が起点でも、保存される概念はユーザー、またはユーザーに紐づくメールアドレスである。
good
- users
- user_emails
bad
- user_imported_email_addresses
注文画面に表示する明細を保存する 画面表示が目的でも、保存される概念は画面用の明細ではなく、注文に含まれる明細である。
good
- order_items
bad
- order_items_for_display
外部サービスから取得した会社情報を保存する 取得元はメタデータになり得るが、主概念そのものを取得経路で命名しない。
good
- companies
- company_external_refs
bad
- crm_imported_company_records
エクスポート用に住所を保持する エクスポートは利用目的であり、保存される概念は住所である。
good
- addresses
- shipping_addresses
bad
- addresses_for_export
チェックリスト
- 保存したい内容を、実装都合(処理・画面・連携・入出力)を除いて言い換えたか
- それが entity・属性・関係・事実・状態のどれかを分類し、その概念に直接名付けたか
- 名前は「何をするか」ではなく「何であるか」を表しているか
- 現在の処理・画面・連携・入出力を知らなくても意味が通るか
- テーブル分割・正規化の理由は用途ではなく、entity・関係・制約・ライフサイクル・cardinality の違いか(分割後の各名前も概念名として成立するか)
- 別の用途・別の作成/参照経路が追加されても名前が嘘にならないか