📝

技術面接に落ちて。キャンパスコンパス開発者

2024/03/28に公開

まえおき

この記事は筆者がCa Tech Jobの技術面接に落ちて悔しくて書こうと思った内容になります。面接で聞かれたことに答えながら技術力をあげよう‼️って趣旨です。

内容としては、以下の構成をメインにしつつ今後の面接対策ついでに色々残そうと思います。

  • キャンパスコンパスについて
  • キャンパスコンパスの技術構成

インターンの技術面接に落ちるくらいなので技術力は大したことない者なので間違っている点などあれば教えて頂けると幸いです。
自分なりにこんなもんだろって思いましたが、これ書けよ!これ考えろよ!ってことがあれば教えていただけると本当に助かります。

自己紹介

これを見てくれる方は自分のことを知らない方が多いと思うので一旦自己紹介です。
26卒で2024/04から豊橋技術科学大学 修士前期課程 電気・電子情報工学専攻に入学します。
最近気づきましたが、自分は技術に興味が無いみたいです。

興味が無いからこそ、この記事を書いて技術力あげよう!って魂胆です。
基本的に技術よりもプロダクト志向な所があり、○○作りたい、○○なアプリ欲しいと思って実際に自分が使えるものをよく開発しています。
以下の経験があります。

  • kotlinでAndroidアプリ2つを開発し、Googleストアに公開
  • PythonでGUI付きWindowsアプリをBoothにて販売
  • WEBアプリ2つをVPSでデプロイして公開
  • スクレイピングや自動化ツール開発をクラウドソーシングにて受注

ナンプレアプリで世界をとりたいという思いからFlutterを用いたモバイルアプリ開発に最近手を出しました。
(周りから就活のためにwebで開発したら?という声がありましたが悩み中)

ちょっと自己紹介が長くなりましたが、1番伝えたいことは、技術よりもプロダクトを重視しているってことです。
そのため、技術に対しての深堀りは行っておらず、開発にもgptさんを多用していました。

では、記事の本題の「キャンパスコンパス」とは何ぞやってところを書いていきたいと思います。

キャンパスコンパスとはなんぞや

豊橋技術科学大学の学生向けの情報集約サイトです。
URL:https://pus-pass.com/

キャンパスコンパスの概要

授業の評価の投稿・閲覧を主に、研究室情報やサークル・団体情報やイベントや技科大生に役立つような記事を掲載しています。
学内メールアドレスを持っている方のみ会員登録を可能にしているため外部の方のアクセスを制限しています。
制限しているのは、授業評価、研究室情報になります。
サークル情報や記事は学外の方も閲覧掲載可能になります。
(詳細はサイト内を見てください)

開発のきっかけ

自分の経験から開発を決めました。
履修登録時に授業情報が少ない、テスト時に過去問のない教科でどんな問題が出るのかがわからない。といった経験です。
開発当時、大手さんが運営している授業評価サイトにあまり情報がなく、困っていました。
実際開発してからにはなりますが、しっかり調べたところ2万件くらいの評価は見つけることができたので、リサーチ不足だったとは思っています。
また、先輩たちがスプレッドシートにて研究室の情報をまとめてくれており参考になったという経験もありました。
サークルに関してですが、どんな活動をしているのかを一元的に集約されている場所がなく、学校の公式サイトもサークルの名称とリンクが載っているだけの簡易的なものでした。
そこで、サークルの情報を集約することを決めました。
最初の一年間は運営しながら、後輩たちにどんな情報が欲しいのか、サイトの使い勝手などのフィードバックを集めながら手探りで開発を行っていました。

今後の展望

一番はマネタイズをすることです。
運営に必要な資金を集めたいと考えています。
そのためにスポンサーや記事を載せたい企業などを現在探しています。
そして数年後の目標にはなりますが、"技科大生であれば利用したことがあるサイト"になるように新入生への認知の拡大や機能の充実を図っています。

8割の学生の会員登録を目指しています。

そして、さらに本題の本題。技術力向上のための技術構成を書いていきます。

キャンパスコンパスの技術構成

