これはなに?
先日投稿した君はまだ平成のアーキテクチャを使ってるのか?僕はFirebaseと令和の時代に行くぞ。の続きです。
思っていたよりもたくさんのフィードバックを頂いて驚いています。ありがとうございます。
伝えたいことが伝わっていてよかったなと思う一方、記事の内容の設計が微妙だったなという感じのご指摘もいただきました。この記事では、前回の記事を読んでいただいたみなさんが抱いたであろう疑問・懸念にお答えすることができればと思っています。
この記事だけ読んでもおそらく何の話かわからんとおもうので、先に前回の記事を読んで頂くと良いと思います。
Firebaseって銀の弾丸なの?
違います。
先の記事から引用しておきます。
大切なことは、解決したい問題を明らかにし、それを解決できる技術を選ぶということです。
この過程を怠った信念なき技術選定が誰かを幸せにすることは絶対にありません。
Firebaseが優れたツールであることは間違いありませんが、あらゆる問題を解決するものではありません。エンジニアとしてはFirebaseの特性ををよく理解し、使うべきケースでそれを投入する知識と同様に、使うべきではないケースで無理に使わないようなアドバイスができるようになることが重要です。
「いまのところ、(僕が)やりたいことを実現するためには総合的に見てFirebaseを使うのがベストな選択だよ」というくらいの推し度です。
Firebaseで大規模アプリケーションは無理じゃないの?
僕の観測範囲にそれをサポートするエビデンスはありません。大規模と言えるほどのものをやったことがないので出来るとも断言しませんが、感触としては可能であろうと思っています。何をもって大規模とするかはまちまちですが、Firebase自体のスケーラビリティは同時アクセスするユーザ数が100万くらいまでは全く問題ないと思います。エミュレータも充実しつつあるので、チーム開発特有の懸念もなくなってきています。ランニングコストが見合うかどうかは別途考えなければいけないポイントです。ただ、Firebaseがなかったときに必要になる開発・運用の工数まで考えるとFirebaseをつかったほうがトータルのコストは安くなることが大半だろうとは思います。
大規模アプリケーションを構築する場合、全てのデータをFirestoreで持つことはおそらく誤りです。Firestoreにはクライアントから参照したいデータをクライアントにとって便利な形式で保存しておけばよく、それ以外に必要なデータはGCPなりなんなりをつかって拡張したバックエンドで持つことになるでしょう。マイクロサービスと組み合わせて使うことも十分考えられます。
リアクティブなアーキテクチャって実際どうなの?
可能性は感じますが、僕の観測している世界が狭すぎるということも自覚しています。あらゆるアプリケーションで適用できるかどうかといわれるとまだわかりません。(なのでたくさんの人に挑戦してほしいなーというのが先の記事の隠れた主旨です。)
公私含めいくつかのアプリケーションでこのアーキテクチャを試してきましたが、解決したかった問題は解決できた、という認識までにしか至っていません。もちろんいくつかの問題は見つかっていますが、それがアーキテクチャに由来するものなのかどうかはサンプル数が少なすぎて断定できないという状態です。なので、しばらくはこれで挑戦していくと思います。
必ずしもリアクティブであることが重要であるとは限りません。「システム化の対象である現実の業務(プロセス・フロー)をなるべく正確にモデル化する」ことが大事であると考えています。そうすることで、メンバーの理解の助けになるなどの効果が期待できます。DDDがユビキタス言語の利用を推すのと同じような思想です。
トランザクションとか非同期とか辛くない?
辛いです。それ自体を実装する難易度と言うよりは、アプリケーションの動きをリアクティブ(≒非同期)に対応させて不自然じゃなくすることが辛いです。これまでの常識はまぁまぁ通用しなくなります。ですが、より良いユーザ体験を考えるための良い機会ということで前向きに取り組んでいます。
REST APIってオワコンなの?
個人的にはオワコンになってほしいとは思いますが、まだまだ現役です。特に、外部システムと連携する場合はしばらくREST APIのお世話になることでしょう。Firebaseを取り入れたアプリケーションでは、Cloud Functionsから外部システムへ接続しますが、その境界ではやはりAPIが必要になります。自分では使いたくないですが、必要ではあると思います。
ちなみにオワコンになってほしい理由はシンプルで、フロントエンドの改修スピードに追従するのがキビシイからです。真面目にAPIを作ろうとすると必ず認証・認可1の話や性能面を中心とした非機能要件の話やバージョニングの話がついて回り、開発のボトルネックになるのが悲しかったからです。
Firestoreを使うとフロントエンドエンジニアが当たり前にデータベースに触ることになるので、少なくとも開発をブロックすることはありません。最終的にフロントエンドで必要なデータ形式が安全に取得できるようサーバサイドロジックとセキュリティルールを頑張るだけです。
リレーショナル・データベースでいいんじゃないの?
リレーショナル・データベース(RDB)であなたの問題が解決できるのであれば、それでいいと思います。僕がやりたいことには用がたりないので諦めました。もしクライアントアプリケーションから直接アクセスできるRDBが登場したら検討するかもしれませんが、RDBゆえのインピーダンスミスマッチがきついことが想定されるので多分使わないと思います。
クライアントからデータベースに直接つなぐということは、RDB界ではよく使われるO/Rマッピングのようなことをやってくれる層がなくなるということを意味します。やるとしたらクライアント側でやることになりますが、マルチプラットフォームを想定するとあまりいい戦略ではありません。そのへんを考えた上で、データモデルの設計をすることになります。これはRDBの時代のベストプラクティスとは激しく乖離する思想です。でもまぁやる価値が十分あるんじゃないかと思われるのでやっています。
スキーマレスの辛みはよくいわれますが、一長一短です。慣れないと辛いと思います。この辺に関しては本に書いたので読んでください(宣伝)。RDBでも辛いものは辛いと思います。特に、データ(とデータベース)は触るのを怖がって、ドメインモデルが変わったのにデータベース上のデータモデルは変えずになんとか耐えようという試みが無意識のうちにサーバサイドで行われてきたのはそろそろ改めるべきと思っています2。データベースの種類を問わず、データモデルに変更が必要なら変更できるような仕組み・スキルを備えることが大事ではないでしょうか。
それならGraphQLでいいんじゃないの?
GraphQLは良い代替となる可能性があります。APIを介さずにクライアントからデータストアに直接アクセスできるという点では同等の機能性を備えていると言えます。また、リアクティブな世界に必須のsubscriptionが使えることも注目すべきポイントです。
ただし、Firestoreと比べると書き込み(mutation)時の認証・認可とデータのバリデーションがちょっとめんどくさいな3という気持ちがあります。また、subscriptionを使おうとするとサーバレス4構成をうまく維持するのが難しいなという思いもあります。ついでにいうと、キャッシュ処理やsubscriptionのオフライン状態での動作をFirebase SDKがやってくれているレベルで実装しようとすると想像を絶する困難度があるなとも思います。このへんの要件が緩い、あるいは自力で実装できるなら現状のGraphQLでもいけるとおもいます。
ベンダーロックインとはどう向き合っているの?
(今のところは)気にしないくてよいだろうと思っています。もちろんずっとこの方針で行くことはありませんが、少なくとも標準的な中小規模のアプリケーションの寿命くらいであれば問題が顕在化することはないと判断しています。一方で、代替技術については当然検討しています。たとえば、AWSのAppSyncなどには可能性があるかもしれません。
いきなり料金が上がる懸念についてはあまり心配していません。裏側はGCPと共通なので、Firebaseだけ料金上乗せするのはほぼ不可能である(しようとしてもGCPに逃げることが可能であり、GCPも一緒に値上げすることはもっと考えにくい)と思っています。
アーキテクチャを考えるときに、そのアーキテクチャをいつ辞めるかを予め計画しないのは自殺行為(あるいは無責任)です。僕はモノによりますがだいたい7年くらいもてばいいかなという気持ちで設計します。7年もしたらきっとまた新しい何かがでているはずなので、それで作り直してください、というようなことをいつも言っています。
結局何がいいたかったの?
ちゃんと考えた結果、全くまとまりがなかったことが判明しましたがいまさら元記事をいじるわけにもいきません。反省しつつここに箇条書きにしておきます。
- 課題を捉えて、正しい技術を選ぼう
- システム化の対象を正確にモデル化しよう
- システム内部にREST API作るのやめたい
- Firebaseはいいぞ
- 本を買ってくださいお願いします
最後になりますが、アーキテクチャ設計の際に気をつけてなければいけないのは不可逆な意思決定をしないことです。これはきっと何らかの間違いを発見するであろう将来の誰かへの最低限の配慮です。間違っていたらきっとそれを見つけた人が直してくれることを期待して、現実的にやり直しが出来る範囲であればどんどん新しいことにチャレンジするのが大切だと思っています。
という一見有益なメッセージを残して、2019年の執筆を終えたいと思います。良いお年を!