Pintアプリの開発にFlutter + Firebaseを採用した理由とその結果
背景
2021年12月ごろ、Pintの企画が完成に近づき、UXの要求がまとまりつつありました。
企画のユースケースを実現するためには慣れたRails+Webviewで構築するのが一番手っ取り早いですがUXがあまり良くないので、ネイティブで構築するという方向性で検討を進めました。
アプローチ
速く、安く作るにはiOSとAndroid上で動作するクロスプラットフォーム対応のフレームワークを採用することが第一候補となります。
当時は、React Naive、IONIC Framework, Cordovaなどのフレームワークが存在していました。
どれも一定のプロダクションのアウトプットは出せる感じがありました。しかし、開発者の定着度合いがあまり良くなかったり、微妙なUIがあるためこの中から選ぶのはあまり良くないなという感覚がありました。
そして、当時はFlutter 2.8がリリースされたあとでもあり、かなりいろいろなコンポーネントがリリースされてきてFlutterで作られたアプリケーションがちらほら出だしてきているときでした。
また、
【初アプリ】未経験がFlutterで肉牛繁殖農家のためのアプリを作ってみた
というアプリが1ヶ月ぐらいの開発で良さそうなUIのアプリがリリースされていました。これを見て、Flutterのポテンシャルがかなり高く、ユースケースも実現できそうというのはなんとなく感じてました。
新技術を使うときやフレームワークに乗る時にはやはりリスクが伴うので、カルチャーであるFail&Learnの考えのもと、薄く広く実装をしながらFlutterを学習しつつ実現したいユースケースを達成できるかというフィージビリティチェックも同時に進めていきました。
また、アプリ開発においてはフロントエンドとバックエンドの両方の技術選定を決める必要があります。
そして、スタートアップなので速く、安く、持続可能な技術でプロダクトをデリバリーする必要があります。
もっと抽象的に作れるかを検討
Flutterより上位のレイヤーでノーコードに近い形でアプリを開発できたら良いなと思い、まずはFlutterFlowを検討してみました。
FlutterFlowはノーコードでFlutterアプリを構築できるというのが特徴です。デモのUI/UXもすごい良さそうに見えました。
サンプルが豊富にあることや、UIからアプリのコードを生成できる機能があるため、アプリの基本形を作るまでのスピードは非常に速く、プロトタイプ作成などで特に有効なツールかと感じました。また、毎週のように新機能が追加されており、活発なプロダクトであったことも印象的です。
とりあえず使ってみないとわからないのでFlutterFlowをベースに開発を進めていましたが、手が届かないと感じる点も出てきました。
FlutterFlowにカスタムのメソッドを適用する機能もありますが、あくまでUIの何かの操作がトリガーのものに限定されるなど、カスタマイズ不能な範囲がどうしてもあります。
例えば郵便番号のバリデーションのようにユーザーが入力中に動いてほしいものや、複雑なユーザーのルーティング条件が必要な場合には対応できないユースケースがありました。
そういったケースは、FlutterFlowから出力したコードを変更して対応します。
FlutterFlowからはソースコードに1方向でしか変換できないため、結局のところソースコードを書きかえていくとFlutterFlow上のUIに差分が出つづけ、マージが手間になリます。
また、FlutterFlowだけでは本番・ステージングなどの複数環境の切り替え機能がないことも、CI/CDなど環境を構築するに当たって重要な要件を満たせないこともわかりました。
こうした点を踏まえ、FlutterFlowの利用は諦めました。
Flutter上でDartを書くことに決定
FlutterFlowを使うときに、簡単なアプリであれば問題ないのですが、ちょっとはみ出たことをしようと思うとどうFlutterFlowを使って実現すれば良いのか、ドキュメントも少ない中で考える必要があります。
一方Flutterは公式ドキュメントが非常に充実しており、結局0から開発するほうが自由度高く、かつ早く開発できました。これはローコード・ノーコードツール全般に言えることだと思いますが、ビジネス要件がきっちり決まっている場合は、実現できることをツール側に寄せる必要のある開発スタイルではなく、フルスクラッチで開発するのが良いと思っています。
またFlutterはWidgetを組み立てて構築していくフレームワークなので、UIからアプリを組み立てていくことにこだわらなくても十分問題ないという言語特性もあります。
ソフトウェアアーキテクチャ選定
Flutterで構築する際に、重要になるのがソフトウェアアーキテクチャのモデル選定です。当時はデファクトスタンダードが無く、どれも一長一短ではありました。主に以下のアーキテクチャがオプションとしてはありました。
- Stateful Widget
- MVC
- MVVM
- MVVM + repsitory
当時のトレンドの1つであったflutter-architecture-blueprintsをベースに、MVVM + repositoryの構成で設計を進めました。MVVM + repositoryに関する情報がWebに充実しておりまた最後発で様々なアーキテクチャ上の課題を解決しているためです。
利用したパッケージの紹介
今回、利用したパッケージの一部を紹介します。
riverpod + Flutter Hooks
状態管理にはriverpod + Flutter Hooksを使用しています。
freezed
ModelをcopyWithでイミュータブルに扱ったり、JSONのde/serializeしたりといったコードの自動生成をするために使用しています。
flutter_gen
flutter_gen
画像などのリソースファイルへ安全にアクセスできるようにするため使用しています
search_choices
search_choices
銀行口座を一覧から選択する際に、多数の項目から選択するUIが多いです。こちらのパッケージを使用することでテキスト入力からリアルタイムにフィルタリングして項目を絞れ込めます。
バックエンドの選定
バックエンドはFirebaseを採用しました。
Amplifyなども検討しましたが、やはりFlutterと同じGoogleが開発しているので、ドキュメント・パッケージともにFirebaseとの接続がサポートされているケースが多いです。
またJSONで様々なデータが扱えたり機能ごとにきちんと結びつきがあったりと親和性が高いです。
Flutterを使って開発する場合はバックエンドをFirebaseで構築するのがデファクト・スタンダードのような印象を受けました。
Firebase上の処理が多くなってくるとコストが嵩んでくる問題はありそうでしたが、そのときには適宜バックエンドの再選定をしていくのが良いと思います。
Tips
Flutterで開発をしてみて、得られた知見をまとめておきます。
DartやFlutterの最新情報は要チェック
DartやFlutterはマイナーバージョンの更新でも大きな仕様変更が入ります。
例えば、2022年5月のDart2.17です。enhanced-enumという、enumの拡張機能が追加されたのですが、こちらがreleaseされるまではenumを自ら拡張して実装する必要がありました。
新興言語ということもあり、大きなアップデートが多いため、変化が多くて楽しいです。
アーキテクチャありきでなくても良い
FlutterFlowから切り替える際にはアーキテクチャから検討を始めましたが、まずは標準的なStateful Widgetでの開発で進めても良かったかもしれません。
というのも、多くのパッケージにおけるサンプルはStateful Widgetで記載されているため、riverpod + Flutter Hooksを軸にしてしまうと、慣れるまでは置き換えるプロセスで手間がかかります。
特にFlutter未経験の状態であったこともあり、なおさら標準スタイルで進めた方が結果的にリリースまでのスピードが速かったのかなと感じることがあります。
もちろん自社のリソースの技術スタックによりますが、まずは素直にFlutterの公式ドキュメントをベースに進めていくのが一番の近道かもしれません。
最初からきちんとデザインする
デザイナー不在もあり、今回の開発では未経験者のPdMがMaterial Design等を無視してデザインをしましたが振り返ってみれば、Material Designを学んでもらって、それに則った開発をするべきだったなあという公開があります。それをすればテーマを当てるだけでよくなるのでコードが軽量化され実装面でも楽になります。
学習コストはかかりますが、トータルで考えたときにペイするので、デザイナーがいない状態でも最初からMaterial Designに則って設計するべきだと思います。
もちろんエンジニアもMaterial Designを理解しデザインを作る人とコミュニケーションを取れるようにすることが重要です。
終わりに
Flutterを採用してどうだったか?
回り道もありましたが、総じてFlutterを採用したことは非常にプラスだったと感じています。
結果的にネイティブ開発の知識はビルドなどに関する設定が必要だった程度で、今回のチームでも無事にAndroid/iOSともにストアへのリリースまで進めることができました。
実際に開発してみたところ、Nativeで書くところはほとんどなく、Swift + Kotlinより早く、楽に開発できました
Pintのアプリをリリースしてから半年が経ち、Flutterの勢いは当時よりも増しているように感じます。現時点ではPintアプリは今後もFlutterで開発、運用を続けます。
Pintについて
Pintはアプリを経由するだけでAmazonや楽天などのECサイトでのお買い物でポイントがもらえるサービスです。この機会にぜひインストールして活用してみてください!
Discussion