公立はこだて未来大学の学校祭、未来祭で行われた学内ハッカソンに参加した記録です。

成果物

下のYoutube動画から見ることができます。
fuNGという名前で、同期2人との3人チームで参加しました。

Depotifyというサービスを開発し、自分はそのなかで、ネイティブAndroidアプリを作成しました。 (Githubのレポジトリはまだprivateなので今は紹介できません。いつか公開されると思います)

振り返り

今回のハッカソンは2週間の開発期間が与えられた長期ハッカソンでした。
そのため、ほとんどのチームが前半一週間でアイデア出しをして、後半一週間で実装をするというパターンが多かったように思います。
自分たちのチームも最初の一週間はアイデア出しに注力し、その中で、「これは絶対に必要になるだろう!」と思われるものだけ先にパーツとして作っておくという形を取っていました。バックエンドのチームはこの時点でWebサーバーのフレームワークを決定して、死活管理用のルートなどを作っていました。自分は何をしていたかというと、Jetpack Composeの勉強をしていました。(自分はAndroidに触ったことが1回程度しかないため、先にAndroidを勉強することにしていました。)

アイデア出し

今回のハッカソンのテーマが「函館の交通課題をハックする」という課題解決型だったために、自分はほとんどアイデア出しに参加できませんでした。幸い自分以外のチームメンバーが交通などへの興味を持っていたために、その2人にアイデア出しをすべて投げてしまったことを反省しています。

最終的に今回の相乗り補助アプリに落ち着いたわけですが、一応自分もプロダクト内部のアイデアを出したりしています。
ドライバーと乗せてもらう側のソフトウェア上での動きが全く別のため、その2つを区別する必要があり、なおかつ、乗せてもらう側も様々なセットアップをスマホでしなければいけないというところがユーザーの負担になりそうだという話を踏まえて、ドライバーのみがアプリをインストールし、種々の情報を詰め込んで、バックエンドサーバーにgetリクエストを投げるQRコードをドライバーのアプリに表示するというアイデアを出しました。
まだ設計段階でこのアイデアを出したため、今回のプロダクトに採用されました。

設計画像

他にも、様々なアイデアがメンバーから出されて、そのほとんどが採用されました。
プロダクトの部分部分の責任分割ができていたため、手戻りが細かなものしか発生せず、それぞれの人が別のメンバーにインターフェースを提供するというような形で開発できたのが良かったと思っています。

開発はじめ

今回のチームは、珍しく、バックエンド2人、フロントエンド1人(自分)という構成のチームでした。
そのため、開発開始からは大してバックエンドとの連携を取ることが少なくなり、時々バックエンド班から提供されたAPIの仕様を聞きに行くようなことを繰り返していました。

まだJetpack Compose完全に理解したみたいな状態ではなかったので、SwiftUIを書いた経験からなんとなくでJetpack Composeを使っていました。この時点ではそこまでComposable間でのデータの受け渡しや、呼び出し元Composableに影響を与えるような機能についての実装方法がいまいちよくわかっていなかったような感じです。当然ViewModelなども知りませんでした。

このころはまだボタンやUIを並べたり、適当に画面遷移を書いたりする以外のことをしておらず、そんなに辛さもなかったです。宣言的UIの嬉しさを一番満喫していた頃とも言えます。

開発中期

UI作りがほぼほぼ一段落して、アプリのローカルストレージなどを扱ったり、GPSを扱わなければいけなくなりました。

GPSに関してもかなり苦労があり、自分のやりたいことをリファレンスで調べていたら、Android公式Referenceにたらい回しにされるという状態が1時間半くらい続いて、かなり辛かったです。
結局自分の求めている情報はAndroid Developersではなく、Google Play Serviceのリファレンスに記載されていたという罠もありました。


また、ローカルストレージ周りでも様々ありました。

データ ストレージとファイル ストレージの概要 - Android Developers

上のリンクを見てもらえばわかるように、Androidではアプリに、さまざまなデータ保存方法が提供されています。自分はgetFilesDirなどを用いてファイルを読み書きしたり、Roomを使ってデータを保存しようと考えていたのですが、どうしても決めあぐねており、メンターにその旨を伝えました。

そこでSharedPreference APIの存在を教えてもらい(もともとリファレンスを読んで知ってはいたが、今回の用途で使えるとは思っていなかった)、これでローカルストレージ周りの実装をすることを決めました。ここにきて、Contextなどの概念を勉強しはじめることになります。

開発後期

APIに対してデータをリクエストする処理は、一般的に独立した関数やクラスで行われるものだと思います。
自分の今回の実装もそうです。
ここで、下のような問題が生じました。

