🤝

チーム開発で学んだこと

2023/12/05に公開

概要

アプレンティス」に参加し、課題の中でチーム開発を経験させて頂きました。
この期間中に私が考えていたこと、チームに貢献したことなどを中心に書いていきます。

前置き

チーム開発概要」に従って開発を進めました。
チームは3人。約1ヶ月間で「自分たちの役に立つもの」を考え、設計、開発し、ハッカソン形式でプレゼンまで行いました。ハッカソンは、採点形式で行われ、受講生からの評価が最も高いチームに「Best Student Award」、メンターからの評価が最も高いチームに「Best Award」が授与されるといったものでした。

現状

  • チームメンバーは全員チーム開発の経験がない。
  • 技術レベル3人ともバラバラ。
  • 3人とも社会人であり、開発に充てられる時間が限られている。
  • アプレンティスでは、同時進行で「クエスト」と呼ばれる課題があり、これも期限内に終わらせなければならない。

こういった条件の中で、1ヶ月でプレゼンまでやろうと思うと、凝りすぎたものを作るのは無理があります。
かといって、低品質のサービスを作っても自分たちの成長に繋がらないとも思いました。
(前提条件として、RailsやLaravel、Sinatra、Reactなどのフレームワークは使用せず、HTML/CSS、JavaScript、Ruby/PHPで開発を行う)

アイデア出し

前述した課題から、開発するプロダクトについて以下のような条件を挙げました。

  • ここまでの学習内容(技術要件として、Ruby、データベース/SQL、HTML/CSS/JavaScript)を一通り使用するようなサービス
  • 1ヶ月で開発・実装ができる程度の内容
  • 自分たちの役に立つものであること(マスト)
  • 発表時間5分で見せられる範囲を仕上げておく

プロダクトについて

自分がお酒を飲むことが好きだということもあり、「お酒のアレンジレシピを投稿するサイト」を私のアイデアとして提出したところ、このアイデアがチームで採用され、開発を進めることになりました。

プロダクト詳細

背景/課題

現状の困りごととして、以下のようなものを感じていました。

  • 同じ飲み方ばかりで慢性的なマンネリ化。
  • お酒のアレンジレシピをまとめたサイトがない。
  • お酒をアレンジしてみたいが、失敗したくない。

これらから、次のような機能を考えました。

サービス概要

  • アレンジレシピの閲覧・投稿・検索が可能。→必須機能
  • 会員登録不要で利用可能。→お酒を飲む時、飲んでいるときに会員登録は面倒
  • レシピ検索は、ベースのお酒、味や風味、キーワードから可能。→検索機能の充実
  • 会員登録することで、自分オリジナルのレシピを投稿が可能。→レシピを共有したいユーザー向け
  • 投稿されたレシピに対するレビュー機能。 →投稿するモチベーションUP
プロダクト裏話

このプロダクトを提案した理由の本音の部分を書いておきます。
 まずチーム開発という演習を行っているという立場から、最低限のCRUD操作をフレームワークを使わずに実装するという経験をしておきたいと思っていました。
テーマ自体は何でもよく、サーバーを自分で立てて、エンドポイントを作って、データベースを操作するといったコードをフレームワークなしで実装できれば、今後の理解がさらに深まるだろうと考えていました。
 次に実際にサービスを運営する目線で考えたときに、例えば普通のレシピサイトであれば、競合が強すぎてまず勝てません。
そこで「お酒」というジャンルに絞った上で、似たようなサイトがなかったこと、でも一定数の需要はあると思ったので、「お酒のレシピサイト」というプロダクトを提案しました。

個人で担当したタスク

・設計の進め方を提案

こちらの記事を参考に、設計の進め方について、チームに提案しました。
https://qiita.com/Saku731/items/741fcf0f40dd989ee4f8

その結果、以下のような画面設計(ワイヤーフレーム)と、詳細設計を作成し、プロダクトの全体像を把握してから開発に移ることができました。

画面設計

画面設計

詳細設計

詳細設計

