メインコンテンツへスキップ
  1. blog/

絶望チーム開発日記(2) 湧かぬモチベーション

Diary
くろえい
著者
くろえい
高専生.ガジェット、中国やお出かけに関心あり.1人旅は移動式の引きこもり.たまにお勉強.「すごい人」にはなれなかったが、日々奮闘しております
目次
絶望チーム開発日記 - この記事は連載の一部です
パート 2: この記事

進捗状況やアプリの設計などをここに書き散らす.

環境構築
#

メンバーに各自の PC を持ってきてもらい、次の作業を行った.

  • WSL のインストール
  • 余計なアプリのアンインストール、スタートアップ無効化
  • Windows 10 から 11 へのアップデート

また、チーム開発用の GitHub Organization を作成した.

普段全く自分の PC に触れることがなく、Word を開いた際に半年前のレポートの未保存の内容が表示されるというケースも見られた.

セキュリティソフトは Windows Defender のみで十分であると考えており、メーカによってプリインストールされていたであろうサードパーティ製のセキュリティソフトはアンインストールした.そのようなものは PC の動作を重くさせるほか、開発の妨げになることもあろう.

WSL 上での GitHub アカウントへのログインは、GitHub CLI をインストールし gh auth login で行った. このとき、.bashrc にて環境変数 BROWSER にブラウザのパスを設定しないとブラウザが開かず、ログインできない.

export BROWSER='"/mnt/c/Program Files/Google/Chrome/Application/chrome.exe"'

.zshrc ではスペースを含むパスを " で囲むだけで良かったが、.bashrc では '" で囲まないといけないようだ.

Figma
#

メンバーに次のことをやるよう催促した.

  • Figma の操作方法の勉強
  • Web 開発に慣れるために自分のサイトを作る
  • Flutter の勉強

やる気のあるメンバーは Figma でどんどんアプリの UI を考えてくれたり、Flutter のハンズオンをしてくれていた.少し希望の光が見えた.

一番簡単であろうという理由で Figma をやることを選択するメンバーもいたが、あまり面白くなく集中力を持続できないようでいた.

設計書の執筆
#

これを書くのが最も大変であった.開発経験もないのに

  • データフロー図
  • フローチャート
  • クラス図
  • データベース設計

を考えねばならなかった.かなり頭のリソースを食う作業であり、一人でデータフロー図やフローチャートを描いて土日を溶かした.かなり精神的に辛かった.フローチャート、クラス図、データベース設計は ChatGPT に任せた.

設計書
#

機能概要
#

  1. プロフィール交換
    • QRコードを用いたプロフィール交換
    • 特定グループ内での一斉プロフィール交換
  2. 履歴保存
    • 交換日時と場所を記録
  3. 複数プロフィール
    • 用途別 (e.g., 学校、職場) の複数プロフィール作成機能
  4. 個人メモ
    • 他人には見えない個人用メモの作成 (覚えておきたい情報、出会ったシチュエーション)
  5. テーマ
    • 見た目をカスタマイズ可能
  6. データエクスポート
    • プロフィール情報の画像やJSON形式でのエクスポート
  7. 検索機能
    • 興味・関心でプロフィール検索、共通の趣味を持つユーザを見つけられる
  8. 先生向け機能
    • 学生の興味を把握し、効果的な授業運営を支援
  9. コミュニティ可視化
    • 所属コミュニティ (e.g., 部活、同好会、寮) の可視化
  10. 興味関心の分析
    • ユーザが提供した画像を AI が読み取って分析する

利点
#

次のような悩みを解決する.

  • 人の名前を覚えられない
  • 自己紹介が苦手
  • 趣味の合う人を見つけたい
  • SNS交換に抵抗がある
  • 人と話すのが苦手
  • 既存の SNS のプロフィールに書ける文字数が少ない
  • 個人サイト開設や GitHub のプロフィール作成はハードルが高い (一般人には)

目標
#

学校祭の来客者100人以上にプロフィールを作成してもらう.

データフロー図
#

本来はレベル \(1, 2, \cdots\) と掘り下げて描くものであろうが….

