学園祭実行委員会で物品管理システムを作った話

はじめに

こんにちは

筑波大学学園祭実行委員会に今年度所属していたpuripuri2100です。 学園祭実行委員会の中でも「内部向けシステムやサイトの運営、映像の作成や生中継」などの情報系を主な職務とする「情報メディアシステム局」という部門で作業をしていました。

学園祭実行委員会は通常学類11年生と2年生が所属するのですが、自分は1年生時には所属せず2年生になった今年度のみ所属するというかなり珍しいことをしていました。これには理由があり、既に情報メディアシステム局に所属して作業をしていた同学年の友人が昨年度末ごろに「今作ろうとしている物品管理システムの進捗が芳しくない」とこぼしていたのを聞き、それをヘルプで入ったためです。既に高校生の時に文化祭の準備委員会で使う物品に一意のIDを振ったうえで貸し出しを管理するシステムとソフトウェア2を作っていたことや、困っている友人を助けたいという気持ち、またグループ開発をしてみたかったという様々な動機がありました

今年度の学園祭の前になんとか物品管理システムを完成させることができ、運用できたためここでその振り返りをしてみたいと思います。 採用してみた技術についてや作るうえでの苦労話、情報メディアシステム局で実際にソフトウェアを作ってみておもしろかったところやしんどかったこと、愚痴などをまとめて成仏させたいと思います。

作成したものについて

システムの概要

物品管理システムの概要

ユーザーが既に存在するLANケーブルやパソコンなどの「物品」に関連付けられた情報を取得したりその情報を更新したりすることができるシステムを作成しました。 ここでの物品に関連付けられる情報とは、例えば

  • 型番
  • 保管場所
  • 貸出があるかどうか
    • いつ
    • どこに
    • 誰が

といったものです。 また、このとき物品とソフトウェアの紐づけのためにIDをひとつずつ振り、QRコードを貼り付けることで物理的に物品にIDが紐づくようにしています。

システムはWebサービスの形で提供しており、次の画像のように様々な操作がブラウザを通じて行えるようになっています。サイトのURLは"https://qr.sohosai.com"です。

ページにあるように、このサービスの名称は"QR"と名づけられています(大変に紛らわしいので以降一貫して「物品管理システム」と記述します)。

物品管理システムのWebページの見た目

システムの目的

このシステムが作成された目的として、既存の物品の管理について下記のような問題点があり解決する必要があったからです。

  • 管理している細々とした物品が大量に存在する
    • 来年度の購入するものを考えるためにも、毎年一日かけてリストとの照合を行っていたが、リストに書いてあるものと現実の物品の対応を取るのが大変
    • 学園祭後の片付けが大変
  • 新歓や学園祭の準備中などに様々な物品を貸し出す必要がある
    • 貸し出しの記録を付けなければならない
    • 物品が移動するため、所在地を概ねでも確認出来ておきたい

そして、もう一つの裏の目的として「システムの開発経験を通じてメンバーの技術力を向上させ、より力を入れなければならない"https://sohosai.com"などの開発のときに使えるようにする」というものがありました。 残念ながらこの目論見は

  • 実は学部生レベルでコードを書ける人は少ない
  • 実は学部生レベルでコードを書こうとする人は少ない
  • 実は学部生レベルでコードを書けるようになろうと努力する人は少ない
  • 毎年引き継がれている出展団体管理システムのメンテナンスで唯一コードを書ける人が忙しくなった

という事情により頓挫し、自分がアサインするまでこのプロジェクトが放置されることになりました。悲しいですね。

使用した技術

を使用しました。使用した技術の多くは情報メディアシステム局で今年度採用した技術を踏襲しつつ、新しいものを取り入れていくようにしました。これは、学習コストの爆発を避けメンテナンスをしやすくするようにし、同時にモダンで使いやすい開発環境を維持していくためです。

情報メディアシステム局では過去に採用した技術に固執することなく、使いやすいモダンではあるものの今後急速に廃れる恐れが少ない技術を積極的に採用しており、とても良い環境でした。また、採用していた技術をより良いもので置き換える場合も合意が取れれば裁量の範囲内で行うことができてとても良かったです。

開発スケジュール

開発スケジュールのガントチャート

自分が参加する前の1月から3月まで教育兼簡単な実装が行われていたらしいです(伝聞)が、前述のとおりこれは中断され放置されていました。また、2月の中旬に物品の確認ついでにQRコードを物理的に貼っていたらしいです(伝聞)。

5月中旬に自分がアサインされたあとは

  • 学園祭実行委員会の雰囲気を掴む
  • 情報メディアシステム局の雰囲気を掴む
  • 情報メディアシステム局のメンバーと交流して誰が何をしているのかを把握する
  • 作成する物品管理システムについて、情報の収集と整理をする