開発は以下の技術スタックを使用しています。

  1. クライアント (Webブラウザ): ユーザーがインターフェースと対話する部分です。HTML、CSS、JavaScriptを使用して構築されます。

  2. Nginx (Webサーバー): クライアントからのHTTPリクエストを受け取り、それに応じて静的リソースを提供したり、アプリケーションサーバーにリクエストを転送します。

  3. Gunicorn (アプリケーションサーバー): Djangoアプリケーションを実行するためのWSGIサーバーです。Nginxからのリクエストを受け取り、Djangoアプリケーションに渡します。

  4. Django (Webフレームワーク): リクエストを処理し、ビジネスロジックを実行し、データベース操作を行い、レスポンスを生成します。

  5. SQLite (データベース): アプリケーションのデータを保存するための軽量でファイルベースのデータベースシステムです。

システム構成図

  1. ユーザーからのリクエスト:

    • ユーザーがウェブブラウザを通じて特定のURLにアクセスすることでHTTPリクエストを開始します。
    • ブラウザは、このリクエストをインターネット経由でウェブサーバー(NGINX)に送信します。
  2. ウェブサーバーでのリクエストの処理:

    • NGINXがリクエストを受け取ります。
    • 静的リクエストの場合(画像、CSSファイル、JavaScriptファイルなど)は、NGINXが直接これらのファイルをクライアントに返します。
    • 動的コンテンツがリクエストされた場合(データベースのクエリなど)、NGINXはこのリクエストをアプリケーションサーバー(Gunicorn)に転送します。
  3. アプリケーションサーバーでのリクエストの処理:

    • GunicornはWSGIプロトコルを使用してDjangoアプリケーションにリクエストを渡します。
    • Djangoはリクエストを受け取り、ビュー、モデル、テンプレートを使用して処理を行います。この時、データベース(SQLite)からデータを取得したり、データを保存したりすることもあります。
  4. レスポンスの生成とクライアントへの返送:

    • Djangoは処理結果をHTTPレスポンスとして生成し、Gunicornに渡します。
    • GunicornはこのHTTPレスポンスをNGINXに転送します。
    • 最終的にNGINXはHTTPレスポンスをインターネットを経由してユーザーのブラウザに返します。
    • ユーザーのブラウザはレスポンスを受け取り、ページをレンダリングしてユーザーに表示します。

技術選定

ここからはどのように技術選定を行ったのか記載していきます。
選定するにあたって以下の状況を前提にします。

  • 一人での開発
  • 4月に新入生が入ってくるため約一ヶ月でリリースまで行う必要がある

ユーザーが確保できるように新入生がくるまでにある程度形にする必要があり、開発スピードが求められる。
開発を行いながらコンテンツ(授業評価)集めを行う必要がありできる限り開発コストを抑えたい。
今思うと結構エグい状況っすね。。


自分の開発当初触ったことある技術としては以下になります。

  • Python(スクレイピングやDjangoでのWEBアプリ)
  • kotlin(Androidアプリを2つ開発)
  • Javascript(自動化するのに触っていた)
  • HTML/CSS(WEBアプリ開発やスクレイピングのために触っていた)

キャンパスコンパスのアップデート開始時点では以下が追加されました。

  • Golang(API開発をインターンで行った)
  • Flutter(ナンプレアプリを開発した)
  • React+Typescript(インターンでWEBアプリを開発した)

基本的には開発当初の選定を記載していきます。
使える技術が増ましたが、時間に限りがあったという制約は変わらなくて時間的余裕は皆無だったため。

また、今回のシステムでの機能要件は簡単に以下のようになっています。

  • 会員登録
  • メール送信
  • 管理画面からのデータの操作
  • テンプレートからページの生成

言語・フレームワーク

PythonとDjangoを選定しました。
PythonとDjangoを使用してWEBアプリを開発した経験があるからってのが一番大きいですが、
ここでそんなこと言ってたら書く意味がなくなってしまうんでこれを機に調べました。

時間的に考えてフルスタックフレームワークを使用することにしました。
フロントエンドとバックエンドをまとめて開発できて、サーバーを一つにできるという点で考えました。

フルスタックフレームワーク

フルスタックフレームワークで有名な以下の4つを比較します。
比較の際には触ったことのあるDjangoを基準に行います。
すでに触ったことがあるというのは開発スピードが求められる場面ではかなり強力な優位点であるためです。

  • Python + Django
  • Python + Flask
  • Ruby + Ruby on Rails
  • PHP + Laravel

