高校の課題研究で素人４人がAndroidアプリ作ったので過程と反省をまとめる

Androidアプリを私含め４人で作った過程でいろいろあったのでまとめます。  
問題続出だけど私は楽しかった。  
これから似たようなことする人はぜひ生かしてね！

# 課題研究とは
私の通う埼玉県立越谷総合技術高校では、３年４月から１月まで**課題研究**という
「学科で学んできたこと活かしてチーム組んでなんか作って発表してね」
という趣旨の課題が出されます。  
私は情報技術科でしたので、PCやスマホ用のソフトウェアやゲーム、Webサイト、動画編集などをすることが多いようです。  

:::note warn
この記事は、越谷総合技術高等学校公式のものではありません。
:::

# 作ったアプリ  
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/7b46adde-4143-3a1d-d135-9f6142cf92ec.png">

Ewiseという、英単語学習を目的としたアプリになります。
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/31d96978-3dc2-9814-c163-d280c4a8fd3c.png">
こういう英単語を暗記するやつありますよね。
これをカメラで英文を撮影するだけでアプリ内に作成できます。

<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/431d4a42-1ebb-7333-4a58-d0094447159e.png">

<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/986172e3-0f03-e61e-d2cb-eb05da9486a1.png">
<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/50005b98-0044-2353-38fd-cfa5228a37cd.png">
<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/3a904b66-d6f2-c633-f6ff-ceaf780c4a5f.png">  

Android7.0以上で動作します。ぜひダウンロードしてみてください！

https://sousiomine.github.io/Ewise/

# 完成までの過程  
当時の状況を、私目線でざっくりと書いていきます。  

## 春
班員を最初に決めます。  
私と私の友人３人の計４人に決まり、以後Discordグループでもやり取りします。  
ちなみに班の名前は**放課後アイティータイム**に決まりました。
情報技術科はプログラミングを専門的に学習する学科なので、課題研究が始まった時点で全員がC言語とC#、WindowsFormsやSQL、HTML等を浅く学習しています。  
それに加え私はちょっとだけGitとGitHub、もう1人にはちょっとだけUnityでのゲーム開発経験がありました。  

課題研究での作成物はなんでも良いわけではなく、先生からの審査があるため、計画を提出しプレゼンをする必要があります。  
そのうえ大会への作品出品や具体的な日程が要求されこれが結構大変。  
何度も審査に落ち、以下のような大まかな内容にまとまりました。  

- Androidスマートフォン用の英単語帳アプリ  
- AndroidStudio & Javaで開発する  
- 8月末締切の「第10回スマートフォンアプリコンテスト」に応募  
- Amazonアプリストアにリリース  

プレゼンの際にはこのような画像を用意していました。夢がありますね。  
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/28698064-e822-375f-8388-4d435d1b3c43.png"><img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/bc31b1d7-67be-0d6b-3d44-bafa51a4d8de.png"><img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/0848c84b-89ed-1312-b4b7-55b662e104b2.png">

今、というか当時も薄々感じていましたがこの時点で**問題点**が複数存在しました。  

<dl>
    <dt>Androidスマホでしか動かない</dt>
    <dd>先輩がAndroidStudioを使っていたことや先生の薦め、スマホアプリ開発の知識の乏しさからのAndroidネイティブアプリ開発の選定でしたが、この班にはAndroidスマホをメイン利用しているのは私しかいません。<br>
    私以外のモチベーション低下につながります。</dd>
    <dt>スケジュールに余裕がなさすぎる</dt>
    <dd>決まってからコンテスト提出までたった３ヶ月半！<br>
    ３年生なので進路活動も必要です。</dd>
    <dt>技術力不足</dt>
    <dd>前述した通りJavaやAndroidStudioを触ったことなんてありません。
    私以外はGit使ったこともありません。<br>
    以後トンデモコードを量産することになります。</dd>
    <dt>学校の劣悪な開発環境</dt>
    <dd>複数人である程度複雑なアプリを作るのに必須なGitとGitHubですが、学習していないばかりか学校でそもそも<b>使うことができません</b>。<br>
    埼玉県教育ネットワークの規制に引っかかってGitHubとssh通信ができないんですね。<br>
    さらに審査担当の１人にGitの使用に反対する先生がおり、機嫌を損ねぬよう、先生に提示した日程でGitについての記載を見送りました。</dd>
</dl>