などをしていました。

既に出来上がっている組織に途中から入るとだいぶ大変で、まず人と用語を覚え、次にやって良いところとダメなところの境界を把握することが必要でした。

ここでの感触として情報メディアシステム局は概ね「技術最高!全てを自動化したい!強い思想を発露するぜ!」という感じでだいぶマッチョな雰囲気でした。しかし、この感覚が実は少しだけ間違っていたということを後ほど思い知ることになります。

また、自分の立ち位置が"学園祭実行委員会委員長 > 情報メディアシステム局局長 > ネットワーク部門長 > QR担当長 > QR実装実戦部隊としてのpuripuri2100"という、いわば一番の下っ端の実戦部隊ということになっていることを交流を通じて知ったのですが、ネットワーク部門長もQR担当長もマネジメントを放棄しており自分が全てをやる羽目になることを後ほど知ります。

情報収集としては、1月から3月にかけて多少は実装をしていたにもかかわらず情報が全く整理されていなかったため、

  • そもそもとしての前提知識
  • 今抱えている課題
  • どういう機能があると課題を解決できるのか
  • 実際にその機能を実装するために必要な実装

のそれぞれを大量の断片的な情報からまとめあげてDesign Docを自分の手で作成する必要がありました。そもそもとして要件などを記述したページが

という3つのページについて分散し、しかも一つのページの中でも議論をする箇所と確定した情報を書く箇所が混在しているといった有様でした。とてつもなく読みにくかったです。

大学の課題が落ち着き雰囲気を掴んだ7月頭からバックエンドを作成し始め、リハーサルのある9月中旬までに最低限の機能を実装してフィードバックを受けて11月頭の本番までになんとか機能を拡充する、という感じでした。 でしたが、そもそもとしてフロントエンドも自分が作る必要があることを知ったのが8月中旬であったり、一緒に作業をするはずだった人が何もしなかったために全て一人で実装する必要があったりと地獄のような日々でした。あぁ、大学二年生の夏…………。

というわけでここからはそれぞれの実装フェーズでの話を詳細に書いていきたいと思います。

バックエンドの基本的な機能作成

今回作成したバックエンドは、

  • 外部にはHTTPリクエストで操作を行うことができるAPIをURLの形で公開
  • APIREST APIの形式に則る
  • DBに対して挿入・更新・削除・取得の操作を行う関数を定義し、APIとして公開する
  • データの取り扱いはserdeで自動変換

という感じで実装していきました。

バックエンドの概要

HTTPリクエストとDB操作用関数の結び付けはaxumというWebフレームワークライブラリに任せ、生成するSQL文とDBの結びつけと実際の操作についてはsqlxというDB操作用ライブラリに完全に任せることにしました。

これにより大幅な省力化をすることができ、プロジェクトに本格的にとりかかって学習をはじめてから3週間ほどでAPI実装用のテンプレートを作ることができました。7/26日にいきなり「7月中にバックエンドのテンプレートを作り終えて色んな人にタスクを振ってね」とマネージャー相当から宣言されてから泣きそうになりながら実装していたとしても(やや遅刻しながらも)なんとか対応できて良かったです。本当はそういう無茶ぶりをされたときにブチ切れることが一番良かったのでしょうが……。

実は最初はwarpというwebフレームワークを使って作っていましたが、所有権回りの制約が厳しくDBのコネクションプールを撮りまわしたりするのが難しかったために挫折し、axumに乗り換えるなどしていました。

挫折した時に「help wanted状態になっており自分では解決できないので誰かわかる人が居たら助けてください」と情報メディアシステム局のチャットに投げたのですが誰も反応してくれず、それどころか「君が他の人を教育して、その人と一緒に解決すると良いのではないだろか」とマネージャー相当の人から言われ、頭を抱えていました。自分が教えないとコードが書けないレベルの人間が、自分が解決できない課題を解決できるわけも無いし教育には膨大なコストがかかるということもわかっていないようで本当にどうしたものかと思っていました。「教育なんてやってるよりも自分が解決する方が早い」とちゃんと要望は蹴ったのですが、バックエンドのテンプレートを作るだけでここまでコミュニケーションが食い違っている有様というわけで未来が暗いですね……。

さて、「HTTPリクエストに反応してSQL文を通じてDBを操作する関数」の書き方のテンプレートができたため、必要なDB操作と対応するAPIをリスト化してIssueで作業してくれる人を募集しつつ実装を進めていきました。

切り分けられた大量のタスク

