スタートアップはFirestoreを使うな

--

要約すると題名のとおりである。Firestoreをおすすめしない理由は大きく分けて2つである。

  1. スキーマがない問題
  2. その他のクソな問題達

1. スキーマがない

スキーマがないということはどういう事かわからない人が多いようだ。

本当にあなたのアプリがスキーマを必要としないのであればFirestoreはいい選択だろう。ただ、そんなことはあるのだろうか。

例えば次のような問題が起こる。Userのモデルを作るとして時、Ageというフィールドを用意したとする。年齢なのでInteger型としよう。ところが、スキーマがないからそこには数字ではなく文字列の”37”といった文字列を入れることが出来る。はたまたフィールド名をageと誤り全部小文字のフィールド名に値を代入する事もできる。スキーマレスである限り、どのようなデータも入れたり定義することが出来るのだ。

そんなバカな事は起きないだろうという楽観的な人がいるかもしれないが、実際にconfirmed_passwordが何故か入ってしまっていて、パスワードが平文でDBに意図せず混入していたという話を聞いたことがある。スキーマを定義していれば、このようなミスは起きえない。

結局、こういうミスを防ぐためにオレオレフレームワークみたいなもの書くことになる。そこにはモデルが定義され、その自分の書いたフレームワーク以外でデータの挿入や更新をさせなくしたくなる。ただよく考えれば、スキーマレスバンザイで初めたサービスだったのに、フレームワーク側でスキーマを定義して運用をせざるを得なくなっている。だったらはじめからスキーマのあるDBを使ってもよいのではないか。

またオレオレフレームワーク内では、create, updateなどを直書きする必要がある。これはいつの時代だろう。PHPでSQLの生コードを書いている時代と何も変わらない

RailsやDjangoではORMが用意されていて今はSQL文を直接書くようなことは無い。直書きはバグも発生するし、なにより開発時間がかかり、危険だ。

スキーマレスの問題はそれだけではなく、複雑化による開発の困難性も問題になる。当初単純だったアプリも顧客の要望やエンジニアの希望により複雑化してくる。エンジニアの能力によっても、非正規化、正規化したり、DocReference貼りまくったりする人などDB内が管理が必要になる。Firestoreは自由度が高いため、開発者が多くなればなるほど色んな流儀が出てくるし、また最適解も見つけにくい為、ルール作りを考えていかなくてはならない。

その他、Android, iOS、Web開発などでそれぞれのフレームワークを使い始めるとカオスになり始める。別のプラットフォームから間違ったデータをプッシュしたら他のプラットフォームではクラッシュしてしまう問題も発生する。

それでは、1つのサーバーのみを介すAPIアクセスだけに限定して処理するルールを作ればいいのではないか?となるだろう。しかし、Firestoreの素晴らしい(私が思う唯一の)機能としてリアルタイムチャットを簡単に実装できる機能があるが、これはクライアントサイドのアプリとFirebase/Firestoreが直接通信する仕組みである。Firebaseと直接通信する必要があるため、手前で作ったサーバーを介せない。つまり、クライアントアプリ側でDBのモデルやコントローラーを書くことになりルール違反となる。1つのサーバーのみというルールを敷けば、こうした便利機能が使えなくなってきてしまう。

結局どこかいつかのタイミングで誰かがスキーマを定義する事が必要となるのがだが、今度はスキーマ情報(モデル情報)の管理方法が問題になってくる。(スキーマレスなDBなのだが!)スキーマをどうやって管理すればいいのか?共有フォルダのテキストファイル?Notion? Google drive ? Git ? 誰でも触れるのか?整合性はとれているのか?記載漏れがあったらどうなる?すべてのチームのメンバーがその重要性を理解して、きちんとミス無くモデルを定義し管理する仕組みづくり、運用はできるのだろうか。

こうした悩みが次々と発生して、チーム内で不要な相談とやり取りが増えてくる。つまるところ開発効率が非常に悪くなる。

2. その他のクソな問題達

Firestoreの難点はそれだけにとどまらない。

検索がPoorすぎるというのがある。集計することが非常に難しい。

FirestoreはWhere検索と言って条件にあった検索ができる機能がある。例えばユーザーの年齢が37歳以上とかで一覧をとってこれる。ただし、制限が有り、2個以上の不等号の検索が出来ない。つまり、10歳以上、20歳未満の人を抽出などができないということだ。こうしたことにいちいち頭を悩ませる事がモデルが増えれば増えるほど多くなる。そのため、不要なフィールドの追加や、コレクションの追加が発生し始める。オレオレフレームワークのモデルもその都度更新していき、システムはどんどんと汚れていく。

リレーションが貼れないのも大きな問題だ。いやいや、貼ることが出来るという人がいる。確かにDocReference型がある。しかし、DjangoやRailsのようなフレームワークを使わずしてリレーションを貼る行為は非常に危険である。自殺行為だ。

例えばそのオブジェクトの指し先が消された時にどうやって感知するのか?答えは当然出来ない。従って、オレオレフレームワークで消した際の振る舞い、管理機能も作っていかなければならない。誰が?一体誰が開発するの?それはあなたである。

場合にも依るがFirestoreはDBを正規化せずそのまま突っ込んでいくのが理想である。リレーションを多く貼ったり、正規化するのであればスキーマレスなDBでなく、リレーショナルDBを検討したほうが良い。上でも述べたとおりフレームワーク無しでドキュメントDBでリレーショナルを貼るなんて考えたくない。

断言できるが、いつかMany to Manyテーブルが恋しくてたまらなくなってくる。その頃には、なんでFirestoreを選んだのか後悔し始めるに違いない。

バックアップが非常に難しいのもFirestoreの悪いポイントだろう。言ってしまえばProductionからStagingへのコピーが容易ではない。これも開発効率を非常に悪くさせる。機能が完成してテストを走らせたい時に、(本当は良くないが)Productionからデータを引っ張ってきてチェックしたいという事がある(二回目だが本当は良くない)。Firebaseはこれができない。なぜならユーザデータの移行が簡単でないためだ。そこそこのアプリサイズになればユーザーとFirestoreがなにかしら(多くはUID)で紐付いているが、ユーザー群を引っ張れないため、本番環境のデータを用いたテストや確認が非常に難しくなる。Firestoreの移行すら管理画面でポチポチしたりと大変である。Firebase Local Emulator Suiteを使えば良いと思うかもしれないが、大変な経験をするので是非やってみてほしい。

最後に

Firebaseは一度手を出したが最後だ。ユーザー認証部分があり、他に移行することは容易ではなくなるからだ。

だからこそ、スタートアップが最初にFirestoreを選択すると超絶後悔で死にたくなるに違いないと思い、この記事を書いた。

Firestoreを使うと、とにかく考えさせられる時間が多い。出来ないからどうしようか、と相談したり、紆余曲折のソースコードを書いたり、不要なフィールドを追加してテストしたり、色々と調べたり…と、全く持ってナンセンスだ。開発時間がいくらあっても足りないくらいだ。

Firebaseは投資家へのテストアプリや、簡単なサービス、部分的にpub/subを使うサービス、超スモールなサービスには優れている。リレーショナルデーターベースをよくわかっていないクソエンジニアにも適している。

私の話に対して、反論する人もいるだろう。アプリや開発手法やサイズによって変わる、バックアップの仕方はそうではない、リレーションの貼り方をこうすれば解決できる、スケーラビリティが優れている、などなど。

聞きたくもないし、愛してやまないFirestoreを勝手に使い続けていれば良い。

--

--