@Composable
fun baseComposable() {
    var hoge = null //これをAPIから取ってきたデータで書き換えたい。

    hoge = getDaraFromTheAPI() //これはできない
}

suspend fun getDataFromTheAPI() {
    //処理
}

Androidのルールとして、ネットワーク通信は非同期で行う必要があります。そこで、suspend属性のついた関数を呼ぶわけですが、そもそもsuspend属性の付いた関数を普通の関数の中で呼ぶことはできません。(launchブロックの中などで呼ぶ必要があります。)
それに加えて、Composable間でデータを共有する必要がありました。SharedPreferenceを使うことでこれを解決できそうでしたが、そもそもComposableでない関数についてLocalContext.currentは取得できません。

かなり開発後期(終了2日前?)にこの問題にあたってしまい、正直かなり焦りました。
インターネットを様々調べていると、海外のWebサイトを見つけ、そこでViewModelを用いて自分の行いたい処理を実装している記事を見つけました。まずはそれをコピペして、実際に動くことを確認し、コードを読みながら、解釈して、書き上げることになりました。

結局今でもViewModelについて詳しく理解できたわけではないのが辛いです。
Androidのリファレンスなどを読んでも、いまいち核心的な説明が書かれていないことが多く、開発中は常にこれに悩まされていました。

発表

デモ用にスライドに埋め込まれた動画を作ったりしていました。
大学にあるApple製パソコンであれば、自分の学内アカウントでログインすることでAdobe製品を自由に使うことができます。久々にPremiere Proを使いました。

ところで、ページ最上部に貼ったYoutube動画を見てもらえばわかりますが、発表会時に2人しか出ていません。
ここでいないのは私で、寝坊しました。

助けてくれ

結局ラスト2チームくらいの発表を見て、昼休みになりました。
結果的には負けてしまったのですが、まあいろいろと得られることはあったので良かったと思います。

反省など

意思疎通でエラーが多く発生していたと思います。
タスクはGitHubでissueやmilestoneを使って管理していたので「今自分は何をすればいいんだろう…」と迷子になることはなかったですが、各個人との意思疎通でエラーが発生しており、「この実装がなされていると思っていたが、そんなことはなかった」ということが割と最後の方に発覚して炎上しかけました。
今回作成したプロダクトはAndroidのフロントエンド、Webフロントエンド、バックエンドの3つがあるため、どこでエラーが発生したかの追跡が非常に困難でした。
というのも、Androidフロントエンドの実装がマズくて(バックエンドに不正なリクエストを投げているとか)エラーが発生しているのか、そもそもバックエンドのロジックエラーなのかの切り分けが必要であったりして、エラー発生箇所の特定に非常に時間をかけてしまいました。

自分の反省点としては、デザイン面や、コーディング面が多いです。
デザイン面では、最初に提案したカラーデザインをチームメンバーにすべて蹴られました。(蹴られましたが、正しい判断だったと思います。) 色覚異常がある場合に、並んだ2色の区別がつかないような色を選択しており、配慮がなかったと思います。実際、(小さいものですが、自分の考えもあって決めた)自分の決定について他人から詰められるのはかなり辛いのですが、落ち着いて他人の意見を聞けるようになりたいです。

コーディング面については

  • クラスとして分けられているべき機能が分かれていない。
  • 実装できそうと宣言した機能について実装できなかった(これは本当予想外で、リファレンス通りに進めたはずなのに実装できなかった)
  • 書きながら知識がアップデートされているため、同様の処理を行う、最初の段階で書いたコードと最後の段階で書いたコードが異なる

など、様々あります。(もちろんこれ以外にも)

これらについて解決策として、

  • しっかりと関数、クラスのスコープを分けること
  • 自分の中である程度のフォーマットを決めておくこと or コードフォーマッタを導入すること(フォーマッタの導入はあんまりしたくない)

などを考えています。

感想

他のチームメンバーのレベルが高かったこともあり、ハッカソン参加者内では、最も完成度の高い状態で発表に臨むことができたと思います(サーバー、フロント2つがすべて連携して動いているチームは自分たちのチームだけな気がします)。
ハッカソン終了後、審査員からの評価を見ることができましたが、結局アイデア負けのようなところがあり、少しやるせない気持ちになりました。評価にも少し納得のいっていないところはありますが、それは実力として受け入れています。

なにより、初めてのハッカソンでここまでのプロダクトを作り上げられたことについて良かったと思っていますし、楽しかったです。

また、他のチームやメンターの方とお話する機会も頂けたので、様々な情報のキャッチアップができて良かったです。

次回は、多分 p2hacks です。