flowchart LR User[ユーザ] InterestAI([興味分析AI]) subgraph 自分のプロフに関する画面 DisplayMyProfile([プロフ表示]) EditMyProfile([プロフ編集]) SwitchMyProfile([プロフ切替]) subgraph テーマカスタマイズ画面 ThemeList([テーマ一覧]) UploadTheme([テーマアップロード]) end end subgraph 交換に関する画面 GenerateQR([QR生成]) DisplayQR([QR表示]) ScanQR([QRスキャン]) GenerateQR -->|生成されたQR| DisplayQR end subgraph 受け取ったプロフに関する画面 ReceivedProfileList([プロフ一覧]) DisplayReceivedProfile([プロフ表示]) subgraph 検索に関する画面 Search([検索]) SearchAI([検索AI]) DisplaySearchResult([検索結果]) Search --> DisplaySearchResult Search --> SearchAI --> DisplaySearchResult end subgraph コミュニティに関する画面 CommunityList([コミュニティ一覧]) end end subgraph データストア ThemeDB[(テーマDB)] MediaStorage[(メディアストレージ)] GroupDB[(グループDB)] subgraph プロフDB ProfileDB[(プロフ内容DB)] ReceivedProfileDB[(受け取ったプロフDB)] MyProfileDB[(自分のプロフDB)] ProfileDB --> ReceivedProfileDB end end subgraph エクスポート画面 ExportAsImage([画像でエクスポート]) ExportAsJson([JSONでエクスポート]) end subgraph グループに関する画面 GenerateGroupLink([グループ招待リンク生成]) CreateGroup(["グループ作成・編集"]) subgraph グループ分析に関する画面 GroupAnalysisAI([グループ分析AI]) GroupAnalysisResult([グループ分析結果]) end end %% 自分のプロフに関する画面 自分のプロフに関する画面 -->|"自分のプロフ内容"| User User -->|文字列や興味分析に使用する画像| InterestAI --> EditMyProfile EditMyProfile -->|"プロフ内容"| ProfileDB & MediaStorage MediaStorage -->|URL| ProfileDB MyProfileDB -->|"ユーザが保有するプロフ"| SwitchMyProfile SwitchMyProfile -->|"追加・削除"| MyProfileDB & ProfileDB ProfileDB -->|"プロフ内容"| DisplayMyProfile ProfileDB -->|"既存のプロフ内容"| InterestAI ThemeDB -->|"テーマのCSS"| EditMyProfile EditMyProfile -->|"テーマ識別子"| ThemeDB %% 交換に関する画面 交換に関する画面 -->|"QRコードやカメラ"| User ScanQR -->|"相手のプロフ識別子"| ReceivedProfileDB %% 受け取ったプロフに関する画面 受け取ったプロフに関する画面 -->|"他者のプロフ情報"| User ReceivedProfileDB -->|"名前やプロフ識別子"| ReceivedProfileList ThemeDB -->|"テーマのCSS"| DisplayReceivedProfile DisplayReceivedProfile -->|個人メモ| ReceivedProfileDB %% 検索に関する画面 User -->|"検索ワードやプロンプト"| 検索に関する画面 検索に関する画面 -->|"検索結果"| User Search -->|"検索"| プロフDB SearchAI -->|"検索"| プロフDB プロフDB -->|"検索結果"| Search %% エクスポート画面 プロフDB -->|"プロフ内容"| エクスポート画面 GroupDB -->|"グループ識別子"| エクスポート画面 エクスポート画面 -->|"ファイル"| User %% コミュニティに関する画面 プロフDB -->|"プロフに記載された所属コミュニティ"| コミュニティに関する画面 GroupDB -->|"グループ情報"| コミュニティに関する画面 %% グループに関する画面 CreateGroup -->|"グループ識別子"| ProfileDB CreateGroup -->|"グループ情報"| GroupDB User -->|"分析して欲しいこと"| GroupAnalysisAI GroupAnalysisResult -->|"分析結果"| User ProfileDB & GroupDB -->|"グループメンバーのプロフ情報"| GroupAnalysisAI GroupAnalysisAI -->|"分析結果"| GroupAnalysisResult GroupDB -->|"グループ情報"| GenerateGroupLink %% テーマカスタマイズ画面 User -->|"テーマのCSS"| UploadTheme UploadTheme -->|"テーマ情報"| ThemeDB ThemeList -->|"テーマ情報"| ThemeDB ProfileDB -->|"テーマ識別子"| ThemeDB

