Flutter製の個人開発アプリ「禁欲スカイウォーカー」の技術的まとめ
はじめに
8月にFlutter製の個人開発アプリ「禁欲スカイウォーカー」をリリースしました。今回はそこで使った技術についてのまとめです。Flutterで個人開発がしたいと考えている人の参考になれば嬉しいです。
1. 禁欲スカイウォーカーについて
禁欲スカイウォーカーは、一言で言うと「オ○禁の継続日数を自動でカウントしてくれるアプリ」です。オ○禁の意味が分からない方は、ブラウザバックしてください。
リリースしてから3ヶ月目の現在、そこそこ良い評価(iOSで評価数・平均4.6)をいただいており、いいスタートを切れています(月1500円ほどの収入・・)。
また、本アプリはiOS/Android両方でほぼ同時に(2020/8/1 ごろ)リリースしています。 簡単に2つのプラットフォームにリリースできるのはFlutterの大きな魅力の一つです。
「オ○禁」を選んだ真面目な理由
一応、「オ○禁」というジャンルを選んだのには以下の真面目な理由があります。
- 性的なジャンルなので企業が参入しにくい(ピンクオーシャン)
- 規模が大きすぎず小さすぎずで企業が参入しにくい
- 現状競合アプリが少ない(両OSともに4つほど)
- 多くの男性の生活をより充実したものにできる
僕は「生きる活力を高めるサービス」を作りたいと思っており、 その考えとも矛盾なく作れてかつお金が稼げる規模になりそうだと思ったので、このアプリを作ることにしました。
サービス内容やユーザ拡大戦略についての話は他の記事で書きますので、そろそろ技術の話に移っていきたいと思います。
2. 使用した言語・フレームワーク等
- フロントエンド(iOS/Android): Flutter/Dart
- バックエンド: Firebase(Authentication, Firestore, Analytics, Admob)
Flutterとの相性の良さからFirebaseを使いました。Flutterでは公式のFirebase操作用ライブラリが使えるので、スムーズにバックエンドと連携するコードを書くことができます。
dart-defineの活用
また、開発環境と本番環境の二つのFirebaseプロジェクトの切り替えをいつでもできるようにdart-defineを使いました。 flavorとも迷ったのですが、あまりコストに大きな差がなさそうということと、ちょうど開発を始めた時期は日本語のdart-defineに関する記事がなく、「これは記事にできる」と思い採用しました。こちらに関しては以下の記事に書きました。
3. アーキテクチャ
シンプルに ChangeNotifier・Riverpodを使ったMVVMパターンを採用しました。
(イメージ)
ちなみに、以下のwasabeefさんの記事とほぼ同じ設計になっております。
少なくとも個人開発の規模では、この構成で全く問題ないように思います。 BLoCやStateNotifier、Reduxなどのアーキテクチャも同様に問題ないと思います。 このあたりの選定に不安がある方は、比較的学習コストの低いChangeNotifier/ValueNotifierとflutter_riverpodを使う構成をオススメします。
パッケージ分割(ディレクトリ構成)
また、パッケージ分割はドメイン別に分割する方法をとっています。大体以下のような構成にしました。
- zzz
- yyy
- xxx
- widgets
- xxx_page.dart
- xxx_list_view.dart
- models
- xxx.dart
- xxx.freezed.dart
- その他(xxx_repository.dart、xxx_notifier.dart、xxx_api など)
- main.dart
こちらの話は以下の記事でまとめています。
4. テストコード
基本的にバグが出た箇所や不安な箇所にはテストを書くようにしています。 リリース当初はテストを書いていなかったのですが、一ヶ月ほど一つの機能で複数のバグが断続的に発生し、バグを潰した際に以前修正したバグが再発するなどひどい状況になったためテストを書くことを決意しました。
結果的に テストで保護していくことで安心してバグを潰していくことができ 、バグの修正がバグを生むということがなくなり安定した開発を行えるようになりました。「テスト駆動開発」でも不安がなくなるまでテストを書くべきと述べられていますが、その通りだと痛感しました。
また、モックやスタブの作成にはmockitoを使いました。
5. 静的解析
analysis_options.yamlを lib/ 直下に追加し、const指定などにもwarningが出るよう厳し目のルールにしています。
6. CI/CD
CI/CDにはCodemagicを使っています。ただFirestoreを使い始めてからビルド時間が長くなり、課金されてしまうようになってしまったので今後継続して使っていくかは迷っています。
7. その他:Widgetを画像にしてSNSシェア
SNSにシェアをする際にWidgetを画像にしてシェアする方法について記事を書いているので、参考になれば嬉しいです。
最後に
もしご質問・ご指摘等ありましたら、以下のTwitterまたはこの記事のコメント欄からコメントしてください。
おまけ:FIrebase以外で使用したライブラリ
最後に、使用したライブラリをひたすら列挙して終わりとします。
flutter_riverpod
DIができたり状態更新通知ができたりするライブラリ。package:providerの後継で、2020/10/21現在はまだ安定版ではないので注意が必要。
esys_flutter_share
唯一画像もシェアできる シェア用ライブラリ。SNSへのシェア機能に使用。
freezed
json変換機能やUnion Type、ValueObjectなどが使いたい時に使うライブラリ。今回はjsonデータとDartrオブジェクトの変換機能のみ利用(json_serializableを使っても良かった)
sqflite
sqliteを使うためのライブラリ。テーブル形式で保存したいデータの保存用に使用。
shared_preferences
データの永続化に使用
flutter_launcher_icons
アプリアイコンを一つの画像から生成してくれる、非常に便利なライブラリ。
rxdart
rxのdart向けライブラリ。BehaviorSubjectが使いたかったので使用。ChangeNotifierでも代用可能ですが、勉強として使ってみたかったので使用。
flutter_cupertino_date_picker
日付を入力するPIcker
flutter_calendar_carousel
カレンダーライブラリ
url_launcher
リンクを指定してブラウザを開いてくれるライブラリ。アップデート訴求のダイアログからストアページに飛べるようにするために使用。
package_info
ビルドナンバーを取得して、アップデート訴求のダイアログを出すために使用。
rate_my_app
レビュー訴求のダイアログを出してくれるライブラリ。
mockito
テスト用のモックを作るためのライブラリ。