必要な機能について表でまとめました。

特性/フレームワーク Django Flask Ruby on Rails Laravel
会員登録 組み込みサポートあり 拡張機能(Flask-Securityなど)が必要 DeviseなどのGem使用 FortifyやJetstreamによるサポートあり
メール送信 組み込みサポートあり Flask-Mailなどの拡張機能が必要 Action Mailerを使用 Mailableクラスを使用
管理画面からのデータ操作 組み込みの管理画面あり Flask-Adminなどの拡張機能が必要 Active AdminなどのGem使用 Nova(有料)やBackpackなどのパッケージ使用
テンプレートからのページ生成 Djangoテンプレートエンジンを使用 Jinja2テンプレートエンジンを使用 ERB/hamlなどを使用 Bladeテンプレートエンジンを使用

機能要件については特にどれでも問題なさそうです。
ここでの違いは、フレームワークに組み込まれているかですね。
プラグインやエコシステムに依存するよりかは、フレームワークに組み込まれている方が学習コストは低そうですね。

DjangoはBatteries included(バッテリー同梱)という開発哲学を採用しているだけあって標準で組み込まれているから今のところはDjangoが変わらず優位です。

今回はプロトタイプのようなものなので機能の拡張性も考えておかないとダメですね。
機能の拡張性においてはどのフレームワークもそこまで大きく面倒ということはなさそうです。
DjangoとRuby on Railsがちょっと似ていますね。

結論
Djangoしか勝たん!
管理画面とセキュリティに強いってのは個人開発であまりカスタマイズの必要がない場合はかなり強みになりますね。
セキュリティに関してはここではあまり触れていませんので調べてみてください。

ソフトウェア設計

ここ何答えたらいいかわからなかったです。
面接の方に聞いたらアーキテクチャに関して聞かれたのでアーキテクチャのことを書きます。

MTV(Model-Template-View)アーキテクチャを採用しました。
新しい機能の追加や既存機能の拡張が必要になった場合の容易さや、
データモデルの定義から、ユーザーインターフェースの作成、アプリケーションロジックの実装まで、MTVアーキテクチャを用いることで、迅速にプロトタイプを開発できる点で採用しました。

Djangoの構成は以下の記事がとてもイメージしやすかったです。
処理の流れの視覚化できてよかったです。
https://baapuro.com/Django/four/

インフラ

VPSを用いて、ubuntu上に構築しました。
WEBサーバーにはNginxを採用し、DjangoアプリケーションとNginxを繋げるためにアプリケーションサーバーとしてGunicornを使用しました。

クラウドは利用したリソースに対してのみ課金されるため、トラフィックの増減によっては予測しづらい費用が発生する可能性があります。
一方でVPSは、固定的な月額費用であるため、初期段階でのコスト管理がしやすく、長期的な予算計画を立てやすいです。
上記を考慮しクラウドではなく、VPSを採用しました。
また、VPSはプランの変更でサーバーのスペックが変更可能なので将来的にトラフィックが多くなっても問題ないと判断しました。

データベース

データベースにはSQLiteを採用しました。
SQLiteを選択した主な理由は、開発の迅速化とシンプルなセットアップだからです。
ファイルベースなためデータベースサーバーを構築する必要がないため開発を迅速化できると考えました。
また、初期段階のトラフィックやデータ要件を満たすのに十分だと判断しました。

データの量が増加するにつれて、パフォーマンスやスケーラビリティの面でサーバーベースのデータベースに移行する必要が生じるかもしれません。
そのため、将来的にはPostgreSQLやMySQLなどのより強力なデータベースソリューションへの移行を検討しています。
ただ、現段階ではまだ選定は行っていません。
Djangoを使用しているため、技術的には異なるデータベースシステム間での移行が比較的簡単に行えます。DjangoのORMは複数のデータベースをサポートしているため、データベースエンジンの切り替えによるアプリケーションコードの大規模な書き換えを最小限に抑えることができます。
ただし、各データベースの性能、スケーラビリティ、コストなどの違いを評価し、プロジェクトの要件に最適な選択を行う予定です。
以下を移行のタイミングと捉えています。

  • 同時に数十の接続を超える
  • ファイルのサイズが数ギガバイトに達する