フローチャート
#

  • システム全体

    ナビゲーションバーはログイン後全ての画面で表示されていることとする.ユーザは任意のタイミングでアプリを終了できることとする.

    flowchart TB Start([開始]) --> IsLoggedIn{ログイン済み} MyProfilePage[[自分のプロフに関する画面]] IsLoggedIn -->|yes| MyProfilePage & NavigationBar{ナビゲーションバー} IsLoggedIn -->|no| LoginProcess[[ログインプロセス]] -->|success| MyProfilePage & NavigationBar NavigationBar --> MyProfilePage & DisplayReceivedProfile[[受け取ったプロフに関する画面]] & Search[[検索に関する画面]] & Group[[グループに関する画面]]
  • ログインプロセス

    ゲストモードの場合、アカウント作成にメールアドレスや電話番号等は不要である.ゲストアカウントは学校祭終了後に削除される.アカウント情報はブラウザに保存される.(Cookie)

    flowchart TB Start([開始]) --> LoginMethodSelection{ログイン方法選択} LoginMethodSelection -->|Google| GoogleAuth LoginMethodSelection -->|Microsoft| MSAuth LoginMethodSelection -->|学認| 学認ログインサービス LoginMethodSelection -->|ゲスト| ゲストモード GoogleAuth & MSAuth & 学認ログインサービス --> IsLoginSuccess{アカウント作成/ログイン成功} IsLoginSuccess -->|no| LoginMethodSelection IsLoginSuccess & ゲストモード --> End([終了])
  • 自分のプロフに関する画面

    flowchart TB MyProfileStart([開始]) --> ViewProfile[プロフィール表示] ViewProfile --> EditProfile[プロフィール編集] EditProfile --> UpdateProfileDB[プロフィールDB更新] UpdateProfileDB --> ViewProfile ViewProfile --> SwitchProfile[プロフィール切替] SwitchProfile --> LoadProfileDB[プロフィールDB読込] LoadProfileDB --> ViewProfile ViewProfile --> ThemeCustomization[テーマカスタマイズ] ThemeCustomization --> ChooseTheme[テーマ選択] ChooseTheme --> ApplyTheme[テーマ適用] ApplyTheme --> ViewProfile ThemeCustomization --> UploadNewTheme[新しいテーマアップロード] UploadNewTheme --> UpdateThemeDB[テーマDB更新] UpdateThemeDB --> ThemeCustomization ViewProfile --> InterestAnalysis[興味分析] InterestAnalysis --> UploadMedia[メディアアップロード] UploadMedia --> InterestAI[AIによる分析] InterestAI --> DisplayInterestResults[分析結果表示] DisplayInterestResults --> ViewProfile ViewProfile --> AccountSwitch[アカウント切り替え] AccountSwitch --> SelectAccount[アカウント選択] SelectAccount --> LoadProfileDB[プロフィールDB読込] LoadProfileDB --> ViewProfile ViewProfile --> QRExchange[QRコードによるプロフ交換] QRExchange --> GenerateQR[QRコード生成] GenerateQR --> DisplayQR[QRコード表示] DisplayQR --> WaitForScan[スキャン待機] WaitForScan --> QRScanned[QRコードスキャン] QRScanned --> RetrieveProfile[プロフ取得] RetrieveProfile --> SaveToReceivedProfiles[受け取ったプロフに保存] SaveToReceivedProfiles --> ViewProfile
  • 受け取ったプロフに関する画面

    flowchart TB ReceivedProfileStart([開始]) --> ViewReceivedProfileList[受け取ったプロフィール一覧表示] ViewReceivedProfileList --> SelectProfile[プロフィール選択] SelectProfile --> DisplayReceivedProfile[プロフィール表示] DisplayReceivedProfile --> AddMemo[メモ追加] AddMemo --> UpdateReceivedProfileDB[受け取ったプロフDB更新] UpdateReceivedProfileDB --> DisplayReceivedProfile DisplayReceivedProfile --> SearchProfile[プロフィール検索] SearchProfile --> EnterSearchCriteria[検索条件入力] EnterSearchCriteria --> SearchAI[検索AI] SearchAI --> ShowSearchResults[検索結果表示] ShowSearchResults --> DisplayReceivedProfile DisplayReceivedProfile --> ViewCommunityList[コミュニティ一覧表示] ViewCommunityList --> DisplayCommunity[コミュニティ表示] DisplayCommunity --> DisplayReceivedProfile ReceivedProfileStart --> ReceivedProfileEnd([終了])
  • 検索に関する画面

    flowchart TB SearchStart([開始]) --> EnterSearchPrompt[検索プロンプト入力] EnterSearchPrompt --> ChooseSearchType{検索タイプ選択} ChooseSearchType -->|通常検索| ExecuteSearch[検索実行] ChooseSearchType -->|AI検索| ExecuteSearchAI[AI検索実行] ExecuteSearch --> DisplaySearchResults[検索結果表示] ExecuteSearchAI --> DisplaySearchResults[検索結果表示] DisplaySearchResults --> SelectProfileFromResults[検索結果からプロフィール選択] SelectProfileFromResults --> ViewProfile[プロフィール表示] ViewProfile --> SearchEnd([終了]) SearchStart --> SearchEnd([終了])
  • グループに関する画面

    flowchart TB GroupManagementStart([開始]) --> ViewGroupList[グループ一覧表示] ViewGroupList --> SelectGroup[グループ選択] SelectGroup --> DisplayGroupDetails[グループ詳細表示] DisplayGroupDetails --> CreateGroup[グループ作成] CreateGroup --> SaveGroupDetails[グループ詳細保存] SaveGroupDetails --> DisplayGroupDetails DisplayGroupDetails --> EditGroup[グループ編集] EditGroup --> UpdateGroupDetails[グループ詳細更新] UpdateGroupDetails --> DisplayGroupDetails DisplayGroupDetails --> GenerateInviteLink[招待リンク生成] GenerateInviteLink --> ShowInviteLink[招待リンク表示] ShowInviteLink --> DisplayGroupDetails DisplayGroupDetails --> AnalyzeGroup[グループ分析] AnalyzeGroup --> DisplayGroupAnalysisResults[分析結果表示] DisplayGroupAnalysisResults --> DisplayGroupDetails GroupManagementStart --> GroupManagementEnd([終了])

