😽

【個人開発】授業で使えるちょっとしたツールを作ってみた

2024/05/10に公開

自己紹介

某県の共学化されかけている全寮制男子校に通っていた、現在は会津大学の学部一年生をやっているしゃけのきりみ。です。
Cloudflareをこよなく愛する人です。

1.作ったきっかけ

私は旧学習指導要領最後の学年であり、影響を受けていなかったのですが、一つ下の学年から指導要領と評価方法が変わりました。
新学習指導要領では、旧課程と異なり、意欲・関心・態度にさらに重きを置いた評価が必要になったそうです。
そのため、私の地理の担当の先生は、授業態度を先生が授業中にした質問の答えを紙に書かせて提出することで評価をしていたそうです。
しかし、毎授業ごとにクラスの人数分の紙を処理し、なおかつ、地理総合が増えたためさらに多忙になった(のと、ITがお好きだった)先生が、私に、「これ、DXできない?」 と相談をされました。

2.システムの構成

そんな感じで、できることならやってみよう精神でできたのが、「ClaQ」です。

技術スタック

フロントは、HTML、CSSとJavaScript、IDaaSにFireBase Authenticationを採用、バックエンドにはCloudflare Workers、データベースにD1を採用しました。ホスティングはCloudflare Pagesです。

早く作らないと卒業してしまうのと、受験も並行してやらなければならず、また、学校で配布されている一人一台PCがあまりにも 貧弱 だったので、なるべく読み込みを軽くする必要がありました。そのため、新しい技術や言語を多く取り入れるわけにもいかず、典型的な言語で、何のひねりもないものができました。

なるべく安く済ませたかった結果、コストはアクセス数が膨大にならない限りはドメインのみ。XDomainで1円でした。

仕様

求められた仕様は以下でした。

  • 生徒が答えを送信し、それを先生が見ることができる
  • 先生はクラスを作り、それに生徒を参加させる
  • 集めたデータを評価に活用できる形でまとめられる
  • なるべく軽く、早く。
    これらを達成するには、ログイン機能、答え送信機能、そしてクラスの管理機能でした。

実際に実装された機能は、以下のとおりです。

  • 先生がクラスを作成する
  • 生徒がそれに参加する
  • 先生が問題を開始し、生徒がそれに答えを送信する。
  • 生徒は1問に対し、1度しか送信ができない。
  • 先生はそれを一覧にして表示ができる。
  • クラスが終わったら、先生は答えの一覧をGoogleSpreadSheetに書き出し、クラスを閉じて生徒が参加できないようにする。

実装

まず始めたのが、バックエンド、すなわち、CloudFlare Workersの実装です。
少し触ったことこそあったものの、SQLはやったことがなく、当然D1やKVは全くの未経験。SQLiteとかMySQLとかおいしいの?とかのレベルでした。
ということから、今回も、ChatGPTや各種記事に非常にお世話になりました。
ここからは実装方法の話になるのですが、私は商業開発はおろかチーム開発も未経験なので、おそらく「そうはならんやろ」という点が多くあると思います。許して。
バックエンドを実装するにあたり、割と大きめな実装をするという予感はしていたので、ステータスコードから考えました。
具体的には、ステータスコードには、「エラーなのか成功なのか」「どのメソッドなのか」「サーバーエラーなのかクライアントのエラーなのか」を含めることにしました。

そして、ステータスコードを決めた後、それを元にドキュメントを作成しました。
ちょうどJetBrainsのWritersideがリリースされた頃なので、それを使ってMarkdownで記述しました。Swagger?知りませんね。

そしていよいよ、触ったことのないDBへの挑戦です。
といっても、最初はWeb上の先駆者の方々のブログ(それこそZennやQiit⚪︎など)を読み、理解を深め、それから実際に練習用のDBを使って練習をしました。
まだまだ完璧とは程遠いので、勉強中です。

その後、やっとフロントの実装を行いました。
お恥ずかしながら、CORSをやっと理解しました。

ここまでかかった時間、実に1週間。実のところ、受験と並行できていたのかと言われると微妙なところです。

実装の話を長々と書いても仕方ないのでここまでにしておきます。

運用

実装ミスが見つかりました。はい。
始めてつかったSQLの文法を間違えて、大変なことになりました。
具体的にはこんな感じです。

const { results: answerExistCheck } = await env.D1_DATABASE.prepare(
          "SELECT * FROM Answers WHERE class_Code = ? AND question_Number = ? AND submitted_User_Email = ?"
        ).bind(class_Code, String(currentQuestionNumber), userEmail).all();
        console.log(class_Code, answerExistCheck);
        console.log(answerExistCheck);
        if (answerExistCheck.length != 0) {
          console.error("User already submitted answer.");
          return new Response(JSON.stringify([{ "message": "You already submitted the answer.", "status_Code": "SSE-12", "result": "error" }]), await headerMaker(400, false));
        }

もともと、このコードの2行目、つまりSQL文の部分は、以下のようになっていました。

"SELECT * FROM Answers WHERE class_Code = ? AND question_Number = ?"

そう。submitted_User_Emailの縛りを設けていなかったのです。
このミスにより、何が起きたか。

1つの問題に対し、1人の生徒が1つの答えしか送信できなくなりました。
要は早押しクイズ状態。それもそれで楽しめたらしいですが、私としてはやってしまったなという感じでした。なるべくミスはないように実装したつもりでも、やはり抜けがあるものだなと実感しました。
まぁ、何しろ1週間で作ったので、ミスは覚悟でしたが、それでも割とショックでした。

作ってみた所感

まず。共通テスト2ヶ月前にやるもんじゃ到底ありません。
依頼してくれたからには全力でやろうってのはいいけど、限度ってもんがあるだろ自分。

そして、SQL書いたことないのにこんなのを最初に作るな。慣れろまず。

そんな感じです。

そもそもWeb開発が初めてで、これまではGASでLINE Botを作ってきたような人なので、始めてやるにしては荷が重すぎたと思います。

できることなら作り直したい。

以上です。

Discussion