実に22個のタスクがあり、すさまじいことになっています。そしてここまでくるとわかっているようなものだったのですが、結局ほぼ全部自分が解決することになり、これまたすさまじいログになっていました。

自分で解決!

最低限使えるAPIを作成したので、あとはフロントエンドの要請に合わせて仕様を少しずつ弄りつつDockerで固めてデプロイで解決です。デプロイ周りはネットワーク部門長のmomeemtraspi0124、後輩のappare45にかなり助けてもらいました。一緒に手を動かしてくれる人が居るというのは本当にありがたいことですね。

フロントエンドの基本的な機能作成

自分はバックエンドを担当するだけだと思っていました。あの日までは。

『絶望』

たしかになぜかフロントエンド側の進捗報告が一切無かったと思っていたんですよね~。

この会話をしたのが8/12で、バックエンドに必要な機能をIssue化したのも8/12でした。そのため、フロントエンドの実装を考えつつバックエンドのタスクの巻き取りもしていかないといけないというデスマーチが展開していくことになります。 誰も助けてくれないし頼れる人は居ないということはもはや聞くまでもなく自明でしたので、自分で全部実装しなければならず、しかも学園祭のリハーサルがちょうど一か月後の9月下旬にあるためにそれまでに完成させないといけないというプレッシャーで精神的にかなり追い詰められていました(「物品管理システムは真に望まれて導入しようとしているものですか?」と聞くあたりで察せますね)。

追加のタスクを前にスケジュールの練り直しをする図

システムの作成を諦めて情報メディアシステム局をやめようか悩んでいた瞬間

8月末はつくば市と連携した教育イベントの運営に携わっていたり、母校の中高の部活の夏合宿にお邪魔して自分の学園祭のステージの練習をしつつ後輩に教えてるなどしておりとても忙しかったです。忙しすぎて結局僕の夏合宿にディスプレイを一枚持ち込んで宿でも空き時間にずっとコードを書いていましたし、ちゃんとメンタルも壊れて精神科に駆け込んでいました。

嘆き

さて、実装の話です。既にボタンやテキスト入力フォームのコンポーネントとトップページだけは実装されていたので、気合でエスパーしつつ必要な機能を拡充させていきました。 技術的なスタックとしてはNext.js + Reactの良くある構成で、muiで便利な機能を並べたりQRコードの読み取りにはreact-zxingあたりを使ったりしていました。コンポーネントの動作確認にはstorybookが既に採用されていたのでこれを使いました。はじめて触ったのですが、とても便利でした。

圧倒的才能により9月頭にはQRコードを読み取って貸し出しフォームにIDを自動で入力して貸し出しボタンを押して登録できるようになるまでできていました。他にも用意したデータをもとにして物品の詳細ページ表示もできるようになったりしており、これにて基本機能の実装が終わったので1週間半くらい休んでいました。良かったよかった。

初めて動いた瞬間 感動!!!

リハーサルでのとりあえずの運用

自分にバックエンドをデプロイするサーバーを触る権限が無かったので権限のある人にデプロイ周りを任せていたのですが、結局ギリギリまでやってくれずリハーサル前日に仮デプロイとデプロイ方法のドキュメント化をしてもらいました。まともな接合テストもそこではじめてやったため様々なエラーが出まくってその対応で当日午後まで修正する羽目になっていました。CORSの設定やAPIリクエスト送信のタイミング、データへのアクセス方法など様々に想定外のことがあり、自分の詰めの甘さと開発用サーバーの必要性を実感しました。

実際に物品の片付けのときに使ってもらった結果、コードをどの部屋のどの箱にしまうのかがちゃんと表示されて便利!との声を貰えて本当に嬉しかったです。

バックエンドの機能拡充

リハーサルでの経験などを踏まえて

  • 検索機能の追加
  • 認証システムの追加

を学園祭本番までの間に実装することになりました。

最初、検索機能は単純にSQL文で単語の部分一致だけをやれば良いかと思っていましたが、ちょうど数か月前に買っていた『検索システム ― 実務者のための開発改善ガイドブック』(打田智子・古澤智裕・大谷 純・加藤 遼・鈴木翔吾・河野晋策 共著、ラムダノート社、2022年)をこのタイミングで読み検索エンジンの奥深さに感動した結果、Meilisearchという最近話題の新しい検索エンジンを導入することにしました。 MeilisearchはDocker imageが配布されていてインストール・起動が非常に楽でした。 また、起動した後の操作もHTTPメソッド経由でAPIを叩いたりRustのSDKを通じて関数で操作できたりと非常に便利でした。 初めて思った通りの検索結果が実現できた時は感動がありました。検索エンジンってすごい!

