KINTO Tech Blog
Development

サブスクサイトリニューアルでテーブルを再設計する際に気をつけたこと

Cover Image for サブスクサイトリニューアルでテーブルを再設計する際に気をつけたこと

はじめに

KINTOテクノロジーズの新車サブスクグループに所属している森本です。バックエンドエンジニアとして日々開発しています。

2022年度のアドベントカレンダーでは、社内の若手メンバーでGraphQLの勉強会を実施したことについて書きました。
若手メンバーで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:社員テーブルでレコードを一意に特定するID
  • employee_id:社員を一意に特定するID
  • mail_address:メールアドレス
  • pref/prefecture:都道府県
  • group_and_role/grouprole:所属グループとロール
  • delete_flag/is_deleted:そのレコードが削除されているかどうか

4つの見直しポイント

  1. カラムに略称を使用しない
  2. 値を数字に置き換えない
  3. 1つのカラムに複数の意味をもたせない
  4. フラグ系のカラムは_flagと命名しない

1. カラムに略称を使用しない

カラム名prefのように、カラム名を省略しないようにしました。

これが都道府県を表すことは何となく理解できるでしょう。
しかし、これをドキュメントやソースコードで使用する場合、prefprfなどの表記揺れが発生する可能性が高くなります。また、そもそも何の略称かわからなくなってしまう場合もあります。

そのため略称は使用せず、長くても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つの定義があった場合を想定します。

  1. HR_Manager
  2. HR_Staff
  3. Development_Manager
  4. Development_Staff

仮にDevelopmentグループの名称をNewDevelopmentへ変更しようとなった場合、更新SQLの条件が複雑になります。

  1. HR_Manager
  2. HR_Staff
  3. Development_Manager → NewDevelopment_Manager
  4. Development_Staff → NewDevelopment_Staff

また検索やソートをする観点でも問題があります。検索のクエリが複雑になったり、ソートをする場合も_(アンダースコア)以降で区切るという手間が必要になってきます。もちろん、可読性も下がります。

そのためサイトリニューアルする際には、1つのカラムは1つの意味を持たせるように分離する作業を行いました。

4. フラグ系のカラムは_flagと命名しない

delete_flagは削除したことを表すカラムだと理解できます。しかしtrueは削除済を示しているかどうか迷ってしまいます。

そのためis_deletedのようにbe動詞+過去分詞の形式にしました。そうすることでtrueは削除されたこと、falseは削除されていないことを理解できます。

ここで大切なことは、カラム名と中身の値の認識に相違がないことです。
例えばis_deletedは、社員情報に更新があった場合に古いレコードを論理削除するためのカラムとなります。

  • true:削除済み
  • false:未削除

フラグ系のカラムでtrueかfalse以外の第3の状態が出てきた場合は、フラグ系のカラムから変更すべきです。

改善し続ける

テーブル設計は1回だけではなく、リリースする数ヶ月前まで継続して行いました。

さまざまな種類のテストが行われる中、テーブルを変更することは大きな影響を持ちます。開発チーム内の修正だけでなく、場合によってはバックエンド・フロントエンドを結合したテストを再実施しなければなりません。
バックエンドのプログラムとテーブル間だけで修正を完結することもできましたが、リニューアルするにあたってはAPIのインターフェースまでも一貫して綺麗にしたいと考え、APIを利用する各チームと連携して足並みを揃えて修正しました。
プロジェクト全体で、目先の大変さより、リニューアルする目的を意識していたことが共通認識にあったと思います。

またバックエンドチーム内で改善事項を積極的に伝え合える雰囲気もありました。テーブル設計だけではなく、開発全体で改善し続けられたことが、リニューアルプロジェクトを成功に導くことができた1つの要因だと考えています。

さいごに

実際にはテーブルの構成自体の変更や、使用していないカラムの削除など、大きな構成変更をしました。

これは入社して初めて携わったタスクで、サブスクサイトの構成や機能を100%理解できていない状態で設計することとなりました。開発途中で動作確認をして永続化できていない値に気づいたり、テストなどで指摘があって初めて定義が誤っていることを知ったりすることがありました。

リリースの終わった今でさえ、
「なぜこのような命名をしてしまったのか?」
「ここのテーブルは分離しておくべきだったかも…」
と思うことが多くあります。

しかしながら、チームメンバーをはじめプロジェクト全体でテーブル変更を快く受けれてくださった方々のおかげで無事リリースすることができました。

今後も、わかりやすいテーブルを引き続き目指して改善していきます。

Facebook

関連記事 | Related Posts

Kairi Watanabe
Kairi Watanabe
Cover Image for 中途入社者へオリエン研修を実施するべき理由と4つのアプローチ

中途入社者へオリエン研修を実施するべき理由と4つのアプローチ

Yuji.M
Yuji.M
Cover Image for 若手メンバーでGraphQLについて勉強会をしてみた

若手メンバーでGraphQLについて勉強会をしてみた

yuki.n
yuki.n
Cover Image for 12月・1月入社メンバー紹介

12月・1月入社メンバー紹介

Y.Suzuki
Y.Suzuki
Cover Image for 11月入社メンバー紹介

11月入社メンバー紹介

Maya.S
Maya.S
Cover Image for 10月入社メンバー紹介

10月入社メンバー紹介

Cover Image for プロジェクト推進グループ紹介

プロジェクト推進グループ紹介

We are hiring!

【フロントエンドエンジニア】新車サブスク開発G/東京

新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。​業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、TOYOTAのクルマのサブスクリプションサービス『KINTO ONE』のWebサイトの開発、運用を行っていただきます。

【フロントエンドエンジニア(コンテンツ開発)】新車サブスク開発G/東京

新車サブスク開発グループについてTOYOTAのクルマのサブスクリプションサービスである『 KINTO ONE 』のWebサイトの開発、運用をしています。​業務内容トヨタグループの金融、モビリティサービスの内製開発組織である同社にて、自社サービスである、TOYOTAのクルマのサブスクリプションサービス『KINTO ONE』のWebサイトの開発、運用を行っていただきます。