🧩

テーブル設計: statusカラムから生じる技術的負債とその解決策②

2024/05/17に公開

概要

https://zenn.dev/rsugi/articles/8a939d7bd2f60a
の解説記事です。

実際にありそうなユースケースで説明しています

対象読者

  • テーブル設計を学んでいる方
  • 技術的負債を解消したい方

いいね!してね

この記事の事例は必要に応じて今後追記していく予定です!
「新しい事例が知りたい」「他の事例も知りたい」と思った人は、ぜひこの記事にいいね👍してください。筆者のモチベーションにつながります!

それでは以下が本編です。

ユースケース

下記のような会員(member)のテーブルを例にしたい。

会員のライフサイクルは下記のような流れで変わると想定できる。
1 会員未認証(pending_activation)
2 会員認証完了(verified)
3 会員情報入力完了(active)
4 会員退会(resigned)

また、上記の他に、システム・管理者権限で操作できるものとして下記の状態がある。
5 会員失効(disabled)
6 会員強制退会(banned)
7 会員復元(restored)

その他ライフサイクルが変わるごとにレコードを作成するアクティビティテーブル(status_activities)がある。

上記のライフサイクルについて説明していく。

diagram

説明すること

  • Writeフロー
  • Readフロー

Writeフロー

会員未認証(pending_activation)

firebaseのメールアドレスログインのフローを想定してほしい。
ユーザーが、会員登録フォームにメールアドレス・パスワードを入力して送信する。
入力したメールアドレス宛に認証用のメールが送信される(未認証)


Writeフローの例1

会員認証完了(verified)

ユーザーは、認証用のメール内のリンクをクリックして認証を完了させた。
※認証完了時にコールバックでWEBサイトの特定のURLをGETする


Writeフローの例2

会員情報入力完了(active)

アドレス認証完了したのち、会員情報入力画面を表示させる。
ユーザーは、必須入力項目のみ登録する。
※入力項目はhas_oneでmember_accountテーブルを用意する。今回は割愛


Writeフローの例3

その他

割愛。必要であれば追記します

Readフロー

ログインユーザーの判定

member_status_activitiesテーブルを見ると、上記のWriteフローの履歴が全て存在する。

member_status_activities

id member_id status created_at
xxxxx-xxxxx-00001 aaaaa-aaaaa-aaaaa PENDING_VERIFICATION 2024-05-16 22:00:00
xxxxx-xxxxx-00002 aaaaa-aaaaa-aaaaa VERIFIED 2024-05-16 22:05:00
xxxxx-xxxxx-00003 aaaaa-aaaaa-aaaaa ACTIVE 2024-05-17 10:00:00

ログインメンバーかどうか判定したいなど、最後のステータスを取得したいケースが想定される。

その場合は、member_idごとに最後のステータスのみ表示した viewテーブル(member_status_activity_latest)それに相当するレポジトリ層を用意する。

member_status_activity_latest

id member_id status created_at
xxxxx-xxxxx-00003 aaaaa-aaaaa-aaaaa ACTIVE 2024-05-18 03:00:00

このテーブルからmember_idAVTIVEという条件でレコードを取得できたとき、ログインユーザーであると判定できる。


Readフローの例1

まとめ

ステータスの追加、削除、順序入替えをしたくなったときに対応しやすいテーブル設計になった!

主キーで関連しているためデータ量が増えてもクエリコストが小さいと思う!

この記事が参考になった方は、ぜひこの記事にいいね👍してください。筆者のモチベーションにつながります!また、質問や疑問点があればコメントください

Discussion