XAPPSXAPPS
← Blog
·3分で読めます

一問一答アプリの問題データを、どう設計したか

#個人開発#設計#データ

マナビポータルという、資格試験の一問一答アプリを作っています。このアプリでいちばん頭を悩ませたのが、「問題データの設計」でした。この記事では、最初の素朴な設計から、運用しながらどう育っていったかを、具体的なテーブルの形とともに書いてみます。

最初は「問題と答え」だけだった

作り始めたころは、シンプルに考えていました。問題文と、その答え。最低限これがあれば一問一答は成立する、と。最初のテーブルは、ほとんどこれだけでした。

create table questions (
  id      bigint generated always as identity primary key,
  body    text not null,   -- 問題文
  answer  text not null    -- 答え
);

ところが、実際に運用してみると、それだけでは足りないことがすぐに分かってきました。

運用して見えてきた「必要な情報」

使っていくうちに、こんな情報が欲しくなっていきました。

  • 解説:答えだけでなく、なぜそうなるのかを示したい
  • 難易度:やさしい問題と難しい問題を分けたい
  • カテゴリ:分野ごとに出し分けたい
  • 出典・改訂日:情報が古くなっていないか管理したい

結局、何度かデータの形を見直し、最終的にはこんな形に落ち着きました。

create table questions (
  id          bigint generated always as identity primary key,
  category_id bigint references categories(id),
  body        text not null,
  answer      text not null,
  explanation text,                 -- 解説
  difficulty  int default 2,        -- 1=易 2=普通 3=難
  source      text,                 -- 出典
  revised_at  date,                 -- 改訂日
  created_at  timestamptz default now()
);

カテゴリは別テーブルに切り出して category_id で参照する形にしました。最初から文字列で category を持たせていると、表記ゆれ(「基本情報」「基本情報技術者」など)で泣くことになるからです。

「間違えた問題」をどう持つか

もう一つ悩んだのが、ユーザーの解答履歴です。「間違えた問題だけ復習したい」を実現するには、誰がどの問題をどう答えたかを持つ必要があります。ここは解答ごとに1行貯めるシンプルな履歴テーブルにして、「最後に間違えている問題」を後から絞り込めるようにしました。集計より先に、まず生の履歴を貯めておく——この発想は、データを扱うほかのプロジェクトでも共通して効いています。

最初から完璧を目指さない

この経験で学んだのは、最初から完璧なデータ設計を目指さないということです。個人開発では、作って、使って、必要なものが見えてから足す——そのくり返しのほうが、結果的にうまくいきます。もちろん後からのカラム追加は手間ですが、使ってもいない機能のために最初から複雑なスキーマを抱えるより、ずっと健全でした。

問題は今もAIに手伝ってもらいながら、少しずつ増やしています。アプリ全体の話は「資格学習アプリ「マナビポータル」を個人で作っている話」にまとめました。育てていく過程そのものが、個人開発の楽しさだなと感じています。