これらの問題に対し  
- 6月までにGitを通話しながら勉強して使えるようにする  
- 学校ではコードを書かず、基本家でコーディングを行う  
- 分からなかったらChatGPTか僕に聞いて！

とだけ決まり、遅れながらも開発が始まりました。  

ここで５月半ば、ここからからGitのGUIクライアントを使って、画面共有と通話でGitの使い方を共有しました。  
ただここでGUIクライアントのバグ？を踏みプライベートリポジトリのクローンができず

https://community.atlassian.com/t5/Sourcetree-questions/Sourcetree-for-Mac-GitHub-account-permissions/qaq-p/961120

かなり時間を取られてしまいました。  
Javaの勉強も、C#と文法が似ているとはいえあまり順調には進まず...

これと並行して画面遷移図を作成し、それを用いて各人がどこを担当するかも決めました。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/07f87110-2a7f-3455-0fc1-d3daae534ee7.png)
これを画面遷移図と言っていいのかは知らん  

アプリの機能をおおまかに２つに分類し
2人2チームで分担

ということになりました。  
もちろん各分担２名中１名しか作業しないということが頻発しますが後述...  

## 6月
一応私は班の中で一番プログラムが書けたので、一足先に作業に入りました。  
内容は「英単語の情報を格納するアプリ内データベースの構築」です。  
これから作っていく機能の基礎となるので最初に開発しなければなりません。

