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

Feb 10 2022
要約すると題名のとおりである。Firestoreをおすすめしない理由は大きく分けて2つである。 スキーマがないということはどういう事かわからない人が多いようだ。 本当にあなたのアプリがスキーマを必要としないのであればFirestoreはいい選択だろう。ただ、そんなことはあるのだろうか。 例えば次のような問題が起こる。Userのモデルを作るとして時、Ageというフィールドを用意したとする。年齢なのでInteger型としよう。ところが、スキーマがないからそこには数字ではなく文字列の”37”といった文字列を入れることが出来る。はたまたフィールド名がageと誤って全部小文字のフィールドと値で代入する事もできる。スキーマレスである限り、どのようなデータも入れたり定義することが出来るのだ。 そんなバカな事は起きないだろうという楽観的な人がいるかもしれないが、実際にconfirmed_passwordが何故か入ってしまっていて、パスワードが平文でDBに意図せず混入していたという話を聞いたことがある。スキーマを定義していれば、このようなミスは起きえない。 結局、こういうミスを防ぐためにオレオレフレームワークみたいなもの書くことになる。そこにはモデルが定義され、その自分の書いたフレームワークを使ってじゃないとデータの挿入や更新ができなくなる。ただよく考えれば、スキーマレスバンザイで初めたサービスだったのに、フレームワーク側でスキーマを定義して運用をせざるを得なくなっている。だったらはじめからスキーマのあるDBを使ってもよいのではないか。 またオレオレフレームワーク内では、create, updateなどを直書きする必要がある。これはいつの時代だろう。PHPでSQLの生コードを書いている時代と何も変わらない。 RailsやDjangoではORMが用意されていて今はSQL文を直接書くようなことは無い。直書きはバグも発生するし、なにより時間がかかり、危険だ。 スキーマレスの問題はそれだけではない。複雑化による開発の困難性だ。当初単純だったアプリも顧客の要望やエンジニアの希望により複雑化してくる。そのため、どこかいつかのタイミングで誰かスキーマを定義する必要となってくる。そのスキーマ情報(モデル情報)がどこかで一元管理されていればいいが、そううまくもいかない。 スキーマがないと(あっても)、Android, iOS、Web開発などでそれぞれのフレームワークを使い始めるとカオスになり始める。別のプラットフォームから間違ったデータをプッシュしたら他のプラットフォームではクラッシュしてしまう問題も発生する。 じゃあ1つのサーバーのみを介すAPIアクセスだけに限定して処理するルールを作ればいいのではないか?となるだろう。ただ、例えばFirestoreの素晴らしい(私が思う唯一の)機能としてリアルタイムチャットを簡単に実装できる機能があるが、これはクライアントサイドとFirestoreが直接通信する仕組みである。直接Firebaseと直接通信する必要があるため、手前で作ったサーバーを介せないので、クライアント側でDBのモデルやコントローラーを書くことになる。一つのサーバーのみというルールを敷けば、こうした便利機能が使えなくなってくる。 (スキーマレスなDBなのだが!)スキーマをどうやって管理すればいいのか?共有フォルダのテキストファイル?Notion? Google drive ? 誰でも触れるのか?整合性はとれているのか?記載漏れがあったらどうなる?すべてのチームのメンバーがその重要性を理解して、きちんとミス無くモデルを定義し管理する仕組みづくり、運用はできるのだろうか。 こうした悩みが次々と発生して、チーム内で不要な相談とやり取りが増えてくる。つまるところ開発効率が非常に悪くなる。 2. その他のクソな問題達 Firestoreの難点はそれだけにとどまらない。 検索がPoorすぎるというのがある。集計することが非常に難しい。 FirestoreはWhere検索と言って条件にあった検索ができる機能がある。例えばユーザーの年齢が37歳以上とかで一覧をとってこれる。ただし、制限が有り、2個以上の不等号の検索が出来ない。つまり、10歳以上、20歳未満の人を抽出などができないということだ。こうしたことにいちいち頭を悩ませる事がモデルが増えれば増えるほど多くなる。そのため、不要なフィールドの追加や、コレクションの追加が発生し始める。オレオレフレームワークのモデルもその都度更新していき、システムはどんどんと汚れていく。 リレーションが貼れないのも大きな問題だ。いやいや、貼ることが出来るという人がいる。確かにDocReference型がある。しかし、DjangoやRailsのようなフレームワークを使わずしてリレーションを貼る行為は非常に危険である。自殺行為だ。 例えばそのオブジェクトの指し先が消された時にどうやって感知するのか?答えは当然出来ない。従って、オレオレフレームワークで消した際の振る舞い、管理機能も作っていかなければならない。誰が?一体誰が開発するの?それはあなたである。 そもそもFirestoreはDBを正規化せずそのまま突っ込んでいくのが理想である。リレーションを貼るなどの正規化するのであればスキーマレスを使う必要はなく、リレーショナルDBを検討したほうが良い。ドキュメントベースのデータベースでリレーショナルを貼るなんて考えたくない。 断言できるが、いつかMany to Manyテーブルが恋しくてたまらなくなってくる。その頃には、なんでFirestoreを選んだのか後悔し始めるに違いない。 バックアップが非常に難しいのもFirestoreの悪いポイントだろう。言ってしまえばProductionからStagingへのコピーが容易ではない。これも開発効率が非常に悪くさせる。機能が完成してテストを走らせたい時に、(本当は良くないが)Productionからデータを引っ張ってきてチェックしたいという事がある(二回目だが本当は良くない)。Firebaseはこれができない。なぜならユーザーのデータの移行が簡単でないためだ。そこそこのアプリサイズになればユーザーとFirestoreがなにかしら(多くはUID)で紐付いているが、ユーザー群を引っ張れないため、本番環境のデータを用いたテストや確認が非常に難しくなる。Firestoreの移行すら管理画面でポチポチしたりと大変である。Firebase Local Emulator Suiteを使えば良いと思うかもしれないが、大変な経験をするので是非やってみてほしい。 最後に Firebaseは一度手を出したが最後だ。ユーザーが利用しているので認証部分を他に移すことは容易ではなくなるからだ。 だからこそ、スタートアップが最初にFirestoreを選択すると超絶後悔で死にたくなるに違いないと思い、この記事を書いた。 Firestoreを使うと、とにかく考えさせられる時間が多い。出来ないからどうしようか、と相談したり、紆余曲折のソースコードを書いたり、不要なフィールドを追加してテストしたり、色々と調べたり…と、全く持ってナンセンスだ。開発時間がいくらあっても足りないくらいだ。 Firebaseは投資家への簡単アプリを作りプレゼンや、サービスをお試ししたい人、超スモールなサービスには優れている。リレーショナルデーターベースをよくわかっていないクソエンジニアにも適している。 私の話に対して、反論する人もいるだろう。アプリや開発手法やサイズによって変わる、バックアップの仕方はそうではない、リレーションの貼り方をこうすれば解決できる、スケーラビリティが優れている、などなど。 聞きたくもないし、勝手に愛してやまないFirestoreを使い続けていれば良い。.

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

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

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

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

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

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

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

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

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

スキーマレスの問題はそれだけではない。複雑化による開発の困難性だ。当初単純だったアプリも顧客の要望やエンジニアの希望により複雑化してくる。そのため、どこかいつかのタイミングで誰かスキーマを定義する必要となってくる。そのスキーマ情報(モデル情報)がどこかで一元管理されていればいいが、そううまくもいかない。

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

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

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

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

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

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

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

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

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

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

そもそもFirestoreはDBを正規化せずそのまま突っ込んでいくのが理想である。リレーションを貼るなどの正規化するのであればスキーマレスを使う必要はなく、リレーショナルDBを検討したほうが良い。ドキュメントベースのデータベースでリレーショナルを貼るなんて考えたくない。

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

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

最後に

Firebaseは一度手を出したが最後だ。ユーザーが利用しているので認証部分を他に移すことは容易ではなくなるからだ。

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

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

Firebaseは投資家への簡単アプリを作りプレゼンや、サービスをお試ししたい人、超スモールなサービスには優れている。リレーショナルデーターベースをよくわかっていないクソエンジニアにも適している。

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

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