1. Mojoliciousスタートアップ
  2. here

データベースのテーブル名とフィールド名の命名規約

Mojoliciousスタートアップでは、ビジネスのスタートアップを始める方に向けて、データベースのテーブル名とフィールド名の命名規約をひとつ示したいと考えています。

データベースのテーブル名と列名は自由に決めることができますが、プロジェクトで、一つの命名規約があれば、一貫して名前をつけることができ、悩むことが少なくなります。

良くまとまっているものとして、以下の記事を発見しましたので、これを翻訳して、紹介します。YiiはPHPのWebフレームワークのひとつです。

よいスキーマデザインのためのガイドライン - YiiフレームワークWiki

YiiとあるところはMojolicious、ActiveRecordとあるところはPerlのDBIあるいはO/Rマッパーと読み替えてください。Mojoliciousスタートアップ用に、各所の補足を入れました。

  • 複数形ではなく単数形でデータベースのテーブルに名前を付ける
  • フィールド名の前にDBテーブル名を追加しない
  • モデルクラス名にテーブルプレフィックスを含めない
  • テーブルのID列に「id」という名前を付けます
  • 意味のある主キー名を避ける
  • データベーススキーマで外部キーの関係を定義する
  • 「id」で終わる外部キーフィールドに名前を付ける
  • 単数形/複数形の性質を反映する名前関係を行う

初めに

事実上、すべてのYiiアプリケーションはデータベース上に構築され、YiiはDBに対処する方法が非常に柔軟ですが、設計をうまく選択することによって、他の設計よりも便利になります。

最初に、そして最も広く、YiiアプリケーションはActiveRecordを非常に頻繁に使用するため、設計上の考慮事項は、複雑なSQLクエリを作成する人間ではなく、ActiveRecordの使用の最適化を中心に展開します。実際、これらの設計ノートの多くは、SQLに適したスキーマを作成するためのベストプラクティスと直接矛盾しています。

しかし、これらのベストプラクティスの大部分は、他の人が読み取って理解できるコードを作成することに関するものです。ネーミングは意味を伝えますが、一貫性のない規則によって、従うのがはるかに難しくなります。

これは、フォーラムや#yiiチャンネルで助けを求めている場合に特に当てはまります。良い意味を反映しない奇妙な名前を使用すると、コードが何をしているのかを明確にする多くの質問が得られます。あなたの実際の問題。

一貫性が重要です。

ただし、これらはルールではなく単なるガイドラインであり、従わなくてもコードは機能します。しかし、それらを採用すれば、より簡単な道が開けます。

補足

ActiveRecordは、Yiiに含まれているデフォルトのO/Rマッパーです。Mojoliciousスタートップの場合は、PerlのDBIあるいはO/Rマッパーと読み替えてください。

データベーステーブルに複数ではなく単数で名前を付ける

SQLテーブルは多くのものを保持していると考えられますが、モデルはそれらの1つに過ぎません。$model = new Comments()を見るのは奇妙に思えます。関係を定義するときなどに、この奇妙さが再び現れます。

テーブルを「コメントたち(comments)」ではなく「コメント(comment)」と呼び、「請求書たち(invoices)」ではなく「請求書(invoice)」と呼んでください。デルクラス名(コメント、請求書)にそのまま反映します。

DBスキーマを絶対に変更できない場合は、少なくともYiiモデルクラス名を変更して適切なケースを反映しますが、コードに余分なコメントを追加して、ユーザーにこの不一致を意識させます。

補足

要点は、テーブル名を単数形にするということです。

comment # OK
comments # Not OK

invoice # OK
invoices # Not OK

フィールド名の前にDBテーブル名を追加しないでください

この方法は、従来のSQLスキーマ設計では一般的ですが、ActiveRecordを使用する場合は面倒です。カテゴリテーブルの例です。

-- NO                              -- YES
create table category (            create table category(
    category_id    INTEGER ...,        id    INTEGER ...,
    category_name  VARCHAR ...,        name  VARCHAR ...,
    category_value INTEGER             value INTEGER
);                                 );
<?php
$category = new Category();
// YUCK                            // BETTER
$category->category_id             $category->id
$category->category_name           $category->name
$category->category_value          $category->value

「長い」方法で行うと、手作りのSQLクエリが少し読みやすくなりますが、ActiveRecordでの使用はあまり便利ではありません。

補足

要点は、フィールド名の前に、テーブル名を付けないということです。

モデルクラス名にテーブルプレフィックスを含めないでください

Yiiはテーブルプレフィックスの概念をサポートしています。これは、すべてのアプリケーションが単一のデータベースを共有する共有ホスティング環境で役立ちます。ブログのテーブル名にblog_を、タイムキーピングアプリケーションのテーブル名にtime_を付けるなどして、すべて競合することなく同じデータベースに格納できます。

プレフィックスtbl_は、多くのチュートリアルやサンプルでよく見られます。

ただし、競合を回避する必要性は同じではないため、クラスにこれらのプレフィックスを含めることはできません。ブログアプリケーションは時間管理アプリケーションとは異なります。

