Flutter初見が5日間のハッカソンでアプリ開発してきた

## はじめに
この記事はコロナで外出自粛ムードの中、 `#おうちハッカソン` なるものでFlutterアプリ開発をしてきたのでその体験記になります。

自分 [@hohohoris](https://twitter.com/hohohoris)の簡単なプロフィールとしては、

- サイバーエージェント21年度入社予定
- Androidエンジニア
- プログラミングを初めて1年3ヶ月、Android以外のプラットフォームでの開発経験はない
- もちろんFlutter初心者

という感じです。


## おうちハッカソン

https://connpass.com/event/174573/

外出のできないGWにせっかくだからハッカソンしようじゃないかということで、インターン先でメンターをしてくれている [@at_sushi_at](https://twitter.com/at_sushi_at)さんが主催されていました。


自分も暇だったのと、複数人で開発する中期間のハッカソンに参加したことがなかったためこれを機に参加してきました。

そして、内定者先で一緒に出る人を募集したところ20人も集まってびっくりしました。
会社の風土にマッチした、やる気と熱意と積極性がある人たちばかりで、入社するのがさらに楽しみになりました。
内定先では、コロナで内定者同士交流ができずに、リモート飲み会やイベントを企画しているところだったので、良い交流の機会にもなったと思います。

なにより、人事の[@masagotty](https://twitter.com/masagotty)さんが慣れないながらもキャッチアップしつつ、自分のチームに入ってくれたのが驚きでした。  
良い意味で垣根が低く、なんでもやる良い会社だなあ。

お題は、 **お家で楽しめるなにか** です。
期間はGW中の5日間でしたが、フルで稼働してもいいし、2日だけ開発して最終日少し発表するのでも構わないというコンセプトだったため、ゆるーく楽しめるようになっていました。

...のはずだったのですが、どうせなら良いもの作りたいよねというエンジニアの意地で睡眠時間を削って開発しているチームが多かったように感じます。

自分たちのチームも例に違わず睡眠時間を削って最後まで粘ってました👀


**リモート開催**だったので、モチベーションの意地とチームワークをいかにとるかが重要になっていた印象でした。


### 作ったアプリ
今回作ったアプリは、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/d767adb9-0f42-d093-743d-ef90ceb86ee7.png)
なアプリです。

`大改造!!劇的BeforeAfter` のパロディです笑

コロナで外出自粛中、掃除のモチベーションをあげるSNSチックなアプリです。
<img width="250" alt="スクリーンショット 2020-05-07 22.49.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/495cde72-1405-7558-5abc-c6f314633efa.png"><img width="250" alt="スクリーンショット 2020-05-07 22.49.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/c4d3639f-e035-1a11-55d6-fecc85d309a4.png"><img width="250" alt="スクリーンショット 2020-05-07 23.02.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/989b04bb-f858-de96-aefd-aad6972e6a12.png"><img width="250" alt="スクリーンショット 2020-05-07 22.49.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/884643e2-fb80-9e7f-c962-50f05e74c6b6.png"><img width="250" alt="スクリーンショット 2020-05-07 23.02.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/08068421-46a0-0f84-d126-1f03c98c12ab.png">

概要としては、掃除をするBefore画像と、掃除をした後のAfter画像をタイトルや本文と共に投稿して、他の人と共有するアプリです。

1番の推しポイントが画像ではお見せできないのが残念ですが、

**詳細画面で、Before画面とAfter画像が徐々に切り替わっていくアニメーションともに、バックグラウンドで劇的BeforeAfterのBGMが鳴るようになっています。**

まだまだ開発途中ですが、

- ログイン・ログアウト
- 一覧表示
- カテゴリー検索
- 投稿作成
- 投稿詳細表示
- シェア
- いいね

という、必須要件はハッカソン中に実装することができました。

### 何故Flutterか
今回のチームメンバーが得意としていた領域が、

- iOS、サーバーサイド
- Android
- Android
- サーバーサイド
- 人事

でした。
最後が特殊な領域で面白いですねw

今回、人事のスキルを発揮できる場面はなかったですが、プライベートでGoとFlutterを勉強されているとのことでした。
iOS、Androidができるメンバーがいるので、どちらもネイティブで作ることも考えたのですが、せっかくのハッカソン、みんなで協力し合いながらレビューもしたいというモチベーションがあったためFlutterを選定しました。

自分の周りの強いAndroidエンジニアの方もFlutterエンジニアにジョブチェンジしていたり、公式ドキュメントがしっかりして体系的に入門できることや、googleが後ろ盾であるこれからアツいクロスプラットフォームということも選定材料になっていました。

まとめると、

- フロントメンバーの得意な領域が異なった
- 互いにコードレビューしつつ教え合う環境でハッカソンに挑みたかった
- 体系的に学べるサイトある
- これからアツい

という感じでした。

## Flutterのキャッチアップ
人事、学生含めそもそもFlutterなんてほぼ触ったことはありません。
ハッカソンは5日間です。

時間がない中で効率よくキャッチアップしつつ、サービスを完成させる必要があります。
そこで、今回我々が **Flutter初心者** から5日間でアプリを形にできるようになった道標を簡単に紹介できればと思います。

### 参考にしたサイト/アプリ
#### udemy
[The Complete 2020 Flutter Development Bootcamp with Dart](https://www.udemy.com/course/flutter-bootcamp-with-dart/)

動画でFlutterのサンプルアプリを数個作る教材です。
講師の方はロンドンのProgramming Bootcampの主任とのことで、とても教えるのがうまく、モーショングラフィックスを用いて視覚的にもわかりやすく教えてくださるので、とてもおすすめです。
ただただアプリを作るだけでなく、FlutterのWidgetツリー、オブジェクト指向等、概念的な話も多くあり、体系的に学べます。

英語もゆっくりでわかりやすいでのすが、28時間ほどあるので、ハッカソン中に全部見ようとすると時間が全然足りません。
普段から少しずつ見ていくと良いかもしれません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/62fdf917-ca83-a33d-3981-4a271de13447.png)

#### Advent Calendar
[Flutter 全部俺 Advent Calendar 2019
](https://adventar.org/calendars/4140)
[@itometeam](https://twitter.com/itometeam) さんはFlutterに関して、Advent Calendarを全部1人で書き切った猛者です。
この方は以前のインターン先で自分のメンターをしてくださっていました。
そしてAndroidからFlutterメインで活動をしている方の1人です。

内定先、猛者多すぎ...そしてその猛者たちにメンターをしてもらっててすごくありがたい...


このAdvent CalendarもFlutterに関して体系的に説明してくださっていますが、内容は少々高度な部分もあるため、ある程度他のプラットフォームの知識がある or Flutterの基礎をなんとなく理解している状態で、一通り読んでみるとすごく知識がつくと思います。

Flutterの概要、Widget Treeの話、状態管理、テスト、Flutterの設計等、網羅的に書かれています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/ca68fb16-f1ff-9df7-8c3d-b46f85cca06a.png)


他にも、[Flutter Advent Calendar](https://qiita.com/advent-calendar/2019/flutter)でいろんな方の知見が公開されているので、眺めてみても良いかもしれません。

#### 記事

[Flutterの効率の良い学び方](https://medium.com/flutter-jp/flutter-learning-c5640c5f05b9?source=---------31------------------)
では題目の通りFlutterの効率の良い学び方が書いてあるので、結構参考にさせていただきました。

[Flutter初めの一歩](https://medium.com/flutter-jp/first-step-9b7f2c74fb08)
で、Flutterプロジェクトを立ち上げた時のデフォルトで生成されたアプリのコードを詳しく解説してくださっています。

これらの記事の筆者である [@_mono](https://twitter.com/_mono?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed&ref_url=https%3A%2F%2Fcdn.embedly.com%2Fwidgets%2Fmedia.html%3Ftype%3Dtext%252Fhtml%26key%3Da19fcc184b9711e1b4764040d3dc5c07%26schema%3Dtwitter%26url%3Dhttps%253A%2F%2Ftwitter.com%2F_mono%2Fstatus%2F1023820774610591745%26image%3Dhttps%253A%2F%2Fi.embed.ly%2F1%2Fimage%253Furl%253Dhttps%25253A%25252F%25252Fpbs.twimg.com%25252Fprofile_images%25252F476454722593771520%25252FgoSBw3js_400x400.png%2526key%253Da19fcc184b9711e1b4764040d3dc5c07)さんの記事はとてもわかりやすいので是非みてみてください。

#### アプリ
[Flutter Catalog](https://apps.apple.com/jp/app/flutter-catalog/id1458332586)
これはWidgetの一覧と実装コードが簡単に見れるアプリです。
Storeにリリースされているので、インストールして、手元で動かしながらみることができるのですごく良いです。

<img width="300" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/c9a366d5-ae4e-9d95-36b8-7257294fea3c.png">

#### 公式youtube
[公式youtube](https://www.youtube.com/watch?v=9hltevOHQBw&list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG)

1分程度でわかりやすくWidgetの紹介をしている公式が運用しているyoutubeのPlaylistです

### キャッチアップしつつのハッカソンの進め方
**基本的にDiscordを繋ぎながらタスクの分配、議論、質問を行う形**で開発していました

冒頭でも述べた通り、リモート開催のハッカソンだったため、いかにモチベーションを保つかと、チームメンバー同士のコミュニケーションをどうとるかが肝になってくると思っています。

zoomだと無料枠では3人以上で40分以上通話することができませんが、**Discord**ならslackライクなUIで、かつ `通話/画面共有/ボイスチャット分割` ができるので、5日間、開発する時はだいたい繋げてもくもく会をしていました。
youtubeから引っ張ってきてBGMをボイスチャンネルに流すbotがあったり、人ごとにボリュームを変えられるのでBGMの音量調節も自由で良きです。

ハッカソン用のslackもあったため、

- 重要な議論のログや記事共有、CIやPRのログの通知は `Slack`
- もくもく会、簡単な議論/質問は `Discord` 

 という棲み分けをしていました。


#### 1日目

**アイデアソン**
[miro](https://miro.com) という、オンラインでホワイトボード的な画面を共有でき、マインドマップや付箋をリアルタイムに編集できるツールを用いてアイデアソンを行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/48559ec2-434f-d60e-8df2-7df602b6d825.png)

1. マインドマップを使い、ブレインストーミングを行いました。ひたすら **おうち** や **コロナ** に関してのワードを書き殴る
2. マインドマップに書かれたワードから連想されるものや、単語の組み合わせで浮かんだアプリのアイデアを付箋に書く
3. ローテーションで、自分の書いたアイデアの概要を話す。このとき、他の人は、アイデアを聞いてさらに自分の付箋に新しいアイデアを書いたり、「これあったらいいよね」などと話を広げていく
4. KJ法的に、似たようなアイデアをまとめ、絞り込んでいく

この順序でアイデアソンは進行ました。
幸いなことに、かなりスムーズにアイデアが出てきて、作るものも一瞬で決まりました。
このハッカソンで作るものだけでなく、次作りたいサービスのアイデアも出たりして、すごくよかった。


**Flutter学習**

1日目はほとんど各自学習でした。
上記であげた記事や動画、そして書籍等で勉強し、サンプルアプリを手元で動かしてコードやプラットフォームの概要に関して学ぶ期間です。
この段階でも、質問があればDiscordで気軽に話す感じです。

自分のFlutterの進捗的には、
画面から、ボタンやテキストなどのコンポーネントが全てWidgetで構築されることに戸惑い、まだFlutterの書き方に慣れずにいました。
**`Stateless Widget` と　`Stateful Widget` の違いをなんとなく理解して、状態の更新をなんとなくできるようになった程度**です。

#### 2日目

**Flutter学習**
2日目はそれぞれ、なんとなく雰囲気を掴んできた時期です。
ここで、 `InheritedWidget` の存在を知り、親Widgetや、別treeにいるWidgetとの状態の同期をなんとなくできるようになってきました。

この段階で、それぞれが担当する画面のレイアウトの実装に入っていきます。ロジックの含まれないUIは慣れてきた頃です。

**開発環境**
開発環境は [@ry_itto](https://twitter.com/ry_itto) がこの時期に徐々に整えてくれていました。
最終的な流れは下図の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/44befd74-14b6-b6dc-27e4-34df760b5935.png)

始め、CI/CDツールとして GithubActionsを使ってくれていたのですが、RepositoryがCAの同期で共有するためにつくられたOrganizationだったため無料枠が足りなくなってしまいました。
(Organization単位で無料枠が割り当てられてることを知らずに自分のチームがほぼつかいきってしまったようで...申し訳ないことしたねって笑いました)

また、デプロイ先は初めDeploygateを試してくれていましたが、デプロイされたDeploygateのURLをPRにコメントするのがうまくいかず、Firebase AppDistributionに乗り換えました。
(DeploygateのURL or 末尾のハッシュの取得方法わかる方いれば教えてください)

iOSとAndroidのビルドが走るため、1ワークフローあたりの時間が結構かかっていた印象があります。
ハッカソン中にはできませんでしたが、今後やりたいこととしては

- iOSアプリもApp Distributionにデプロイしたい(今はAndroidだけ)
- DangerでdartLintに関するコメントを自動でさせたい
- スナップショットテスト
- ビルドの効率化

という感じとのことです。


#### 3日目
**Flutter学習**
3日目に理解が大進歩して、一気に開発が進みました。
アーキテクチャをBLoCにするか等いろんな記事を漁ったり、議論をしていましたがこの段階で `ChangeNotifier + Provider` を使うことに決めました。

1〜2日目までは、UIとロジックをうまく分離できていなかったのですが、Providerパッケージを用いてChangeNotifierをDIすることでうまく分離できるようになりました。
最初まではProviderがなんのことか理解が追いついていなかったのですが、

**ChangeNotifierはViewModelとLiveDataだ** というように考えることで一気に点と点がつながった感があります
（この表現は厳密には正しくないので、正しい知識は他の記事をみていただければmm）
画面単位でChangeNotifierを継承した状態管理クラスを作成して、クラス内のメソッドで状態を変更し、Observerに通知することで、UIで生じた状態変更を別Widgetに伝えることができて、かつロジックも分離することができます。

Flutter完全に理解した(第一波)　な状態でしたw

#### 4日目、5日目
アーキテクチャが定まり、CI/CD環境も整ったので、あとは爆速で機能開発を進めていくのみでした。

ハッカソンでは、サーバーサイドが同期1人でやってくれていたのですが、デプロイ周りで苦戦して発表会までに間に合わない可能性があると相談してくれました。
ハッカソンは諦めることなく気持ちよく終わりたいねっていう話に落ち着き、

- サーバーサイドは他の同期チームに相談して、開発は続行する。
- Flutter側は万が一を想定してFirebaseに置き換えできるよう環境を整える

という方針にしました。
Discordで素早く話し合い、方針を決めれたので早めの報連相とDiscordは良きですね。

Firebaseは下図のように運用するようにしました。
こちらも [@ry_itto](https://twitter.com/ry_itto) が先導してくれました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/435438/5cdb8fc5-faf5-15f6-f935-e7d86ca4a7fc.png)

- Cloud Storage
- Cloud Firstore
- Firebase Auth
- Firebase Dynamic link

が、ほぼ1日で構築できるという最高にスピード感ある開発でした。

設計的にも、interfaceを切って、いつでもAPI or Firebaseに置き換えられるような工夫をしていました。
感謝🙏


## おわりに
残念ながら、賞をとることはできませんでしたが、睡眠不足でハッカソンハイになったり、API間に合わないかもしれない相談でエモい感じになったり、すごく楽しいハッカソンでした。

初めてのFlutter開発にしてはかなり上出来だったと満足しています。
Flutterに5日間浮気してみましたが、1つのコードベースでAndroidもiOSも開発できる気持ち良さがなんとも言えないですね...。
これからもプライベートでFlutterは触りたいと思います。

そしてこの　**お掃除BeforeAfter** は是非リリースしたいと思います。