趣味的チーム開発ノウハウ　〜都知事杯や東京公共交通オープンデータチャレンジなどを踏まえて〜

CivicTech ＆ GovTech Advent Calendar 2023に書きたいなと思っていたのですが、シリーズ追加も気が引けるので、元々登録してた方には申し訳ないと思いつつ、代わりに投稿させて頂きます。

趣味的チーム開発が大好きな、たこやきです。我ながらうまく行ったな or 空中分解しちゃったなという開発経験がそこそこあります。この記事では、様々な趣味的チーム開発を経験してのノウハウまとめ記事を書いてみます。２０２３年の都知事杯で技術賞を頂いたBuTTERでの事例を中心に、マインド的なこと、ツール的なこと、ノウハウ的なこと、技術的なこと、幅広く書いていきます。

## これまでに作ってきたもの
現在、社会人2年目です。ITが主でない会社のIT枠採用で、今の仕事では、スクラムによるクラウドを使った内製開発をしています。プロダクトを作るのが好きで、大学時代からこれまでに、以下のような趣味的チーム開発を行っています。

|年|開発したもの|受賞歴|開発チーム人数|
|---|---|---|---|
|2023年|3行貼るだけでバスの時刻表をWebページに埋め込めるツール|都知事杯OpenDataHackathon技術賞|6人|
|2021年|人身事故等の異常発生時における鉄道の混雑シミュレーション|第4回東京公共交通オープンデータチャレンジ最優秀賞|2人|
|2019年|スマホで読み取れるマークシート|第40回U22プログラミングコンテスト 経済産業省商務情報政策局長賞受賞|2人|
|2019年|リアルタイムな列車遅延を考慮した経路検索アプリ|第2回東京公共交通オープンデータチャレンジ優秀賞|3人|

上記以外にも、残念ながら賞を逃してしまった作品や、個人で作った作品、空中分解してしまった作品など、様々あります。

## 個人開発＆チーム開発の難しさ
個人開発、難しい要素はいくらでもあげられます。

- 仕事じゃないのに＆学業があるのにそんなに時間取れない
- 人によって熱量・温度感に差がある
- 継続的に運用していくのはほぼ不可能（詳しくは運用フェーズ）
- いつまでやるのか、どの程度リソースをつぎ込むのか問題
- お金ない

チームの立ち上げ段階は良いのです。当初の目的がはっきりしているうちは良いのです。何かを作ろうとチームを立ち上げただけだと、目標もなく迷走するため、毎回上述したようなコンテストやハッカソンをタイムリミットとして設定し、それに応募することを目標に開発していくスタイルにしています。すると、問題になるのが応募完了後のモチベーションです。受賞できないとそのまま自然消滅パターンとなることが多いですし、受賞できた場合でも、継続的にアップデートしていくことは困難を極めます。良くて、公開時の状態を維持して使える状態として公開し続けられればよい、といった所でしょうか。私がこれまでに作成したものも、様々な要因から、せいぜい3年くらい公開し続けられて、それ以上公開状態を保てたものはありません。なぜかといえば、次のような理由です。

- ドメインの維持費問題
- コンテスト主催元のデータ公開が終了してしまった
- 公開するだけで莫大なコンピュータリソースが必要となる
- メンテナンス性が悪いコードを書いてしまった結果、機能追加するモチベーションが起こらない
- モチベーションが続かない、忙しい

絶望的な状況ですね。これらの課題に対する解は現状、まだ見つけられてないのですが、少しずつではあるものの、改善してきました。一番解決策が盛り込まれている「3行貼るだけでバスの時刻表を埋め込めるツール」であるBuTTERでの例をもとに、これら課題に対して少しずつ見つけてきた、課題に対する解決策をご紹介していきます。