クラス図
#

classDiagram class User { +String userID +String name +String email +String profilePicture +List~Profile~ profiles +List~ReceivedProfile~ receivedProfiles +void createProfile(Profile profile) +void editProfile(Profile profile) +void switchProfile(Profile profile) +void uploadMedia(String media) +void scanQRCode(String qrCode) +void saveReceivedProfile(ReceivedProfile profile) } class Profile { +String profileID +String userID +String name +String bio +String interests +String themeID +void updateProfile() } class ReceivedProfile { +String profileID +String userID +String receivedFromUserID +String receivedDate +String memo +void addMemo(String memo) } class Theme { +String themeID +String themeName +String css +void applyTheme() +void uploadNewTheme(String css) } class InterestAI { +String aiID +String inputMedia +String analysisResult +String analyzeInterest(String media) } class Group { +String groupID +String groupName +List~User~ members +void createGroup(String groupName) +void addMember(User user) +void analyzeGroup() } class GroupAnalysisAI { +String aiID +String groupID +String analysisResult +String analyzeGroup(String groupID) } User --o Profile User --o ReceivedProfile User --o Group User --> InterestAI Profile --> Theme Group --> GroupAnalysisAI

データベース設計
#

erDiagram ACCOUNT { String accountId PK String name String email String authProvider } PROFILE { String profileId PK String accountId FK String displayName String displayDepartment String myHeart String profileImage String hobbies String description String community } DEPARTMENT { String departmentId PK String name } VISITSCORE { String visitScoreId PK String visitorId FK String destinationId FK int score Date visitDate } MEMO { String memoId PK String profileId FK String content Date createdDate } THEME { String themeId PK String accountId FK String themeData } ACCOUNT ||--o| PROFILE : has ACCOUNT ||--o| DEPARTMENT : belongs_to ACCOUNT ||--o| VISITSCORE : visitor PROFILE ||--o| VISITSCORE : destination PROFILE ||--o| MEMO : has ACCOUNT ||--o| THEME : uses

ガントチャート
#