class TblComment extends CActiveRecord {       // NO
class Comment extends CActiveRecord {          // YES

コードの至る所に接頭辞を見るのは非常に気が散ります。

補足

これは、ActiveRecordのクラスについての説明なので、もし仮に、Perlでテーブル名に対応するモデル名をつける場合に、テーブルプレフィックスを含めないようにするという意味です。

テーブルのID列に「id」という名前を付けてください

多くのテーブルには、独自の独立した単一列の一意のプライマリキーがあり(int NOT NULL AUTO_INCREMENT PRIMARY KEYが一般的な例です)、id(commentidまたはpostidではない)という名前の場合、少しスムーズに動作します。

Yiiはデータベーススキーマを読み取って主キーを特定しますが、システムの他の部分は従うことができず、idであるキーに明示的に依存することはできません。

例:CArrayDataProviderはキーがidであると想定しています。keyField属性でオーバーライドできますが、最初から、それを必要とすることを避ける方が良いです。

たとえば、テーブルに複数列のプライマリキーがある場合、またはテーブルのプライマリキーが別のテーブルのIDに対する外部キーである場合、このルールは適用されません。

補足

要点は、行を識別するIDは、idという名前にしましょうということです。

意味のある主キー名を避ける

古典的な設計ミスは、実際の意味を持つ主キーを持つテーブルを作成することです。この例では、ユーザーテーブルはユーザー名を主キーにします。

-- こんな風にはしないで
CREATE TABLE user (
    name   VARCHAR(16) PRIMARY KEY,  -- bad idea
    email  VARCHAR...
    ...
)

これには2つの難点があります。

このフィールドを4バイトの整数ではなく16文字で構成しているため、他のフィールドからこのフィールドを参照するのははるかに効率的です。これは、多くの参照がある大規模なアプリケーションで実際のパフォーマンスの問題になる可能性があります。

このシステムで外部キー制約が有効になっている場合、ユーザーがユーザー名を変更することは非常に困難です。テーブルフィールドとすべての参照を同時に変更する必要があり、それが可能であれば費用がかかります。

はるかに良いのは、不可欠な主キーを作成し、名前を一意にすることです。

-- much better
CREATE TABLE user (
   id     INTEGER PRIMARY KEY AUTO_INCREMENT,
   name   VARCHAR(32) NOT NULL UNIQUE,
   email  ...
   ...
);

この方法では、個人のユーザー名を変更すると、この1つのレコードのみが更新されます。

補足

要点は、意味がなく行を識別するためだけのidを持たせて、それをプライマリーキーで、オートインクリメントにしましょうということです。意味のある主キー(この例ではname)には、ユニーク制約を設定します。

データベーススキーマで外部キー関係を定義する

ほとんどのデータベースでは、データベースがテーブル間の関係を定義できるため、このフィールドには他のテーブルのプライマリキーを指すIDが保持されます。これらは外部キーであり、他の誰かがそれを指している場合に行を削除できないようにすることで、参照整合性を提供します。

MySQLのInnoDBは外部キー制約を強制します。MyISAMではそれらを定義できますが、強制しません。 Yiiはスキーマからこれらの関係を読み取る方法を知っており、Gii / Giixツールは自動的に関係を作成します。

しかし、Yiiがそれらを考慮しなくても、外部キーはデータベースの参照整合性を維持するための重要な部分です。それらについて学ぶ方法に関する多くのチュートリアルがウェブ上にあります。

補足

要点は、もし、データベーススキーマで外部キー制約をつける場合は、O/Rマッパー側ではなくって、データベース側でつけてくださいという意味です。

「id」で終わる外部キーフィールドに名前を付けてる

前のメモに関連して、ユーザーのIDを保持するフィールドがある場合、userではなくuseridフィールドを呼び出します。これは、テーブルに含めるすべての外部キーについて、ほぼ確実にリレーションを定義することを望むためです。

Yiiでは、クラス変数、DBフィールド、仮想属性、リレーションはすべて単一のネームスペースを共有するため、$model->userをテーブルの外部キーとリレーションの両方にすることはできません。

FKユーザーIDを呼び出すことにより、$model->userのBELONGS_TO関係が自然かつ簡単に形成されます。

class Post extends CActiveRecord {

   public function relations()
   {
       return array(
          'user' => array(self::BELONGS_TO, 'User', 'userid')
       );
   }

注:idの代わりにIdまたは_idを使用することを好む人もいます。これは厳密には個人的な好みの問題ですが、一貫している必要があります。

補足

要点は、外部キーの名前は、テーブル名の後ろに「id」または「Id」または「_id」をつけて、命名規則を一貫しましょうということです。Mojoliciousスタートアップでは、外部キーの名前として「_id」をテーブル名の後ろにつける方法を使うことにします。

単数/複数の性質を反映する名前関係を行う

一貫性というテーマを継続し、コードを他の人が読みやすくするために、関係は名前に単数/複数を反映する必要があります。

HAS_ONE - 単一のモデルを返します:singular
BELONGS_TO - 単一のモデルを返します:singular
HAS_MANY - モデルの配列を返します:複数形
MANY_MANY - モデルの配列を返します:複数形

配列を返すリレーションの場合、モデルは1つだけかもしれませんが、配列であるという事実が複数名を保証することに注意してください。

リレーションが配列を返すのかモデルを返すのかを調べるだけで、いつでも通知できるはずです。

$model->post
$model->comments
$model->author
$model->members

調べる必要がある場合、コードの読み取りと保守がはるかに難しくなります。

補足

これは、ActiveRecordの1対1、1対多、多対1、多対多を定義するときのメソッド名の命名規則についての話です。

もしPerlのO/Rマッパーが、類似の機能を持っていた場合は、参考にできます。

関連情報