## 少しだけBuTTERの紹介
少しだけBus Timetable By Edge Runtime Tag、BuTTERの紹介です。3行のタグを作り、HTML中に貼り付けるだけで、ダイヤ改正などを自動反映する時刻表を任意のホームページに埋め込むことができます。3行塗るだけでいい感じになるという意味でバターと名付けました。[こちらのリンク](https://tag-maker.butter.takoyaki3.com)より実際にタグを作ってお試しいただけます。

![ezgif-1-6704f6d9fc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224979/d18e7624-7d72-637b-6073-25844db69516.gif)

### ストレージのみで実現するアーキテクチャ
BuTTERでは、バスの時刻表やバス停の情報を小さいファイルに予め分割し、アクセスしやすい形式に変換しておくことで、ストレージに静的ファイルを置くのみで、APIなしで実現しています。

![ezgif-1-17d5f372ea.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224979/1c68c5f8-5122-2ad3-c6d9-0eda34b24434.gif)

![ezgif-1-bc43ee4450.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224979/edb664b9-31dc-90e5-7a3b-47fe8aee356a.gif)

なお、ファイル自体に電子署名をすることで、協力してくれる方の未活用サーバーリソースを活用した配信もできる仕様としている上、BuTTERチームで運用する場合であっても僅かなサーバー維持費で運営することができます。

さあ、BuTTERは一応、いまも機能改良をしています。先週末もアップデートしました。いつまで開発を続けられるか、いつまで公開状態を保てるか、自己最長記録樹立に向けて挑戦中です！！アクセス数＆タグ導入数が励みになりますので、ぜひみなさまお試しください m(_ _)m

## 問題点と個人的？ベストプラクティス
さて、趣味的チーム開発の問題点とBuTTERを開発する上での対策です。

### ドメインはサブドメインで運用しよう
ドメイン増えていく問題への対策です。
初期の頃は、チームを組んで開発するごとに、ドメインを増やして行きました。ここで問題になるのが、ドメイン維持料金です。ドメインを維持するには、.comの場合で、年間1000円強かかります。毎年、ドメインの期限に関する通知が来て頭を悩ませるのです。更新すべきか、更新しなくていいか…。大体、数年立つと、ここでサービスの公開が終了します。とはいえ、ベンダーロックインを防ぎ、柔軟なインフラアーキテクチャで運用したいため、Firebaseの`.web.app`や、CloudflarePagesの`.pages.dev`などは、公開用には使いたくありません。そこで、ある時から、私が代表者になっている趣味的チーム開発においては、私の所有しているドメイン takoyaki3.com のサブドメインをプロジェクトごとに切り出し [butter.takoyaki3.com](butter.takoyaki3.com) のように独自ドメインを取らないようにしました。私は、以下のように適当にパッと作るツールは *.app.takoyaki3.com というドメイン、ちゃんと開発するものは butter.takoyaki3.com のようなサブドメインで運用しています。

![スクリーンショット 2023-12-11 225003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224979/923c9ed1-5c08-c9bd-a6f6-54259f352d47.png)


### １つのレポジトリだけで開発・運用しよう
GitHubのオーガニゼーション増えてく問題への対策です。
ドメインと同様に問題になるのが、GitHubにおけるオーガニゼーション増えていく問題です。ドメインのように直接的にお金がかかるわけではありませんが、参加するプロジェクトが増えるごとに、オーガニゼーションを作っていくと管理対象が無限に増加してしまいます。そこで、BuTTERでは、Webアプリ・サーバー・変換スクリプト・ライブラリ・紹介ページのすべてを一つのレポジトリ内で管理する運用としました。現時点ではWebアプリや紹介ページ、時刻表アプリの３つをCloudflarePagesで運用していますが、Pagesへのデプロイもproductブランチにプッシュすれば、3サイト同時に自動でアップデートが反映される仕組みとなっています。この１レポジトリで３サイトの運営は、後述するCaddyによって実現しています。

なお、BuTTERのコードは[github.com/takoyaki-3/butter](https://github.com/takoyaki-3/butter)にて管理しています。

|ディレクトリ|概要|URL|ホスト先|
|---|---|---|---|
|about|プロジェクト概要|https://butter.takoyaki3.com|Cloudflare Pages|
|tag-maker|タグを生成するためのWebアプリケーション|https://tag-maker.butter.takoyaki3.com|Cloudflare Pages|
|timetable-app|BuTTERを活用した時刻表アプリ|https://timetable.butter.takoyaki3.com|Cloudflare Pages|
|api|時刻表情報をAPIとして提供するためのコード||Cloudflare Worker|
|cmd|GTFSを分割ファイル形式（butter形式）に変換するスクリプト|||
|lib|分割ファイル形式（butter形式）をダウンロードして必要な情報に加工するライブラリ|https://www.npmjs.com/package/butter-lib|npm|
|tag|タグ|https://www.npmjs.com/package/butter-tag|npm|

### 静的サイト構成＋コンテナorサーバーレスAPI構成にしよう
サーバー増えていく問題への対策です。常駐するサーバープログラムがあると、メンテナンスが大変になります。ユーザの情報やシステムの情報を長期記憶することのない、可能な限りステートレスなシステム構成として、２台以上のVPS等で動かす、または、サーバーレス構成とすることで、冗長性をもたせ、片方のコンテナは停止しても大丈夫というメンテナンス性向上が期待できます。また、コンテナ化することで他のサービスや自分用ツールと一緒に運用できるため、システム運用負荷を大幅に軽減させられます。API側を静的にすることは難しいですが、Webアプリ側は静的構成とすることで、GithubPagesやCloudflarePages、オブジェクトストレージなどで公開することができ、バージョン管理のしやすさやサーバに関して考える煩わしさをなくすことができます。結果的に、コンテナ化＆静的サイト化しておくことで、新たに開発するサービスと一緒にまとめてコンテナを運用できるため、運用の手間やお金の問題の解決にも繋がります。

![スクリーンショット 2023-12-11 225614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224979/e03517c1-069b-f02f-2cfb-d163c2f56599.png)

### データ更新は自動化しよう
データ更新などのメンテナンスに運用作業が生じると、データ更新をしなくなり、サービスの自然消滅となります。データ更新が必要なサービスを開発する場合は、データ取得元のAPIから自動でデータをアップロードし、自動で更新する仕組みを実現させないと厳しいです。BuTTERでは、バスの時刻表データが配信されている[GTFSデータレポジトリ](https://gtfs-data.jp/)や[東京公共交通オープンデータセンター](https://www.odpt.org/)からデータを取得し、メンテナンスを手間なくできる仕組みとしました。

![スクリーンショット 2023-12-11 222228.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224979/4d433f3a-14bd-b44c-4054-2ee7f6b5ae64.png)

### 趣味的チーム開発は気楽にやろう
モチベーションが続かない、忙しいに対する心持ちです。
これに関して意見が分かれる所かもしれませんが、個人的には、趣味的チーム開発は、できる人ができる時に可能な限りやるべきだと考えます。せっかく趣味でやるのに、メンバー間でギクシャクしても嫌ですし、他の多くを犠牲にしてやるべきだとは思いません。また、コンテスト応募！という目標があるうちは良いですが、そこから勝ち進んだ場合の延長線や公開後のアップデートは、動く状態を維持したまま自分が使って楽しめれば御の字だと思います。

### コミュニティが必要になるようなツールは厳しい気がする
モチベーションが続かないに対する対応策です。
本気でやるなら別です。しかし、あまり本気でない趣味的チーム開発では、個人開発も同じですが、コミュニティを形成するのは難しい気がします。例えば、SNS系を作るとなると、使ってくれるユーザが複数いないとSNSとして成立しないため、チームメンバーしか使わないSNSになってしまいます。サークル活動用などであれば継続的に開発・運用するモチベーションにつながるのですが、自分すら使えないツールとなると継続して運用するモチベーションはなくなってしまうため、最低限、ユーザが自分ひとりでも使えるツールを作りたいなとアイデアを考えています。ちなみに、詳しくはないのですが、misskeyなどのActivityPub対応のSNSを作れば、ユーザが自分ひとりでもなんとか普段使いできるのかな？とかって考えてたりもします。

## 便利なツール・必要なインフラ
### MatterMost
SlackのようなことができるOSSです。VPSなど、独自のサーバーで運用できるため、アカウントが増えてもお金が自分のVPS代しかかかりません。音声通話や画面共有もできますし、S3互換ストレージを設定することで、たくさんのファイル共有にも使えますので、とても便利です。マークダウン形式でメッセージを投稿するタイプなため、Slackより個人的には好きです。ここに、メンバーごとに「times_takoyaki3」などの進捗報告チャンネルを作り、各々の進捗を共有＆それに返信していきます。

![スクリーンショット 2023-12-11 230537.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224979/3ef5e5fc-7a78-fe2e-b7d6-6a79fc15101e.png)

### GoogleMeet
GoogleMeets、無料版だと1時間という時間制限があります。趣味的チーム開発におけるMTGはどうしても夜に行うことが多く、ダラダラ続けると無限に時間が溶けていきます（学生時代の趣味的チーム開発はダラダラ夜な夜な開発することも多く、楽しかったのですが）。1時間1本勝負と決め打ち、1時間で強制的にMTG終了するぞ！という意気込みで行うには、実はとても丁度よい機能なのでオススメです。

### Caddy
BuTTERでは、別ドメインの3つのサイトを1つのレポジトリで管理することで効率的な開発・運用を行っており、これら3つのサイトは一括でCloudflare Pagesにてホストし、各ドメインへのアクセスをCaddy Proxyにより振り分けています。詳しくは、[CaddyとCloudflarePagesで複数サイトを1レポジトリでデプロイ](https://zenn.dev/takoyaki3/articles/d62296ecbf983f)において、その運用方法を記しています。

![](https://storage.googleapis.com/zenn-user-upload/4ad606ebcfc7-20231014.png)

|URL|用途|
|---|---|
| https://butter.takoyaki3.com |BuTTER全体の紹介|
| https://tag-maker.butter.takoyaki3.com |Butterタグを作成するためのページ|
| https://timetable.butter.takoyaki3.com |BuTTERを使った時刻表サイト|

なお、時間をたくさんかけられるのであれば、BacklogやMiro、アサナなど、素晴らしいタスク管理ツールはたくさんあります。現在の仕事や学生時代のバイト先（技術系バイトしてました）では使ってますし、しっかりと計画立てて取り組む上ではとても便利なツールなのですが、趣味的チーム開発に導入してちゃんと続けられたことはないです。規模が大きなチームであればしっかりとタスク管理等したほうがよいのでしょうが、タスク管理に時間を費やすのが限られた時間しか使えないと難しいなぁという印象です。

### LINE
なんだかんだ、Mattermostなどは気づかないことがあります。趣味的開発なので、チームでLineを作って、MTGのリマインドやちょっとした報告、日程調整等はLineを使うのが手っ取り早いです。

以上、思いついた限りの趣味的チーム開発における開発ノウハウです。無理なく楽しくほどほどに趣味的チーム開発がもっとメジャーになるといいなと思います。思いついたらまた追記します。