・ガントチャートの作成

まだ、何をつくるか決まっていなかった段階で、ガントチャートを作成しました。
自分だけ、他の提出課題が終わっていたこと、他の二人に比べて比較的時間に余裕があったことから、準備しておけることはやっておこうと考え行動しました。

Notionを用いて、要件定義、設計、開発などの必要な工程を洗い出し、納期(ハッカソン)までの大まかなスケジュールを組み立てました。
こうすることで、「今自分たちは今何をしなければいけないのか、進捗は遅れているのか」が明確になりました。

・開発環境構築

こちらも、まだ何を作るか決まっていない段階での作業になります。
作るとしたら、これまでの課題で学んだ技術を一通り使用した以下のような構成になると考えていました。

  • フロント:HTML/CSS/JavaScript
  • バックエンド:Ruby
  • データベース:MySQL

そこで、Dockerを使って、MySQLのコンテナ、Ruby(HTTPサーバー)のコンテナを作成し、「docker-compose」にて一括で起動できるような環境を構築しました。

作成した環境は、githubに公開しています。
https://github.com/makoto00000/webrick_app

「webrick」というgemを用いて、rubyでWebサーバーを構築し、フロントの画面から、MySQLへデータを保存し、取得できるという簡易的なものです。

ここまでのアプレンティスの課題では、rubyを使ってオブジェクト指向を学ぶというものだけであり、webサーバーの構築や、データベースに接続するといった内容はありませんでした。

アイデアが決まって、設計もできていざ実装となったときに、環境構築で躓くことは用意に想像できました。

それなら、先に環境を作っておいて、チームメンバーに共有する形にしておけば、そういった心配がなくなると考え、環境構築を先に進めることにしました。

結果として、予めこれらの環境を用意したことで、ルーティングやAPIなどの開発がとてもスムーズに進みました。

・デザイン

Figmaを使って以下のようなデザインを作成しました。
UIデザイン
複雑なデザインは使用せず、シンプルで、かつ見栄えが良くなるよう画像を多く使用しました。
実際に、UI部分については、アプレンティスのメンターさんからも褒めて頂けました。

・ログイン機能

フレームワークを使わずに、ログイン機能を実装するのは、かなりレベルが高く自分の知識の無さを痛感しました。
しかし、勉強しながらようやくCookieやセッションについて理解が深まり、実装に至りました。
実装について以下に示します。

①エンドポイント

webrickサーバー(server.rb)に以下のエンドポイントを設置

  • /api/login
  • /api/logout
  • /api/get_current_user

②ログイン処理

JavaScriptから、/api/loginへPOST送信すると、usersテーブルからemailpasswordが一致するユーザーを取得。
一致するユーザーが存在したら、サーバーのセッションへランダムに生成したsession_iduser_idを紐づけて保存。
ブラウザにはsession_idのみクッキーにセットして返却。

③ユーザー情報取得

JavaScriptから、/api/get_current_userへGETリクエストを送信すると、ブラウザのクッキーに保存されたsession_idと、サーバー側のsession_idが一致していた場合、サーバー側のsession_idに紐づいているuser_idを使って、データベースのusersテーブルから、idが一致するユーザーを取得し、JSON形式でフロントへ返す。

④ログアウト処理

JavaScriptから、/api/logoutへリクエストを送ると、ブラウザのクッキーに保存されたsession_idと、サーバー側のsession_idを照合。一致するsession_idがあった場合は削除。

・コミュニケーション

ミーティングや、チャットでの連絡時には、相手の意見を尊重するということを重視していました。

どんな意見からでも、そこから新しいアイデアが広がることがあるのに、そこで相手を否定してしまっては、以後意見が出にくくなってしまうからです。

このようにして、誰かの意見だけで開発が進んでいくことがないよう、均等に意見が出し合えるようにしながら、個人の技術力や、経験、課題の進捗状況、何が得意なのかを会話の中から引き出していき、常に締め切りを意識しながら、舵を取るよう心がけました。

