🍊

type-challengesのオンラインジャッジを作りました

tekihei23172022/06/24に公開3件のコメント

type-challengesのオンラインジャッジ(type-challenges-judge)を作ったので、紹介したいと思います。type-challengesは、TypeScriptの型の演算の問題集です。

https://type-challenges-judge.web.app/

type-challenges-judgeでできること

  • type-challengesの問題の閲覧
  • 問題の回答の提出、判定
  • どれぐらい問題を解いたかの確認

トップページからtype-challengesの問題を閲覧できます。問題に正解すると、トップページと進捗ページのグラフに反映されます。


なぜこのサービスを作ったか

type-challengesの問題を解いて型パズル力を鍛えようと思ったのですが、取り組んでみると以下の課題を感じました。

  • 問題を解いたときの達成感が少ない
  • 他の人の解答が見にくい(Issueには書かれている)

解決しようと思ったのは、主に1つ目の課題です。この課題の原因は「ACがないこと」「進捗が見えないこと」の2つだと考えました。ACとはプログラミングコンテストやオンラインジャッジの用語で、提出した回答がテストケースをパスすることをいいます(Acceptedの略)。

また、進捗についてはAtCoder Problemsのように、解いた問題が緑で埋まっていったり、円グラフでどれぐらい解いたかが分かるようにすればいいと考えました。

報酬に着目してサービスの案を考える

報酬について考えることは、サービスの案を考えるときに有効な方法だと思います。報酬についての考え方で参考にしているのは、元任天堂社長の岩田さんの言葉です。

岩田さんは「なぜかやめずに続けてしまうゲームには、注ぎ込んだエネルギーの量より報酬が大きいという特徴がある」と言っていたそうです。

以下は岩田さん: 岩田聡はこんなことを話していた。からの引用です。

自分が注ぎ込んだ苦労やエネルギーよりも、ご褒美のほうが大きいと感じたら、人はそれをやめない。だけど、返ってきたご褒美に対して、見返りが合わないと感じたときに、人は挫折する。

つまり、サービスが使われようにするためには、ユーザーがサービスから得られるものを、ユーザーが消費するエネルギーより大きくする必要があります。

技術スタック

ReactとFirebaseで作りました。UIフレームワークはChakra UIを使いました。仕事ではVueを使っているのでNuxt3で作ろうと思っていたのですが、フロントエンドの設計やテストの話になるとReactの情報が多いので、この機会にReactを学んでみようと思いました(隣の芝生が青かった)。

ざっくりとですが使ってみた感想です。

  • React
    • TSXが最高でした
      • コンポーネントの分割を、型に守られながら段階的にできるのが良かったです(同一ファイルで分割してから、別ファイルに抽出できる)
    • Vueと比べると、パフォーマンスや再描画に気を使わないといけない気がしました
      • 気づかないうちに何度かコンポーネントが呼び出されていそうだったので、仕組みについてしっかり学ぶ必要がありそうだなと感じました
      • Vueはブラックボックス化されていて、勝手にうまくやってくれている感があります
  • Firebase
    • Firebase Authenticationで爆速で認証機能が作れてびっくりしました
    • Firestoreは制約が多くて結構つらいなと思いました
      • 階層型DBのつらみと、集約系のクエリがつかえないつらみを感じました
    • 型に守られたバックエンド開発は楽しかったです
  • Chakra UI
    • StackやGridなどのレイアウトのコンポーネントがあるのがびっくりしました(便利でした)

開発の流れ

開発期間は約6週間で、合計時間は50時間くらいでした。GWは休んでいたので空いています。

Reactはちょっと知っていたので、りあクト! Firebaseで始めるサーバーレスReact開発を1週間くらいでざっと読んでから開発をはじめました。

設計

ユースケース駆動開発実践ガイドを読んでいたので、読んでいて必要そうだと思った以下の3つを作りました。

  • GUIプロトタイプ(画面設計)
  • ユースケース記述
  • 用語集

画面設計はExcalidrawを使って書きました。ExcalidrawはUIがシンプルで必要なものが揃っているので、とても使いやすいツールです。

ユースケース記述と用語集はNotionで書きました。ユースケースを用語集の用語を使って書くことが重要なため、用語集をNotionのデータベースで作り、ユースケース記述で参照しながら書きました。

ただ今回は、処理やデータがFirestoreのスキーマにかなり依存していたため、開発のときにはあまりユースケース記述を参照しませんでした。

次に、データモデリングを行いました。Firestoreはクライアントからの書き込みをセキュリティルールで制限するため、それも考慮してスキーマを決める必要があります。どういう画面があって、その画面でどういうデータが必要かを洗い出して、データの持ち方を考えました。モデリングはTechTrainのメンターさんに手伝っていただきました。

RDB以外のデータベースをほとんど使ったことがなかったため新鮮に感じました。最初に参照系のユースケースを考えてスキーマを決めたおかげで実装がスムーズに進んだので、RDBのモデリングをするときもやってみようと思いました。

開発

一番の問題はモチベーションだと思います。モチベーションを保つために以下のことをやっていました。

  • タスクには必ず締め切り(目標期限)を作る
    • 最近は週の初めに1週間分のタスクを決めているので、そのときに1~2個くらい開発のタスクを期限付きで入れました
  • TechTrainのミーティングで相談する
  • 進捗や目標を同僚に話す
    • 画面を見てもらってリアクションをもらったりしました。今日この記事を公開できたのも、24日にリリースすると宣言したおかげです。

おかげでモチベーションが大きく下がることはなかったです。ありがとうございます。

まとめ

  • type-challengesのオンラインジャッジを作りました
  • 画面設計と、ユースケースを考慮したデータモデリングが開発の役に立ちました
  • モチベーションを保つために、タスクに目標期限を設定したり、TechTrainで相談しました

アプリがいいなと思ったら、この記事やリポジトリにいいね・スターをしていただけると嬉しいです。

https://github.com/tekihei2317/type-challenges-judge

GitHubで編集を提案

Discussion

ありがとうございます〜!!

GitHubの方にもIssue立てましたがどうやらstrictNullChecksが有効になっていないようで一部の問題でエラーが出て正解できないようです。私が調査したところ少なくともIf, Includes, IsAny, Sumに影響が出ています。

ログインするとコメントできます