サブスクサイトリニューアルでテーブルを再設計する際に気をつけたこと
はじめに
KINTOテクノロジーズの新車サブスクグループに所属している森本です。バックエンドエンジニアとして日々開発しています。
2022年度のアドベントカレンダーでは、社内の若手メンバーでGraphQLの勉強会を実施したことについて書きました。
今回は、入社した2021年8月から2023年8月のリリースまでの2年間携わった、サブスクサイト(KINTO ONE)のリニューアルについて記載します。その中でも、入社して初めての仕事であるテーブル設計の見直しについて記載します。
テーブル設計で盛り込んだこと
以下の表はリニューアルする前後のテーブルのイメージです。実際に業務で使用しているテーブルではありません。
このテーブルは社員情報を格納するもので、更新があった場合はそのレコードを論理削除し、新しいレコードを追加することで履歴管理できるようになっています。
※レコードを削除せず、フラグを立てることで削除扱いにすることを論理削除と呼びます。大切な値の更新履歴を追うことができるというメリットがあります。
リニューアル前
id | employee_id | mail_address | pref | group_and_role | delete_flag |
---|---|---|---|---|---|
1 | E-001 | email1@XX.XX | 23 | HR_Manager | false |
2 | E-002 | email2@XX.XX | 25 | HR_Staff | true |
3 | E-002 | email2@XX.XX | 14 | Development_Manager | false |
4 | E-003 | email3@XX.XX | 1 | Development_Staff | false |
リニューアル後
id | employee_id | mail_address | prefecture | group | staff | is_deleted |
---|---|---|---|---|---|---|
1 | E-001 | email1@XX.XX | AICHI | HR | Manager | false |
2 | E-002 | email2@XX.XX | SHIGA | HR | Staff | true |
3 | E-002 | email2@XX.XX | KANAGAWA | Development | Manager | false |
4 | E-003 | email3@XX.XX | HOKKAIDAO | Development | Staff | false |
各カラムは以下の情報を表します。
id
:社員テーブルでレコードを一意に特定するIDemployee_id
:社員を一意に特定するIDmail_address
:メールアドレスpref
/prefecture
:都道府県group_and_role
/group
・role
:所属グループとロールdelete_flag
/is_deleted
:そのレコードが削除されているかどうか
4つの見直しポイント
- カラムに略称を使用しない
- 値を数字に置き換えない
- 1つのカラムに複数の意味をもたせない
- フラグ系のカラムは
_flag
と命名しない
1. カラムに略称を使用しない
カラム名pref
のように、カラム名を省略しないようにしました。
これが都道府県を表すことは何となく理解できるでしょう。
しかし、これをドキュメントやソースコードで使用する場合、pref
やprf
などの表記揺れが発生する可能性が高くなります。また、そもそも何の略称かわからなくなってしまう場合もあります。
そのため略称は使用せず、長くてもprefecture
のように表記するようにしました。
2. 値を数字に置き換えない
リニューアル前のテーブルを見ると、pref
の値として23が入っています。47あるうちの都道府県のどこかを表すと推測できますが、23番目は一体どこなのでしょうか。
直感的でないため値が何を表しているかが分かりません。値を見るたびに数字と都道府県の組み合わせを参照する必要があり、可読性が下がります。また誤りに気づきにくくなります。そのためAICHI
のように、都道府県をそのまま格納するようにしました。
そして不正な値が格納されている場合は、プログラムで読み込み時にエラーになるので気づくことができるというメリットもあります。
言語はJava、O/RマッパーはJPAを使用する場合を例として挙げます。prefecture
のenumクラスを以下のように定義し、Userエンティティではその型を使用することでAICHIA
のような不正な値があればエラーになり、気づくことができるというメリットもあります。
public enum Prefecture {
HOKKAIDO("北海道"),
.
.
.
AICHI("愛知県"),
.
.
.
OKINAWA("沖縄県");
private String value;
}
@Entity
public class Employee {
/** ID */
@Id
private Long id;
.
.
.
/** 都道府県 */
@Enumerated(EnumType.STRING)
@Column
private Prefecture prefecture;
.
.
.
}
マッピングできない場合に、以下のようなExceptionが発生します。
java.lang.IllegalArgumentException: No enum constant com.example.demo.values.Prefecture.AICHIA
3. 1つのカラムに複数の意味をもたせない
リニューアル前のgroup_and_role
ようなカラムは、1つのカラムに所属グループとロールの2つの情報を持っていました。一見すると問題ないように見えますが、値を追加・削除・変更する場合の柔軟性が下がります。
元々以下のような4つの定義があった場合を想定します。
- HR_Manager
- HR_Staff
- Development_Manager
- Development_Staff
仮にDevelopment
グループの名称をNewDevelopment
へ変更しようとなった場合、更新SQLの条件が複雑になります。
- HR_Manager
- HR_Staff
- Development_Manager → NewDevelopment_Manager
- Development_Staff → NewDevelopment_Staff
また検索やソートをする観点でも問題があります。検索のクエリが複雑になったり、ソートをする場合も_(アンダースコア)以降で区切るという手間が必要になってきます。もちろん、可読性も下がります。
そのためサイトリニューアルする際には、1つのカラムは1つの意味を持たせるように分離する作業を行いました。
_flag
と命名しない
4. フラグ系のカラムはdelete_flag
は削除したことを表すカラムだと理解できます。しかしtrueは削除済を示しているかどうか迷ってしまいます。
そのためis_deleted
のようにbe動詞+過去分詞の形式にしました。そうすることでtrueは削除されたこと、falseは削除されていないことを理解できます。
ここで大切なことは、カラム名と中身の値の認識に相違がないことです。
例えばis_deleted
は、社員情報に更新があった場合に古いレコードを論理削除するためのカラムとなります。
- true:削除済み
- false:未削除
フラグ系のカラムでtrueかfalse以外の第3の状態が出てきた場合は、フラグ系のカラムから変更すべきです。
改善し続ける
テーブル設計は1回だけではなく、リリースする数ヶ月前まで継続して行いました。
さまざまな種類のテストが行われる中、テーブルを変更することは大きな影響を持ちます。開発チーム内の修正だけでなく、場合によってはバックエンド・フロントエンドを結合したテストを再実施しなければなりません。
バックエンドのプログラムとテーブル間だけで修正を完結することもできましたが、リニューアルするにあたってはAPIのインターフェースまでも一貫して綺麗にしたいと考え、APIを利用する各チームと連携して足並みを揃えて修正しました。
プロジェクト全体で、目先の大変さより、リニューアルする目的を意識していたことが共通認識にあったと思います。
またバックエンドチーム内で改善事項を積極的に伝え合える雰囲気もありました。テーブル設計だけではなく、開発全体で改善し続けられたことが、リニューアルプロジェクトを成功に導くことができた1つの要因だと考えています。
さいごに
実際にはテーブルの構成自体の変更や、使用していないカラムの削除など、大きな構成変更をしました。
これは入社して初めて携わったタスクで、サブスクサイトの構成や機能を100%理解できていない状態で設計することとなりました。開発途中で動作確認をして永続化できていない値に気づいたり、テストなどで指摘があって初めて定義が誤っていることを知ったりすることがありました。
リリースの終わった今でさえ、
「なぜこのような命名をしてしまったのか?」
「ここのテーブルは分離しておくべきだったかも…」
と思うことが多くあります。
しかしながら、チームメンバーをはじめプロジェクト全体でテーブル変更を快く受けれてくださった方々のおかげで無事リリースすることができました。
今後も、わかりやすいテーブルを引き続き目指して改善していきます。
関連記事 | Related Posts
We are hiring!
【フロントエンドエンジニア】新車サブスク開発G/東京
新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、TOYOTAのクルマのサブスクリプションサービス『KINTO ONE』のWebサイトの開発、運用を行っていただきます。
【フロントエンドエンジニア(コンテンツ開発)】新車サブスク開発G/東京
新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、クルマのサブスクリプションサービス『KINTO ONE』のWebサイトコンテンツの開発・運用業務を担っていただきます。