HowTelevision Advent Calendar 2025 15日目の記事です
バンド活動が落ち着いて新しいことに挑戦すべく、大学数学を学ぶため高校数学を勉強している @imaharuTech です
入門問題精講という神参考書に日々感謝しています
本記事は、mond で開発した「お題募集」のDB設計について紹介します
概要
mondは、Q&Aサービスです
お題付きリンクをSNSシェアしたいという要望が上がりました
業務フローは以下の通りです
- お題投稿者が「お題付きリンクコピー」ボタンを押下
- 「SNSシェア」ボタンを押下
- SNS投稿に1でコピーしたリンクを貼り付け
- 投稿閲覧者がリンクを押下
- 投稿閲覧者がお題投稿者に質問
大まかな要件は以下の通りです
- お題の種類は二つ
- mond 提供
- ユーザー自由記述
- mond 提供お題は、一つにつき複数言語
- ex. 匿名メッセージを送って! 、send me anonymous messages!
- mond 提供お題は、並び順あり


左: mond 提供お題 右: ユーザー自由記述
採用した設計
各テーブルについて説明します
前提として、SuffixのMはマスターテーブルです(筆者は、レビュー時のみER図にMをつけます)
- userTopicPromotion
- 後述する質問促進の抽象テーブル
- topicPromotionByUser
- ユーザー自由記述お題を保存
- ユーザーは、複数の自由記述お題を作成可能
- userTopicPromotionと同トランザクションで作成
- topicPromotionByAdmin
- mond 提供お題を保存
- userTopicPromotionと同トランザクションで作成

設計時に考えたこと
質問促進について
当初、アプリ共有リンクを作りたいという要望でした。
これをモデリングすると上手く抽象化できていない感覚がありました。
そこで機能の目的から言語化しようと試みました。
言語化する中で、実現したいことは質問促進であることを発掘しました。
質問促進(TopicPromotion)という概念を取り入れてると、しっくりくるモデリングになりました。
モデリングが上手くいかない時は機能の目的から考えると良いことを再認識できました。
イミュータブル、non-nullable を崩すべきか
データ更新やNull 前提でモデリング、DB設計すると重要な概念を取り逃がす可能性があります。
その対策として、私は初期段階ではイミュータブルかつnon-nullableで設計しています。
しかし、全ての箇所でイミュータブルかつnon-nullableを採用すると実装が複雑になってしまうことがあります。
今回のケースだと、イミュータブルかつnon-nullableだとtopicPromotionByUserはDraft, Published を別々のテーブルで管理します。
テーブル分けても複雑さが増すだけなので、publshed_at を nullable にしアプリケーション側でDraft, Published を管理することにしました。
いつ崩すべきかについてですが、私が気にしているのは、他のテーブルとリレーションを結ぶ際に、テーブルを分けておくことでモデルを見たときに何をやりたいのかがわかりやすくなるかどうかという点です。
まとめ
実際の業務で行ったDB設計について紹介しました。
必要なモデルを抽出する一つの方法として、機能の目的から考える。
モデリングをそのまま実装するわけではない。
をお伝えしました。
誰かの参考になれば嬉しいです。