実装ベースで学ぶ　データベーステーブル設計



# 1. 概要

- これまでRDBに触れてはきていたが、実際にシステム開発の初期フェーズで行うような`エンティティの抽出`や`エンティティの定義`、`正規化`といった経験をすることがなかった。
- 今回ポートフォリオを作成するにあたり、場当たり的に考えてテーブルを作成するのではなく、各フェーズで検討することや思考法を経験者のものを真似ながらやってみる。

# 2. この記事を参照するにあたっての前提知識

特に前提知識がなくていいようにはなっていますが、非エンジニアの方にとっては聴き馴染みのない言葉が出てくるかもしれません。
ここでの話は、最後まで実装非依存な内容になるため、特に何らかのフレームワークを使うこともありません。
ただし、RDBの基礎知識くらいはあったほうがいいかもしれません。
RDBの基礎ってなんぞやという方は下記の書籍がおすすめです。

https://www.amazon.co.jp/dp/B01HD5VWWO/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

# 3. 早速実装と行きたいけど。。。その前に【題材の紹介】

今回説明するために使用するのは、私がポートフォリオとして作成している「ShareFitTube」(ネーミングセンスのなさよ。。。)のテーブルです。
自分で最初から実装するのは初なので、どうせなら自分の作品にしようと思いました。
また、フェーズごとに章立てて説明していく予定です。
解説部分はかなり参考URLの内容とかぶる部分が多いため、解説に関してはURLの内容を参照するほうが早いかもです。
各章末に自分のアプリではどう実装したのかを記載しています。
また、以降では私のポートフォリオのことは「PF」と呼称することとします。

### 参考資料

以下のサイトですが、控えめに言ってめっちゃいいです。
テーブル設計の論理設計では

1. エンティティの抽出
2. エンティティの定義
3. 正規化
4. ER図の作成

という流れになるのですが、この中でも特に`1.`と`2.`は書籍などでも語られることの少ないところで実装は個人によりけりなところがあるような気がします。
ですがここで十分に検討できていないと結局ER図を作成したとにエンティティが足りておらず、再度設計からやり直し。。。のようなことになりかねません。
そのような大事ではあるけど書籍などでうまく言語化されていないことに対して以下のサイトで言及されているので、一読の価値ありです。 [^1]

https://eh-career.com/engineerhub/entry/2018/06/22/110000/

# 4. フェーズ１　エンティティの抽出

## 4.1. エンティティとは

- ある共通項をもったデータの集合体のこと
- 大別すると**物理的なエンティティ**(ユーザー、商品など)と**概念的なエンティティ**(購入履歴、プロフィールなど)の二つがある

テーブル設計を行うに際して、最初からER図やテーブルの項目から考えるのではなく、開発するサービスにでてくるエンティティを抽出することが最初の一歩となる。

## 4.2. ポイント

### 4.2.1. エンティティは大きいものから抽出すること

最初はサービスにでてくる登場人物や主要な概念を大きな粒度のエンティティとして抽出する。
この前にエンティティの中の項目まで細かく検討すると、それが不要になった時のサンクコストがでてきてしまう。
まずは粒度を揃えるために粗い(粒度の多い)エンティティを抽出すること。

#### この段階でのPF

```
物理的なエンティティ
・動画、ユーザー
```

のみです。正直PFのサービス対象領域が狭いので最初に登場する物理的なエンティティはこんなもんです。

### 4.2.2. エンティティ同士でどのような状態変化、やりとりがなされるか考える

粒度の揃ったエンティティを抽出した後は、それらが互いにどのように作用し合うかを検討していくことになる。
この時、ただ考えるとなると手がつかないので、一つの思考法として以下を思考してみる。

#### システムがどう使われるのかを脳内でシミュレートする

最初に開発するにあたって、サービスを考える背景でなんとなく

- ユーザーはこういう場面、こういう事象に「痛み」[^2]を感じている
- それにたいしてこういうアプローチをしたら解決できる

などということを施行していたと思うので、ある程度サービスのユースケース等は頭にあると思う。
それを書き出して、それを実現するために必要なデータを考えていけばいいことになる。

#### この段階でのPF