この物品管理システムはCIの枠などの諸事情によりpublicリポジトリになっており、悪い人間に見つかった場合にはAPIを叩かれて遊ばれてしまう可能性があります。 そこできちんと認証システムを載せることにしました。フロントエンド側だけにCloudflareの認証やauth0の認証を載せるような運用だと万が一バックエンド側のURLが破られた時に意味がなくなりますし3、物品の詳細情報と検索などはログインしなくても操作できた方が便利なので認証をかけるところとかけないところを使い分けられるようにした方が良い、といったことから認証システムを作ることにしました(そして個人的に一回は作ってみたかった)。

形式としてはbasic認証でマスターキーをフロントエンドから送信してもらい、バックエンド側で検証をしたのちに一時トークンを発行して返し、フロントエンド側からの操作はその一時トークンをbearer認証で使うようにするというよくある形です。 もちろんマスターキーが割れたらダメなのですが、環境変数で切り替えられるようにしておりブラウザ側への保存はされないようになっているためあまり心配はしていません。 この認証システムを載せるためにエラーハンドリングやリクエストへの応答形式を統一するためのクソでかプルリクエストを作るなどしていました。エラーハンドリングは最初期から導入した方が良いです(学び)。

フロントエンドの機能拡充

バックエンドの機能拡充に対応した検索ページと認証まわりのアップデートはもちろんのこととして、見た目の改善も行いました。

見た目の改善については後輩のMyxogastria0808が「物品管理システムの開発に関わりたいです」と言ってくれたのでお願いしたところ、マジで使いやすいものを作ってくれました。本当にありがとう……。デザインを自分が学ばないといけないことを改めて実感しました。 ここで初めてまともにレビューというものをしてみたのですが、岡目八目が発動して結構ミスなどを発見することができ、レビューというシステムの重要性を感じました。

運用

11月に入り、いよいよ学園祭当日の運用を行いました。

貸出機能は使われず、検索と物品詳細ページがかなり多く使われたという印象です。 配線をするときのスペックの確認や、片付けのときの整理整頓の際にかなり使われていましたし、その時に便利で助かっているとの声をいただけてよかったです。

片付けの時に要望を受けてその場で簡単な機能追加をしましたが、特に壊れることなく使うことができて安心しました。

ドキュメンテーション

学生組織あるあるの困難さとして作成されたソフトウェアのコンテキストがわからない、ということがあります。そこできちんとDesign Docやコメントをその仕様に決定した経緯を含めて記述することにしました。また、それぞれのリポジトリにおいてCHANGELOGを書いておいたりと、一緒に開発する人がすぐに参加できるように、そして未来の人たちが困らないように気を付けて書きました。 結果として途中から開発に加わってくれた後輩や少し手伝ってくれた同級生などからも「ドキュメントがあったから取っ掛かりがあって助かった」と良い評価を貰えました。

cargo doc最高!!!

感想と反省

今回の物品管理システムの作成を通じて抱いた感想です。 良い面も悪い面も含めて「ひと夏の思い出」ということで……。

  • 様々な技術を触ることができた
  • フルスタックエンジニアになってしまった……
    • 「なりたくてなるものではない」という先人の教えは正しかった
    • 聞き取って要件定義するところからマネジメント兼全ての実装、運用と教育まで……
  • チーム開発は難しい
    • 人は信用ならないので期待しないべき
    • 人が助けてくれると素直にうれしい
    • 認識のすり合わせや催促などのコミュニケーションをしっかりと取っていくことがとても大事
  • マネジメントは難しい
    • 自分がまき取る覚悟でタスクを振らないといけない
    • マネージャーのマネジメントをしたときは流石に狂いそうだった
  • 技術系特有のコミュニケーションと普通のコミュニケーションとのすれ違い
    • 「質問とは質問であって説教ではない」とか「できないことは罪ではない」とか「誠実たれ」とかの信条は意外と共通していないのでそこを事前に共有しておくべきだった
    • 人にはプライドがあるのでわからなくても質問できない場面があるということを把握しておくべきだった
    • 対面でのコミュニケーションで柔らかくやっていくのが適切であったのかもしれないが、精神状態や生活リズムによっては大変なことがあるので難しい
  • 信用できるのは手を動かす人だけ
    • 結局ね
    • せめて自分で一回調べてみてから聞いてほしい

おわりに

本当に色々ありましたが物品管理システムの作成と運用ができ、そして学園祭が無事に終わって本当に良かったです。

このブログの公開をもってひと夏の良い思い出として自分の中で決着させたいと思います。


  1. 筑波大学では通常の学部・学科に相当するものを学群・学類と呼称します
  2. "dlm"という名で公開しています:https://github.com/puripuri2100/dlm
  3. そしてREADMEにバリバリURLを書いていた