見出し画像

SUNABACOの卒業製作で初めてWebアプリを作った話-後編- (バックエンド周りの紹介)

こんにちは、ヴィクタールです。2023年の夏にSUNABACOのプログラミング教室を受講し、無事卒業できました。卒業課題として製作したWebアプリについて、備忘録も兼ねてまとめていこうと思います。

製作したWebアプリの提供価値(目的)や機能の概要につきましては、前編の記事に記載しておりますので、まだ読んでいない方はそちらを先に見て頂くことをオススメします。


1. 今回の記事の目的

前編でもちょっと触れていますが、Webアプリの製作後にSUNABACOの受講生みんなで発表会を行いました。
その状況はSUNABACOさんがYouTubeで公開してくれていますので、興味がありましたらご覧いただけますと嬉しいです。

この発表会にて、有難いことにWebアプリの機能に関する質問を頂きましたが、時間の関係で十分な説明をできませんでした。それが凄く悔しかったので、今回の記事の作成を決めた形になります。

また、講師の方に機能の実装力についても褒めて頂けました。そこで、なぜ比較的(?)スムーズに機能を実装していけたのか、そのあたりの自身の考察も交えてまとめていこうかと思います。

2. WebページとWebアプリの違いについて

この後の説明で、Webアプリの内容について説明して行きますが、その前にWebアプリの定義のおさらいをしようと思います。知っている方はこの項目を飛ばして頂いて問題ありません。

普通のWebページとWebアプリの違いは、静的/動的という言葉を用いて説明されることが多いです。ここで言う静的/動的は、静止画や動画という話ではなく、ざっくり言うとユーザーの各々が画面の状態を動かせるか?という話になります。

Webページは主に静的なコンテンツを提供しています。静的なWebページは、コンテンツ(テキスト、画像、ビデオなど)があらかじめ作成され、更新や変更がない限りそのまま表示されます。ユーザーはコンテンツを閲覧するだけで、ページ内の要素に対して直接的な操作やデータの送受信は行えません。静的なWebページは、情報提供や広告など、基本的な情報の伝達に適しています。

一方、Webアプリは動的な機能を提供しています。動的なWebアプリは、ユーザーの操作や入力に応じてコンテンツが変化する特徴を持っています。ユーザーは対話的にアプリケーションとやり取りし、データの入力や操作、処理結果の表示などが可能です。動的なWebアプリは、オンラインショッピング、ソーシャルメディアプラットフォーム、タスク管理ツールなど、ユーザーとのインタラクションが必要な場面で活用されます。

総括すると、Webページは静的なコンテンツを提示し、一方でWebアプリは動的な操作や機能を提供している、ということになります。
もう少し細かな話は、Progateさんの下記のページが凄くわかりやすかったのオススメです。イラストとか凄くキレイ。

3. 「機能を作成・追加する」とはどういうことか?

今回の卒業製作では主にWebアプリのバックエンド部分(機能実装)を担当しました。従って、これから書いていく内容はバックエンドの話が中心になります。
実は、元々講座を受ける前からPythonの知識はありました。ただ、スムーズに機能の実装を勧められた理由はそれだけじゃないと思っています。

その理由の一つとしては

Webアプリ機能を実装するにあたって、
全てデータベースを中心に考えていったから

だと思っています。

