ハッカソンに参加してきた話

# はじめに
みなさん、こんにちは
Amebaの広告プロダクトチームでバックエンドエンジニアをやっている永井です。
この記事は、メディア事業部の広告横軸組織[PTA](https://twitter.com/PTA_CyberAgent)の[アドベントカレンダー](https://adventar.org/calendars/7539)5日目の記事となります。

# 概要
会社とは全く関係ないのですが、プライベートで[SPAJAM2022](https://www.spajam.jp/result/)に「お久しぶり！」というチーム名で参加し、ありがたいことに本戦で優秀賞と長崎賞をいただくことができました。ハッカソンという時間が極端に少ない状況において開発中に気をつけたこと、もっとこうしておけばよかったことを述べます。

# ハッカソンとは
念の為ハッカソンについて説明させてください。ハッカソンとは、ハックとマラソンを掛け合わせた言葉です。決められた期間内にテーマに沿ったアプリケーションを開発し、プレゼンして完成度やテーマ性にどれほど沿っているか競い合う競技になっております。今回お話しするSPAJAM2022においては、約24時間で「国際交流」というテーマでスマートフォンアプリを開発しプレゼンするというものでした。

# 作ったアプリケーション
こちらについては、ホームページで紹介されている文章がとても適切だったので引用させていただきます。自分は、WorldBottleの開発においてバックエンドエンジニアとしてインフラの構築やAPIサーバの実装を担いました。
>瓶に封じて海や川などに流された手紙ボトルメールをIT技術を駆使して再現したアプリ「WorldBottle」を開発。
ボトルが海の上を流れているUIを経路探索アルゴリズム（RRT）を用いて実装し、 到着した場所の国の言語に翻訳するためにGoogle Cloud Translation APIを使用している。 ボトルメールが海を流れる再現性や、ボトルメール本来のエモさやワクワク感が評価され、優秀賞を受賞した。(https://www.spajam.jp/result/ 「大会結果」より引用)

# 気をつけたこと
今回のハッカソンでは開発時間が24時間しかありませんでした。アイデアを考える時間もの中に含まれています。また、せっかくなのでご飯を食べたり温泉に入ったりを楽しもうと思うと開発にかけられる時間は本当に限られていました。とにかく効率良く開発を進めていく必要があったのでそこで気をつけたことをお話しします。

## 手戻りを減らす
時間が限られている状況では手戻りがとても痛いです。そのため、しっかりと時間をかけてAPIとDBの設計を行いました。自分がたたきをREADME上で記述し、たたきをベースに議論を行いより良い状態にしました。GitHubのREADMEを利用したことにも理由があります。ハッカソンにおいて深夜の作業はほぼ確実なので、情報が流れてしまうSlack上で共有してしまうとフラフラの脳みそ状態だと探すのに時間がかかってしまいます。なので、いつでもここを見れば良いという場所と作ることでそのような事態の回避を狙いました。実際のAPI定義書の内容を付録して一番下に記述しておきます。

## 便利ライブラリは使っていく
今回APIサーバはGo言語で開発しました。利用した便利ライブラリとしては[gen](https://github.com/go-gorm/gen)と[wire](https://github.com/google/wire)です。genは実際にデータベースに接続し、テーブルの情報を読み出して自動でテーブルの情報をGo言語の構造体として生成してくれるツールになっています。設計段階でしっかり時間をかけてしっかりとテーブルも決めるので、サクッとSQLを記述してDBを作れてしまいます。そのため、そこからテーブル定義を読み出してGoの構造体を生成してくれるgenはとても便利でした。次にwireです。wireはコンストラクタ相当のNewXXX関数を用意してwireに食わせてあげると、いい感じにDIしてくれるというツールになります。深夜の開発作業においてDIの部分もミスってしまう可能性がありますが、脳死でDIしてくれるのでこれまたとても便利でした。

## ソフトウェアのアーキテクチャに凝る
今回は、handler->service->repositoryという3層のレイヤでAPIサーバを構築しました。しっかりとレイヤが別れていることで、バグを仕込みにくくなりましたし、それぞれのレイヤで関心を分離できるので開発中も考えることが減り負荷が低く開発することができたと思います。ただ、後述しますが極端に開発時間が短いハッカソンにおいてはやりすぎたかなとも感じました。

# 反省点
ここからはハッカソンの反省点を述べます。

## 事前準備しておけばよかった
バックエンドエンジニアとしてハッカソンに参加している以上、裏側にDBがあるAPIサーバの構築は必ず発生します。そのため、CDKやTerraformでインフラのマニフェストは事前に用意しておけばよかったなと思っています。コンソールからぽちぽちリソースを作成するのにも地味に時間がかかってしまったと反省です。事前準備はもしかしたレギュレーション違反かもしれませんが...

## 開発スピードを重視するべきだった
先ほども述べましたが、ソフトウェアのアーキテクチャに凝りすぎたかなとも思っています。関心が分離されているのでコードは記述しやすいのですが、簡単なAPIサーバの割にコードの記述量は増えてしまったかなと思っています。アイデアを考えている時間を考えると、20時間弱しかない開発時間を考慮するといい意味でもっと雑に作ってしまえばサクッと結合テストができたかなと感じました。

# 終わりに
いかがでしたでしょうか？今回は、自分のハッカソン経験で気をつけたことと反省点を述べました。とても特殊な状況ですが、業務でも適切な設計や開発ができているのか改めて考えていきたいなと感じました。最後までお読みいただきありがとうございました。

# 付録
実際のAPI仕様書(一部抜粋)

## ボトル詳細取得API
### パス
`GET /bottle/${bottle_id}`
### パスパラメータ
- bottle_id：ボトルID int

### レスポンスボディ 
#### 到着している場合
```json
{
  "bottle_id": 1,
  "title": "タイトル1",
  "message": "私の文章は届きましたか？",
  "translated_message": "Did my message delive?",
  "user_id": "test@mail.com",
  "is_landed": true,
  "is_received": true,
  "received_user": "nagai@mail.com",
  "route": [
    {
      "latitude": 23.4,
      "longitude": 123.4
    },
    {
      "latitude": 23.5,
      "longitude": 123.5
    },
    {
      "latitude": 23.6,
      "longitude": 123.6
    },
    {
      "latitude": 23.7,
      "longitude": 123.7
    },
    {
      "latitude": 23.8,
      "longitude": 123.8
    },
    {
      "latitude": 23.9,
      "longitude": 123.9
    }
  ]
}
```