SQLiteは読み取り操作に関しては高いパフォーマンスを発揮しますが、書き込み操作は同時に一つしか処理できないため、同時書き込みが頻繁に発生するアプリケーションではボトルネックになり得るため。
SQLiteデータベースファイルのサイズが数ギガバイトに達すると管理とバックアップが難しくなるため。


開発で一番苦労した経験:時間割アプリのテーブル設計

課題

時間割アプリ開発において、データベースの設計が大きな課題でした。特に、曜日と時限をどのようにデータベースに保存するかで悩みました。
具体的には、以下の3つの選択肢を考えました:

  1. 曜日と時限をセットで一つのレコードとする
  2. 時限ごとに各曜日をまとめて保持する
  3. 各曜日ごとにまとめて保持する

検討した解決策

各授業に一意な時間割コードがあり、表示には授業名や単位数も必要なため、複数のAPIや追加のロジックが必要になる可能性がありました。
さらに、各年度の前期・後期に対応する必要があり、ユーザーごとに膨大な数のレコードが生成されることが予想されました。

解決策の模索

学内の時間割アプリ開発者や一橋大学の「バシコマ」開発者に相談しました。
どのようにデータを扱っているかを教えていただきました。

  • 学内の時間割アプリはデータの保持はしていないが、取得はJSで行っているため、Jsonで処理している。
  • バシコマは、曜日と時限をセットで一つのレコードとしている。(Firestore)

ここで、学内の時間割アプリとの連携の話が出て連携していただけることになりました。
そして、学内アプリとの連携を考慮し、時間割をJSONで保持することを決定しました。

最終的な解決方法と結果

学内アプリから時間割データをJSON形式で取得し、それをアプリ内で使用することにしました。
これにより、開発者の負担を減らしつつ、レコードの管理を効率化することができました。
最善の策かは分かりませんが、現段階での課題を解決することができました。

技術で困り事が自分で解決できない場合どのように解決したか

以下の順に行っていました。

  • ネット検索(ChatGPT含む)
  • 知り合いに聞く
  • Twitterや質問サイトの利用

基本的に自分で解決できていますが、設計部分などはわからないことが多く経験者に聞くことが多いです。
コードは調べればある程度出てきますが、設計など経験で行っていることなどはなかなか検索だと見つけきれないことが多かったです。

最近は書籍の重要性に気づき基本部分を書籍で補ったりもしています。

なぜフロントとバックで分けなかったのか(apiにしなかったのか的な)

APIベースのアプローチを取る場合、フロントエンドにReactなどの別のフレームワークやライブラリを導入する必要があります。
ですが、今回は初期段階のリリース、時間的リソースが限られているという点で学習コストなどを考慮し選択から外しました。
フロントエンドにフレームワークなどを用いることで素のHTML/CSSより開発体験は向上することも理解しています。
時間的余裕ができた際には移行を検討したいと現時点では考えています。
現段階では、Djangoのテンプレートを使用することで、フロントエンドとバックエンドを一つのフレームワーク内で完結させ、技術スタックをシンプルに保ち開発を迅速しています。

おまけ

エンジニアとしてどうなりたいか、

ちょっと質問は覚えてないですけど、キャリアについて聞かれました。
自分は個人開発が好きで個人開発するために技術力をつけているまであります。
なので、将来はまだぼんやりとですが、個人の技術を高めていきたいと思っています。
冒頭の技術に興味がない発言と食い違っていますが、
冒頭のは、深掘りを普段行わないため技術に興味がないと発言しました。
ですが、ここでは自分の開発スキルとして個人スキルを高めたいという思いです。
開発の幅が広がるという部分を重視したいなと考えています。
また、技術の深掘りには興味がないじぶんですが、深掘りするのは面白いと思ってはいるのでこれから深掘りつつ興味を日頃から持てるように意識して開発を行なっていきます。

ここまで長くなってしまいましたが、こんなだぶんを読んでくださりありがとうございます。
これからもエンジニアとして成長していくので暖かな目で見守ってくださると幸いです。

以上

Discussion