こう考えた理由について説明していきます。
Webアプリの仕組みとしては良く以下の図のように説明されます。
(ほぼ内容はProgeteに掲載されていた図の模倣ですが…

Webアプリの仕組み

上記の図に関する細かな説明はここでは省略しますが、ユーザーから見える機能とは、サーバーなどを経由し、データベースにアクセスし、情報の取得や操作などを行なった後、クライアントのブラウザの画面に結果として表示されるモノのことを指しています。

では、過程を飛ばして、ユーザーがおこなっていることだけを表現するとどうなるでしょうか?

ユーザーが実質行なっていること

はい、こうなるわけです(笑)
極論ですがユーザーが直接データベースにアクセスできれば、他の過程は要りません。
つまり、かっこいUIのモーション(フロントエンド側)などは別として、Webアプリにおける「機能」とはほとんどが「データベースの操作」と言えます。
したがって、新しい機能を考えたり、追加したりする場合は全てデータベースを中心として考える必要がある、ということです。

4. データベースの設計について

そして、今回、機能の開発が順調に進んだのは実装するWebアプリの「機能」が決まってすぐに、ほとんど修正する必要がないデータベースの設計をおこなうことができたからだと思います。
そこで、当初実装しようとしていたタスクアプリの機能一覧を記載していきます。ここからは前編の記事を読まれている前提の説明になります。

実装機能一覧

  • リスト表示

  • カード追加

  • カード編集

  • カード削除

  • 未学習/学習済みのカード切り替え機能

  • 未学習/学習済み別のフィルタ表示機能

  • レベルアップ機能

  • インセンティブページ表示機能

  • タグ検索/表示機能

  • ログイン機能

この機能一覧から以下のデータベースの設計をおこないました。

設計したデータベース

灰色の部分は実際には作成しなかったカラムです。
これをどう設計したかというと、七割ぐらいはchatGPTの力を借りました(笑)

この時のchatGPTとの会話内容を参考として載せておきます。
このchatGPTの出力結果を元にデータベースの設計を進めました。
アプリの仕様がブレブレの時期の会話ですので、開発したWebアプリと結構異なる参考情報をプロンプトに書いています。ただ、いわゆるバックエンドの「機能」部分はほとんど変わっていなかったので、初期に設計したモノをそのまま使っています。

ChatGPTの出力からの変更部分

  • ポイント(レベルアップ用経験値)のテーブルを2つに分割

  • アーカイブ帳テーブルの名称をアイテムテーブルに変更

  • フラグ管理用のインセンティブズテーブルの追加

  • カレンダーテーブルの削除

  • その他の細かい修正

ポイントのテーブルについては、バランス調整などで、アクションに対して得られるポイントを調整する必要が生じた場合に、全てのポイント履歴を書き換えることが嫌だったので、各アクションに対して得られるポイントを管理する別のテーブル(ポイント管理テーブル)に分割しています。

また、インセンティブズテーブルは開発の後に必要性に気づいて追加したテーブルです。詳細な説明は省略しますが、インセンティブページの表示条件(例えばレベル10になったらそれを讃えるhtmlファイルを表示する)についてはPythonとJinja2で比較的簡単に実装できたのですが、条件を満たしていると永遠にループしてページから抜け出せなくなってしまいました。この問題に対して表示フラグを管理することでこのループを回避することを思いつき、インセンティブズテーブルを追加することにしました。

5. 機能の追加方法について

ここから、機能追加の一例をピックアップして実装の流れを説明していきます。ピックアップするのは発表会の際にご質問を頂いた「レベルアップ機能」についてです。なお、フレームワークはFlaskを使用しています。

レベルアップ機能を実現するには、2つの作業をWebアプリに実行させる必要あります。

  1. 特定のアクションをおこなった場合にユーザーにポイント(経験値)を付与する

  2. ユーザーポイント(経験値)の蓄積値からレベルを算出し表示する

この2点です。
この項目をデータベースの操作に置き換えると、

  1. 特定のアクションをおこなった場合にポイントテーブルにレコードを追加する

  2. ポイントテーブルの対象ユーザーのレコードからレベルを算出し表示する

となります。
まず1の方から流れを説明して行きます。
今回開発したWebアプリでは「特定のアクション」を2種類用意してしますが、そのうちの一つのタスクカードを追加した場合のケースで説明します。この際の動きは以下のようになります。

タスクカード追加時の動き

/add(post) ルーティングはデータベースへのレコードの追加を、/listルーティングはタスクカード一覧の情報の取得の作業を担っています。カード追加時のページを分けてadd.htmlを追加すれば、講義中に作成したアプリと同様の動きになります。

ここまで特定の操作時のバックエンド側の動きについて説明しました。
ではこの動きにどうやってポイント付与の操作を追加すれば良いでしょうか?
実は方法は至ってシンプルです。

/add(post)ルーティングの際に、ついでにポイントテーブルにレコードを追加するだけです

ポイント付与実装方法

極論を言ってしまうと、レコード追加時のルールだけ決めておけば、SQL文を一行追加するだけでポイント付与の操作ができてしまいます。データベース、素晴らしいですね。

次に2の流れについて説明します。
2はデータベースから抽出した情報を元に計算するので、Pythonコードの追加箇所自体は1に対して多めではあります。
変更内容としては

  • /listルーティングの際に、ついでにポイントテーブルのレコードを取得する

  • 取得したレコード情報を/listルーティング内のPyhtonコードで集計し、レベルを算出する

以上の内容を図で示すと以下の様になります。

レベル算出の追加

ここまで、状況を整理できれば、あとは追記するべき場所にカーソルを移動し、chatGPTやGithub copilotなどを用いてコードを生成してもらうだけで動いてくれる様になります。仮に状況の整理をせずに、「機能」追加の指示のみをchatGPTに入力した場合は、なかなか上手く実装を進められないのではないかと思います。

このように、大まかなデータの流れを把握しておき、機能を操作レベルまで分解すれば、どこにどんな変更を加えれば良いかがある程度見えてきます。開発中はずっとこの作業を繰り返して、機能を追加していきました。

結び

気が付けば前後編合わせて8000文字を超える量になってしまいました(汗)
この実装の考え方が「正解」というわけではないですが、一つの考え方のとっかかりになってくれるのではないかと思います。
当初は、ソースコードを記載する予定でしたが、各ルーテングに色々な操作や処理を入れているので、説明に使うには不向きと判断して入れませんでした。(あとWebアプリのサービスもそのうちリリースしたいし…
この記事が来期以降のプラグラミング教室の受講生の参考にでもなってくれたら良いなー。

ここまでご覧頂き本当にありがとうございました!
今回の記事をきっかけに他にも色々なことを発信してきたいと思います!
よろしくお願いします!
それでは。


この記事が気に入ったらサポートをしてみませんか?