開発背景
私たちは、Instagramの擬似Webアプリケーション「ZUCKER」をJavaで作成しました。アプリ名の由来は、みなさんご存知の通り、某大企業のCEOの名前を元にしています。開発人数は7人で、全員研修以外でWebアプリケーションを作ったことはありませんでした。何もわからない状態からどのようにWebアプリケーションを作成したかについて、時系列順に振り返っていきたいと思います。
アプリ概要
ZUCKERは、写真共有アプリInstagramを模したWebアプリケーションです。主に、写真投稿、ストーリー投稿、ライブ配信の3つの機能があります。写真やストーリーを投稿すると、フォローしている人はその投稿を閲覧することができ、いいねやコメントを書くことができます。また、ライブ配信機能では、コメントできるだけでなく、投げ銭を送ることもできます。
トップページ
ZUCKERにアクセスすると、上記の画面が表示されます。アカウントを登録し、メールアドレス、パスワードでログインすると、ユーザーのタイムラインが表示されます。
タイムライン
自分がフォローしている人の投稿が最新順に表示されます。投稿では写真(もしくは動画)、タイトル、投稿日時、本文が表示されます。一つの投稿に複数の写真がある場合、矢印を押すと表示する画像が切り替わります。
ハッシュタグ検索結果
ハッシュタグに該当する投稿の件数と、投稿内容が表示されます。画像をクリックすると投稿詳細画面に遷移します。
投稿詳細
投稿内容が表示されており、一つの投稿に複数の写真がある場合、矢印を押すと表示する画像が切り替わります。投稿に対していいねやコメントを投稿することができます。また、投稿主であれば、コメントや投稿の削除もできます。
ライブ
配信者側の画面
- 吹き出しアイコンをクリックすると、コメントの表示/非表示を切り替えられます。
- コメントや投げ銭は画面下部に表示されます。
- 人のアイコンの右側の数字は視聴者数を表します。また、アイコンをクリックすると、視聴者一覧を表示します。
- マイクとカメラはクリックするとそれぞれオフにもできます。
- バツを押すと配信を終了します。
視聴者側の画面
- 吹き出しアイコンをクリックすると、コメントの表示/非表示を切り替えられます。
- コメントや投げ銭は画面下部に表示されます。
- 右側の金額が書かれたボタンをクリックすると投げ銭を送ることができます。
- コメント入力欄にテキストを入力し、送信ボタンを押すとコメントを送信できます。
- バツを押すと視聴を終了します。
立ち上げからリリースまで(作成過程)
ここからは、実際にどのように企画を立ててリリースしていったかを時系列順に書いていきたいと思います。
人数 | 7人 |
制作日数 | 20日 |
1日にかけた時間 | 8時間 |
開発環境
フロント:Bootstrap v5.0.2、Push.js v1.0.9、jQuery v3.3.1
バックエンド言語:Java8(サーブレット・JSP)
データベース:Oracle
Webアプリケーションサーバー:Tomcat-8
デプロイ先環境:Linux CentOS
ソースコード管理:Git, GitHub
開発マシン:Mac Ventura(13.3)
エディタ:Eclipse2023-03
6/2~6/5(開始から1~2日目)
何を作るか?
初日は何を作るかを決めました。著名なWebサービスを模したものをJavaで制作することが研修課題でした。しかし、私たちのグループではなかなか何を作るのか決まりませんでした。画像や動画を投稿できる方が楽しいというのがきっかけで、Instagramを作ることに決めました。チーム名は某大企業のCEOの名前からZUCKERBERGに決めました。
まず何をする?
まず、機能一覧を作ることを第一目標にしました。機能一覧を作らないことには、作業計画や設計書を作成することができないと考えたからです。しかし、がむしゃらに機能を出していっても他の機能とバッティングする可能性がありました。そのため、Instagramにあるすべての画面を印刷して画面ごとの機能を考えるようにしました。こうすることで、他の機能とバッティングを防ぐことができました。
6/6~6/8(開始から3~5日目)
必要書類の作成、完成アプリの意識のすり合わせ
機能一覧を作成し、3日目からは全体スケジュール作成、DB定義書作成、画面遷移図作成、詳細設計書作成を分担して行いました。全体スケジュールは機能ごとに役割分担はせず、詳細設計ができた機能から実装していくというスケジュールの立て方で行いました。DB定義書はER図を書いて各機能の登場人物と関係性を整理しながら、列や制約の内容を決定しました。画面遷移図は画面と画面を矢印で繋ぐことで、画面の遷移関係を整理しました。詳細設計書は、遷移方法、クラス名やメソッド名についても、分かる範囲で大まかに決めました。これらの書類を作成することによって、完成アプリの意識のすり合わせを行いました。
DB定義書(一部)
ユーザー関連のDB定義書
投稿関連のDB定義書
画面遷移図
6/9~6/13(開始から6~8日目)
実装、詳細設計、技術調査
詳細設計書が書き終わったものから順次実装に入りました。デザインについては、Bootstrapを用いるという方針が固まりました。同時に、ライブ機能や画像、セキュリティ関連を技術調査班が調査を開始しました。
技術調査の結果、ライブ機能にはWebSocketを使用することになりました。実装時は、以下のサイトを参考にしました。
WebSocket概要
https://www.opentone.co.jp/ot-lab/all/web-system/【html5】websocketとjavaサンプルプログラムのご紹介
動画・音声・コメント等の送受信
http://blog.livedoor.jp/kotesaki/archives/1667452.html
https://gist.github.com/ykst/6e80e3566bd6b9d63d19
http://cad.lolipop.jp/work/class/webapp_with_es2015/dynamic_webapp_with_websocket/image_websocket.htm
データの送受信先を配信者ごとに管理
https://cloudear.jp/blog/?p=2053
6/14~6/21(開始から9~14日目)
実装、レビュー修正、単体テスト、技術調査
実装が完了した機能については、プルリクエストを提出し、メンバー間でレビューし、結合用のブランチにマージし、単体テストを行いました。同時に、通知機能、ストーリー機能の技術調査が開始しました。
技術調査の結果、通期機能についてはPush.jsという便利なライブラリがあったのでそちらを利用しました。Push.jsを使用するとプッシュ通知が簡単に実装できます。
https://www.casleydi.com/blog/engineer/293/
リアルタイムにプッシュ通知を行うためには、ポーリングを行います。ポーリングとは、一定時間ごとにサーバーへ更新状況を確認する技術です。以下のサイトを参考に実装しました。
https://www.kimullaa.com/posts/201601171413/
6/22~23(開始から15~16日目)
細かいコード修正、デザイン調整、結合テスト作成
全ての機能が実装でき、単体テストが完了しました。それに従うコード修正や、結合テスト仕様書を書きました。デザインは主にBootstrapを使用し、アニメーションを伴うデザインは以下のサイトを参考にしました。
https://deshinon.com/category/parts/error/404-error/
Bootstrapで使用したコンポーネントは以下の6つになります。
①モーダル(サイドバーからNewPostボタンを押した時)
②サイドバー
③カルーセル(各投稿の右クリック時&左クリック時)
④カード(各投稿、カードの上に投稿内容を乗せている)
⑤ボタン(詳細ボタン)
⑥Icon(サイドバー内の可愛いアイコン)
これらを組み合わせてデザインを仕上げました
サイドバー
モーダル
6/26~29(開始から17~20日目)
バグ修正、発表準備
結合テストが完了し、細かいバグの修正(送信ボタンを連打した時などの異常系)、qiitaやプレゼンの準備を行いました。
振り返り
苦労した点
ライブ
- WebSocketで一度に送れるデータ量上限に対処するために、送信側で分割してからデータを送信し、受信側で分割データを再結合するようにしたこと
- 同じWebSocketサーバーを使用しつつ、複数人が同時にライブ配信をできるようにすること
- 視聴者数や視聴者名の送受信を一つのWebSocketサーバーで行うために、送受信するデータに独自のシグナル文字列を追加し、データ種類を区別できるようにしたこと(例:viewerNumGet→視聴者数取得、viewerNameGet→視聴者名取得)
- コメント欄やカメラ・マイクの切り替えボタンを、配信映像に重ねて表示すること
KPT
Keep
- 時間が空いた時に、他の作業に回ってお互いにカバーし合ったこと。
- 事前に誰が何のファイルを今から編集するのかを周知し、記録に残して、ファイルの状況をメンバーに周知した。これにより、コンフリクトを防げたこと。
- 研修で扱ったことのない技術が必要な場合に、スムーズに実装できるよう、実際に動かしながら調査を行ったこと。
- 疑問点があればなんでも聞くことができた点、また、報連相しやすい雰囲気がチーム内にあり、全体の意思統一ができたこと。
- チャットだけでなく口頭と張り紙でも連絡を行ったこと。
- チーム間でのレビューを講師の方から受けたような厳格な視点で行ったこと。
- 朝会で進捗状況と今日何をやるのかを明確にしたこと。無駄な時間を少なくできた。
- 1ヶ月で完成予定のプロジェクトだったが最後1週間をバッファにしたことが精神的にも時間的にも余裕ができてよかった。
- 意見のすれ違いが起こった時にはホワイトボードにお互いの意見を書いて建設的に会話ができるようにする。
- 機能の問題点や改善点を見つけ、メンバー間で互いに是正し合えたこと。
Problem
- 立ち上げからリリースまでのところでリモートで作業しているメンバーが居たが、メンバーが通知を見ていなかったり、タイミングが悪かったりしたため、コミュニケーションを取りづらかったこと。それにより、リアルタイムに正確な情報を共有できなかったこと。
- 実装を進めていくにつれて、最初に想定したスケジュール通り行かなくなり、見直しが必要になったこと。
- 機能ごとにスケジュールを立てなかったことでどのくらい前倒ししているのか、遅れているのかが、明確ではなかった。
- 開発メンバー全員に共通する機能や、コードを書く上での共通事項を用意するのが遅くなった。そのため、後からコードを修正する必要が生じたり、ライブラリのバージョンのずれが発生したりしたこと。
- 進捗確認や作業予定が朝だけのことが多く、夕方などには全く別の作業をしていることがあり、進捗の把握が難しいことがあった。
- 後から問題点や修正点が見つかることが多かったため、修正作業が多く発生し、全体の進捗が遅れ気味になった。
- 認識の齟齬が起きた場合に、どの時点から齟齬が生じてしまったのかを振り返らないまま状況だけを見て改善しようとしてしまったこと。
Try
- 早いうちにコードの書き方のルール決めや、機能的な問題点を洗い出して、完成像を全員で共有する。
- 全体の進捗に応じて、メンバーの配分を調整し、日程にも反映していくこと。
- オンラインでもコミュニケーションを取れる環境を作るため、通知の内容を優先して処理する時間を作ること。
- 個人スケジュールの調整を簡単にするために、機能ごとに割り振るべき。
- 自分が編集しているファイルを記録が残る形で書いておく。
- 複数人が使用するファイルを洗い出し、早い段階でそのファイルを作成、共有する。
- 共有事項を逐一口頭で確認すると共に、メンバー全員が文章で共有事項を確認できる場所を用意し共有事項を記述する。
- 認識違いや問題が発生している場合に、ステップを分けてどの段階で齟齬が生じたのかを確認するようにする。
まとめ
最初は、Instagramのような機能がたくさんあるアプリを7人で作れるビジョンが正直ありませんでした。しかし、機能を分解し、1つ1つ実装していくことで、だんだん形になっていきました。モチベーションに関しては、「メンバーに迷惑をかけないよう自分も頑張らなければいけない」という責任感もあったため、高い状態を維持することができました。また、グループ演習を通して、メンバーとのコミュニケーションをとる場面が非常に多く、情報共有を細かく行うことが大切だと学びました。グループ演習で得られた経験を配属後においても、活かしていきたいと考えました。