AndroidStudio用のデータベースライブラリとして[Room](https://developer.android.com/training/data-storage/room?hl=ja)というものがあり、今回はそれを利用することにしました。
しかし、このRoomというライブラリはUIスレッドで動かそうとするとコンパイルを受け付けない仕様になっており、必ずUIスレッドとは別のスレッド、つまり非同期処理で動かさなければいけません。  
もちろん非同期処理なんて全員全く習っていないので、私はデータベースへの非同期アクセスを同期処理っぽく使えるヘルパークラスを用意することで、データベースの中身を簡単に引き出したり挿入したりできるようにしようと構想しました。が、私自身も非同期処理なんて初めてでうまくいくはずもなく...  

こうしてクソコードが生み出されました
例として、単語帳型のBookクラスで見てみましょう
```java
        //単語帳インスタンスをつくる
        Book b = new Book("book", 20230611);
        //データベースヘルパーのインスタンスをつくる
        BookAsyncHelper  bookAsyncHelper = new BookAsyncHelper(this);
        //挿入
        bookAsyncHelper.insert(b);
        //データベースの単語帳をリストで全部取得
        bookAsyncHelper.getAllBookList(bookList);

        //bookListを使う処理を書く
        
```

単語帳インスタンスのbを、データベースに登録し取得するコードに見えます。  
しかし、３行目のinsertは実は非同期処理であり、この行が実行されてもbの挿入がデータベースに反映されているかは保証されません。
この例では挿入直後にgetで取得していますが、ここで**bが帰ってくるか保証は全くありません**。
それどころか、コールバック関数が存在しないため、**いつデータベースにbが反映されたかを感知する方法がありません**し、なんならgetAllBookListも非同期処理なのですが、**いつbookListへのデータ格納が完了するのか分かりません**。

え？じゃあbを挿入した後の単語帳リストを取得するにはどうしてたの？
こうです
```java
        Book b = new Book("book", 20230611);
        BookAsyncHelper  bookAsyncHelper = new BookAsyncHelper(this);
        bookAsyncHelper.insert(b);
        bookAsyncHelper.getAllBookList(bookList);
        
        try {
            //100ミリ秒フリーズさせる
            Thread.sleep(100);
        } 
        catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        //bookListを使う処理を書く

```

#### は？？？？  
「終わるタイミングがわからないなら、確実に終わるまでフリーズさせよｗ」と  
いやこれもたまに取得失敗してバグります。
無知故信じられないコードができました。  


**でも大丈夫！班で開発しているわけですから、こんなプルリクエストを投げても修正し合えばいい！**  
とは、なりません...  

このゴミヘルパークラスは長い間使われ続け、私が最低限の非同期処理の知識を獲得して根本的修正を行うまで半年近く放置されることになりました。  

## 7月

### プルリクエスト機能しない問題  
プルリクエストは、コードに不良やバグがないかを確認すると同時に、レビュアーが変更内容を理解しコードの属人化を防ぐことを期待して行われるものだと認知しています。  
**しかし、放課後アイティータイムでは違った...**

まず、私含めこの班全員、他人のコードをレビューする能力がありません。
正直プルリクエストごとに３人がレビューするやる気もない。  
こういう学校の課題であんまりきつく縛るのもどうかと思ったので

- プルリクエストが出たら班の**誰か１人**が「確認」する
- 「確認」は**バグがないかのチェック**を目的とする
- プルリクエストを出したらDiscordグループに貼る

ということに決めました。
CI/CD（自動でビルドやテスト、リリースする仕組み的なや）を構築することができなかったので、まんまその役割を人間でやる。ということに留まりました。
するとどうなるか

- 誰が確認するのか不明瞭なので何日もプルリクが放置される
- 動いていれば変更箇所をそんなに読まないので、変更の意図は書いた奴しかわからず属人化

といった状態に陥りました。
さらにプルリク処理に時間がかかるので、時が経つにつれどんどん複数の変更を１つのプルリクエストでするようになっていきプルリクエストの巨大化が進行、またコードの意図を考えない変更によって悪循環が発生！  

### コンテスト開催中止  
「第10回学生スマートフォンアプリコンテスト」への応募に間に合わせるようスケジュールを組んでいたのですが、公式サイトにて、今年度は開催しない旨の更新がありました。  

http://contest2022.sig-cds.net/

代わりに先生からの薦めで、「令和５年度 第３２回 [埼玉県工業高校生プログラミングコンテスト](https://www2.spec.ed.jp/krk/kogyo/saikouken/%E3%82%B3%E3%83%B3%E3%83%86%E3%82%B9%E3%83%88/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E3%82%B3%E3%83%B3%E3%83%86%E3%82%B9%E3%83%88)」のプログラミング部門に出場することになります。
このコンテストの作品提出期日は9月8日、ちょっとスケジュールに余裕ができて一安心。
しかし...

#### このタイミングでマインクラフトにハマります

？？？？？？？？？？
みんなでマイクラサーバー建てて7月は遊んでました。
楽しかった

**読んでて頭が痛くなってきた？** もうちょっと続きます  

## 8月～9月
コンテスト提出期日に間に合うよう、9月5日にはこれこれこういう機能を実装して発表できるクオリティにしようと決まり、やっと目立った進捗が出始めます。  
またこのへんで、2人2チームで分担してると片方どちらかが作業をサボることに気づき、1人1つずつ明確な役割を決めて実装を進める方向へ転換します。
しかし、時すでに遅し...

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634181/59429339-072a-85d9-806c-a259da7ed74f.png">
<br>
8月12日時点での単語帳画面 全然できてない！  

なんだかんだ私は、９月初めにはコンテストまでの担当範囲を完遂できました。   

が、みんなそう順調に進むわけでもなく、特に進捗が悪い班員が2名いました。
ただあんまり強く言うのもあれだし...

...

### 9月5日 締切寸前
<b>2人の担当箇所の進捗はそれぞれ50%くらい！</b>
片方は私が大急ぎで残りをやって間に合わせましたがもう一方は間に合わず...
目標未達でしたがまあ動くので提出！ 

## 秋
進路活動で忙しく、ほとんどコードは書いていません。

学校で進捗を報告する「中間発表」が10月に
埼玉県工業高校生プログラミングコンテストが11月にあり、やったのはその発表準備のみ。
結果同コンテストでは、優秀賞を獲得できました。

https://www2.spec.ed.jp/krk/kogyo/saikouken/blogs/blog_entries/view/72/9e80b5eed51428cca9cff87914eb506c?frame_id=114

また、スプレッドシートで「今後作るもの」リストを共有ドライブに作成して、進捗を0～100で、担当者と内容をまとめるようにしました。

## 冬
申請するリソースが確保できないため。Amazonアプリストアへのリリースは諦めました。
その分機能のさらなる拡充やデザインの改修、リファクタリングに力を入れました。
前述したゴミヘルパークラスの修正で、ヘルパークラス由来のバグがすべて解消されたのもこの時です。
他のみんなもいろいろ実装し、目標をだいぶ引き下げつつもなんとかアプリが完成しました。

また[アプリを配布する簡易的なWebサイト](https://sousiomine.github.io/Ewise/)も用意し、発表後にダウンロードしてもらえるような体制を整えました。

### 課題研究発表
1月18日に、今までの課題研究の成果を学校内で発表します。

<b>そこでミス発生！！！</b>
発表時に実演を行うのですが、実演に使用したタブレット端末は学校のネットワークに接続されていました。
そして翻訳APIで英単語の意味を用意する際、学校間ネットワークの制限で翻訳APIと通信できずにロードが永遠に終わらない！
実演を予定通り進めることができなかったのです。

最後にQRコードを出してぜひダウンロードしてね！と言ったものの記事公開時点で1回もダウンロードされていません。涙が止まらない

発表後も作業を続ける班もあるのですが、放課後アイティータイムでは、発表後はなにがあっても課題研究は終了と決めていたため、これにて課題研究は終わりました。㊗️

<br>
ここまで読んでくれた方はツッコミだらけかもしれません。

# どうしたら問題点を回避できたか？
本題かも？

### そもそもAndroidネイティブアプリという選定があかんかった  
班員がiPhoneユーザーばかりなのにAndroid専用アプリというのは、やはりモチベーション低下に大きく関わってきたと思います。
当時の班員みんなReactNativeやFlutter等のマルチプラットフォームな開発を知らず、仮にそれらを採用していたとしても、情報量や学習曲線の問題もありますし、そもそも班員みんなマトモなMacを持っていなかったのでiPhone用アプリをビルドできません。
それでも、せめてWebやWindowsで動くようなフレームワークを採用していればと後悔しています。

もし今の私が技術選定をするなら、おそらくFlutterかAvalonia、MAUIのどれかを選択していたと思います。

### 技術力が圧倒的に足りない
正直これはどうしようもなかった
決して放課後アイティータイムの班員が無能なわけではありません。むしろ情報技術科内では比較的技術力はあったほうだと思います。
課題研究で要求されるレベルが、今までの学習内容と比較してあまりにも高すぎたのだと思います。

技術力はChatGPT-Plusを契約することでお金で即買えるようになりました。
しかし、月額2800円は高校生には出せない。

### 班員のケツを叩けばよかった
班員も友人なので、作業に遅れが出ていたりサボっていても強く言えませんでした。
が、これから友人となにか作ろうとしている人のために書きます。
**ケツは叩け！**
強く言って空気悪くならない？まあなるけど
なるけど完成しないほうが空気悪くなるから！
ちゃんと自分は仕事した上でならば、まあどうにかなるんじゃないですかね？
（といいつつ私もギリギリでしたが...）

:::note warn
友人関係が崩壊しても責任を取りません
:::

### GitHubの使い方は...どうだろう
問題だらけのGitHub運用でしたが、当時の私たちの全力でした。
もしも今くらいの知識があれば、頑張ってGitHubActionsでの自動ビルドくらいには手を出していたかもしれないけどね！

コードの属人化問題も、[CodeRabbit](https://coderabbit.ai/ja/)というツールを使うと無料でプルリクエストの要約まではやってくれるそうなので、今からやる人は試してもいいと思います。

### 発表練習はちゃんとやろう！
発表前日の練習は、画面をプロジェクターでミラーリングするだけで終えてしまったために、通信できない問題に気が付きませんでした。
みなさんは必ずは１回その場で通しで練習しましょう。

# 良かったこと
### Gitを無理やりにでも使って良かった
Gitの使用に反対した先生の意見に流されず、Gitの使用を強行してよかったです。
もしGitを使っていなければGoogleDriveでやっていたのでしょうか？間違いなくプロジェクトが崩壊していたと思います。

### 使えるアプリが完成した
私以外の班員は使えませんが、私はAndroidユーザーなので使えます。
たまに起動してはニヤニヤしています。

（ただし、私は英語が苦手なため英単語学習はせずそっとアプリを閉じます）

### 技術的な進歩
課題研究のおかげでAPIや非同期処理等、様々な技術に触れることになったので、なんやかんやプログラムを作る能力は相当向上したと思います。

### 進路活動で使えた
詳細はあんまり書けませんが、進路活動にはかなり役立ったのではないでしょうか。

### 貴重な経験をできた
高校の友人と一緒にアプリ作るなんて、普通はよっぽどの条件がそろわないと難しいはずです。
そもそも開発ができる性能を持ったパソコンを、みんながみんな持っているわけではありませんからね。
私は幸運なことにそんな経験ができてしまいました。

### 楽しかった
少なくとも、私は課題研究でなにか作っているときはとても楽しかったです。

#### その他
放課後アイティータイムという班の名前は非常に気に入っています

# 最後に
課題研究で作成したアプリ、ぜひダウンロードしてみてください！！！

https://sousiomine.github.io/Ewise/