```
・ユーザーは任意の動画を特定の条件の中から自由に選択して登録できる。
　→「条件」テーブルが必要。この中には動画をカテゴライズする条件を表す項目が含まれる。
・ユーザーは動画を評価できる必要がある。
　→「評価」テーブルが必要。このテーブルはユーザーIDと動画IDを含んだ単一動画に対する単一ユーザーの評価を行うテーブルとなる。
・ユーザーは動画をお気に入りに登録できる
　→「お気に入り」テーブル何必要。このテーブルは上記同様にユーザーIDと動画IDを含んだ単一動画に対する単一ユーザーのお気に入りを管理する。
・ユーザーはログインをすることができる
　→ログイン状態を管理する項目が必要(ユーザーテーブルに入れるかどうかは別で検討)
・ユーザーはプロフィールを編集することができる
　→「プロフィール」テーブル、またはユーザーテーブル内にプロフィール項目を追加する必要がある

物理的なエンティティ
・動画、ユーザー
概念的なエンティティ
・動画カテゴライズ条件、ユーザーの動画評価、ユーザーのお気に入り動画、ユーザープロフィール
```

簡易的にサービスのユースケースから必要なデータなどがぼんやりと見えてきている。実際にどういうテーブルにどういう項目を持つかなどについてはここで検討することではないので検討していない。

# 5. エンティティの定義

エンティティに必要なカラムを洗い出していく作業。
RDBにおいてエンティティはテーブルとして表現し、必要な項目＝カラムとして定義することになる。
この時も必要なポイントの中には

#### ユースケースのシミュレーション

になる。
また、

#### 画面にどんな内容が表示されている必要があるのか

というアプローチも有効になる。
システムの中で、画面に表示されている内容はある程度DBに保存されているテーブルのカラムの内容になるので、画面に必要な項目をテーブルのカラムとして考えるもあり。

#### この段階でのPF

```
ユーザーテーブルに必要な項目
・ユーザーID、メールアドレス、パスワード(暗号化後)、プロフィール画像パス、自己紹介文
動画テーブルに必要な項目
・動画ID、動画名、動画時間、動画URI、運動強度、使用目的、部位、広告種別
動画評価に必要な項目
・評価レート、評価文
```

それぞれのエンティティ(=テーブル)で必要になる情報を大体で分析している。
この時、正規化等には触れていない点がポイント。
正規化はそれ自体が目的ではなく、データの整合性や不整合を防ぐために行う手段である点に注意する。

# 6. 正規化

DML言語を使用して、テーブルのレコードに対して処理を行う際に、データの不整合が起こってしまうようなデータに対しては原則正規化を行うべき、
例えばPFで言うと、

・動画テーブルとカテゴリテーブルを一纏めにしてしまうと、動画とカテゴリという本来独立して存在しておかないといけないエンティティが纏まっていることになる。
これによって、例えば特定の動画が削除された時、削除されるレコードのカテゴリが一つしかなければ、それも削除されることになり、動画削除という本来は関連のないレコードの操作でカテゴリの情報も一緒に失われてしまうことになる。
だからと言って整合性のみを重視して正規化をしすぎると、テーブル間のリレーションが増えすぎることで複雑になってしまいます。
そこは、作成するサービスの成長性や規模にあわせて設計するのが必要です。

#### 最終的な成果物

![2610F511-919A-4776-930F-E8CA016BC031.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/948210/eb9f5e99-cbce-3d63-d7c9-a8175d77909b.png)


エンティティの定義で行なっていたエンティティから何個か増えてますがw
SNS機能を実装する際に必要なテーブルを追加しています。
後は基本的にエンティティの定義で行なっている内容をER図で示しているような感じです。
ER図の書き方や、正規化の手順はこの記事では詳しくは解説しませんので各自で調べてみてください。


# 7. まとめ

今回は自分のPFを題材にして、実際にサービスの構想段階からテーブル定義、正規化までを一つの記事を参考にしながら実装する工程を記事にしてみました。
参考サイトの内容が良質すぎて公開するか迷うくらいなのですがw
RDBに慣れ親しんでいないとここの実装ベースの話については理解が追いつかないと思いますし、私も実際にサービスをイチから開発するのは初なのでこの経験は貴重でした。
今後も作成するPFのテーブル定義などは変化していくことになるとは思いますが、とりあえずの叩き台を作ることができたのでこれにて終わりにしようと思います。

長文になってすみません。
ご覧いただきありがとうございました。


[^1]: 非常に残念なのですが、該当のサイトは後半の正規化〜についてはユーザー登録をしないと参照できないようになっております。弊記事を参照して興味が湧きましたら、是非登録して最後まで見てみてください。

[^2]: 「面倒に思っていること」と解釈してもいいです。サービスの価値としてユーザーが対象事象にたいして苦痛を感じており、それをサービスを利用することで解決することで初めて利害関係が一致し、サービスの利用につながります。