gantt dateFormat YYYY-MM-DD section 行事予定 前期中間試験 :2024-06-06, 2024-06-12 前期期末試験 :2024-08-02, 2024-08-08 夏季休業 :2024-08-09, 2024-09-29 学校祭 :2024-11-02, 2024-11-03 section チーム開発授業予定 第1回発表 :2024-05-24, 1d 5月月例報告書 :2024-05-31, 1d 中間発表, 6月月例報告書 :2024-06-28, 1d 月例報告会, 7月月例報告書 :2024-07-26, 1d ポスター :2024-10-25, 1d section 勉強 Windows 11 への更新, WSL :2024-05-17, 2024-05-24 Figma で UI デザイン :2024-05-17, 2024-07-10 個人サイト制作 (不慣れな者がやる) :2024-05-17, 2024-07-10 Flutter 基礎勉強 :2024-06-12, 2024-08-01 AWS 基礎勉強 :2024-07-01, 2024-08-01 section 開発 基本的な画面と機能を実装 :2024-07-01, 2024-09-10 基本的なクラウド関連の実装 :2024-08-10, 2024-09-10 追加の画面と機能とクラウド関連を実装 :2024-09-11, 2024-10-15 フィードバックを基に改善 :2024-09-15, 2024-10-20 section テスト 複数の学生に使用してもらう :2024-09-11, 2024-09-30 section 運用 アプリ運用 :2024-09-05, 2024-11-10 複数の学生、教職員、来客者にプロフを作ってもらう :2024-10-20, 2024-11-03 ゲストアカウントのデータを削除 :2024-11-08, 2024-11-10

リスク
#

現状として次のような問題を抱えている.

  • チーム開発の提出物を作成するのに多大なる時間を奪われる
  • 他の科目の提出物に手をつけられない
  • 他の科目の復習を行う時間をとれない
  • 他の科目の授業中にもチーム開発の提出物に手を付けている
  • チーム開発の提出物を1人で書いている
  • 負担の偏りが生じている
  • チームでの話し合いがほとんど踏襲されておらず、かつ陳腐な作品を作るが故にチームのモチベーションが低い
  • 本チームはもともと形成されていた「仲良しグループ」ではないが故にチームのモチベーションが低い
  • PCへの馴染みが薄いメンバーもおり、実際に開発を始めるまでのハードルが高い
  • チーム内での議論が消極的
  • チーム開発に絶望感が漂っている
  • チーム内でのコミュニケーションが少ない
  • 開発経験のあるメンバーがいない
  • リーダーのチームを導く能力が低い
  • 難易度の高さ故に集中力が低下する

次のようなリスクがある.

  • 鬱病を発症する
  • マイナス思考の膨張による休学、退学、世逃げ、自殺
  • 精神状態の悪化により過ちを犯し、学校が損害を被る
  • メンバーが減る
  • チーム開発が個人開発に転じる
  • 様々な科目において提出物の未提出が発生する
  • 成績不振に陥る
  • 作品が未完成に終わる

次のような対策が考えられる.

  • 完成した提出物をチーム内で共有する
  • チーム内での勉強の教え合いを活発にする
  • スクールカウンセラーに相談する
  • 「進級さえできれば良い」と割り切る
  • 実装するものについて優先順位をつける
  • 「この程度のアプリも作れないようでは社会のお荷物となる」ことを自覚する
  • 外部の人間に開発を依頼する
  • 外部の人間をチームに招いてサポートを乞う
  • 定期的にミーティングを開く
  • 個々人の責任を明確にする
  • 常に穏やかでいることを努める
  • チーム一人一人が話しやすい環境の構築に努める
  • コミュニケーション能力を高めるよう努める
  • 完璧を目指し過ぎない
  • 恐れることなく先生に相談する
  • 生成AIを積極的に活用する
  • 以前よりも難易度が大きく下がっていることを理解する
  • 自分がどれだけ甘えた人生を送ってきたか自覚する
  • チーム開発の経験が出来ることに感謝する
  • チーム開発を乗り越えた先にある「自身の成長」を志す

実力の差は努力の差
実績の差は責任感の差
人格の差は苦労の差
判断力の差は情報の差

真剣だと知恵が出る
中途半端だと愚痴が出る
いい加減だと言い訳ばかり

本気でするから大抵のことはできる
本気でするから何でも面白い
本気でしているから誰かが助けてくれる

発表
#

5月下旬にクラスメート達と学科の先生方の前で、作品概要の発表を行った.

質疑応答にて次のようなご指摘があった.

  • どうやって皆に使ってもらうか
  • プライバシー的に問題がないか
  • 既存の名刺交換サービスとどのように差別化を図るか

学校祭にて来客者100人以上にプロフィールを作ってもらうことを目標としているが、これをどうやって実現するか良いアイデアは浮かんでいない.交換した数においてポイントを付与し景品が当たるようにするという考えもある.プライバシーについて、プロフィールは交換する相手に応じて複数作成することができること、また既存のメッセンジャーアプリ内での個人情報共有は個人間の信頼感に委ねられていることより問題ないと考えている.

絶望チーム開発日記 - この記事は連載の一部です
パート 2: この記事