また開発に関係のない話もしつつ、気軽に質問をし合える関係性を目指しました。
最初はお互いに初対面だったためぎこちなかったと思いますが、後半はチャットに質問を投げあったり、ボイスチャットにて気軽に会話できるような関係になったと感じました。

チーム開発で学んだこと

複数人で開発することの難しさ

個人でサービスを作った経験は何度かありましたが、チームで開発となると全くの別物だと思いました。
他の人が何をやっているから、自分はこっちをやった方がいいなとか、
ここの実装が遅れていて、自分は今余裕があるから巻き取った方がいいなとか、
考えることが多くあり、管理することの難しさを痛感しました。

また、「チーム開発という課題」でもあったため、一人で多くのタスクをやってしまっても、プロダクトとしては成功するかもしれませんが、チーム開発という貴重な経験が得られないと感じたため、重要な場面では前に立ったり、そうでない場面では一歩引いてサポートに回るということを意識していました。(もちろん、実務ではプロダクト優先だと思いますが...)

今回の、自分を含めチームメンバーそれぞれの持ち味をすべて発揮させた上で開発を進めたという経験は、今後も必ず役に立つと思っています。

タスク管理の重要性

画面設計、詳細設計、UIが完成した段階で、思いつく範囲でタスクを洗い出し、Notionにてチームメンバーに共有しました。
そして、タスクをチケット式にして、各個人で自分ができそうなタスクを取っていく方法にて開発を進めました。

ですが、チームメンバーとの意識のすり合わせや、洗い出したタスクが甘かったこともあり、最終発表ギリギリまで開発をすることになってしまいました。

自分たちの力量で、どれだけのタスクをどれくらいの時間で終わらせられるのかを予測することができなかったのが、最大の原因だと思っています。

例えば、タスクを洗い出した時点で、誰がどのタスクならできそうか事前に把握しておくと、誰にどのタスクを任せれば良いか管理しやすくなり、時間の見積もりも考えやすくなると思いました。

gitの活用

個人開発のときは、あまり使用しておらず、勉強のために少し触った程度でした。
チーム開発では、gitを使う場面が多く中でも、勉強になったのは次の2点です。

  • コンフリクトを起こしたときの対応
  • ブランチを切って開発していくことの重要性

最初、コンフリクトを起こさないようそれぞれの担当をファイル単位で分割していましたが、どうしても同じファイルを変更する場面も出てきたため、コンフリクトを起こしました。

いろいろ調べながら、

  1. ローカルのfeatureブランチにリモートの最新のfeatureブランチをマージさせる
  2. ローカルのfeatureブランチを、現在作業中のローカルブランチへマージさせる←コンフリクト
  3. コンフリクトの内容を見ながら修正していく(VSCodeではここを視覚的にでき楽でした)
  4. 変更したブランチをリモートにプッシュする。
    こういった手順でコンフリクトの解消にあたりました。

また細かくブランチを切っていくことも重要だと感じました。
開発中に、メンバーの人が実装の仕方が分からず、長い時間をかけていたということが何度かありました。ある程度考えて分からなければ、チームで相談するといったルールづくりが必要だったなと思います。

また、Notionを使ったタスク管理に加え、例えば切りの良いところでリモートにプッシュしてもらい、困りごとなどをIssuesに入れてもらうなどすれば、各個人の進捗や、何に躓いているのか把握しやすくなると思いました。

今回は、リモートにfeatureブランチを作り、そこから各個人のタスクごとにブランチを派生させて、マージさせるという方法を取りましたが、github-flowのような規則に則って開発を進めたほうが分かりやすかったかもしれません。

まとめ

複数人で一つのプロダクトを築くという経験ができたことは、エンジニアを目指す上でとても貴重な経験となりました。
同時に、多くの課題や反省点も見つかり、次回のチーム開発では、それらをクリアしたチーム開発にしたいと思います。

最後に、完成したプロダクトはローカル環境だけでの開発であったため、トップページの画像を載せておきます。

LiqRecipeトップページ

GitHubで編集を提案

Discussion