ONEDiaryが最初にスマホへ保存する理由
通信が必要な日記アプリは、地下鉄で使わなくなります。書く操作がネットワークを待たないよう、保存層をどう組み立てたかを紹介します。
多くの日記アプリはアカウント画面から始まります。ONEDiaryは空白のページから始まります。これはエンジニアリングより先に決めたプロダクト上の判断ですが、保存層もそれに合わせなければ続きません。だからこの部分は最初に設計し、最も変更を少なくしてきました。
原則:書く操作はネットワークを待たない
保存層が守るべきルールは一つです。保存をタップしたら、その後に何が起きるより先に記録が永続化されます。アップロード待ちにするのでも、リクエスト中に楽観的に表示するのでもありません。端末のディスクに書き込み、ローカルトランザクションとしてその場で成功か失敗を決めます。
この記事の残りは、すべてこのルールから導かれます。
Roomが信頼できるデータの源
ONEDiaryは端末上の Room データベースに記録を保存します。UIはネットワークから読みません。画面はKotlin Flowを通じてRoomを監視するため、タイムライン、カレンダー、検索は同じローカルテーブルを描画し、書き込みが完了した瞬間に更新されます。
ここは正確に理解しておきたいところです。オフライン対応は、サーバーを正とし、端末に無効化できるキャッシュを置く形で作られることがよくあります。フィードには適した設計です。しかし日記には向きません。書いたものは何かのキャッシュではなく原本であり、コピーが存在しない可能性もあるからです。
- 読み取りは常にRoomから行います。接続状況に依存するローディング画面はありません。
- 書き込みはRoomにコミットされ、その後に別の層が端末の外へ送る必要があるかを判断します。
- 競合はローカルデータを基準に解決し、書き込みを拒否して解決することはありません。
Firestoreは家ではなくミラー
ログインして データ同期 をオンにすると、ONEDiaryはログイン中の端末どうしが揃うように記録をFirestoreへミラーします。文の順番が大切です。ログインは任意で、同期は別のスイッチであり、ミラーはローカルデータベースから派生します。
つまり同期層は遅くても、失敗しても、再試行しても、書く体験に見せずに済みます。アップロードの失敗はバックグラウンドで再試行されます。記録が失われたり、保存ボタンが押せなくなったりすることはありません。
オフラインモードが実際にすること
オフラインモード は同期状態を隠すUIのトグルだと思われがちですが、そうではありません。オンにするとFirestoreとの同期を一時停止し、保留中の変更を再開するまで端末に保持します。
接続があることと、それを使いたいことは別の問題で、後者を決められるのはユーザーだけです。高いローミング料金、まだミラーしたくない記録、電波を静かにしておきたい時間。どれもログアウトせず、設定を失わずに一時停止する理由になります。
オフに戻すと、キューに入った変更はバックグラウンドで処理されます。その間に捨てられるものはありません。
初期状態が設計を語る
新規インストールで取り得る三つの状態を並べると、設計の順序が見えてきます。
- 新規インストールアカウントなし、同期なし、AIアクセスなし。書く、読む、検索する、写真を添付する、カレンダーを見ることができます。アプリはこの状態で出荷され、多くの人はそのまま使い続けます。
- ログインしてデータ同期をオンログイン中の端末間で記録が揃います。いつでもオフにでき、オフラインモードで一時停止もできます。
- AIアクセスを許可別に明示して許可する権限です。許可した後だけ、レポートと日記チャットが記録を読めます。同期をオンにしてもAIアクセスはオンになりません。
これは設定という名前のアップセルではありません。決めるまではすべてオフで、オンにした画面からいつでも戻せます。
私たちが負担するコスト
正直に言えば、ローカル優先は仕事を減らすのではなく増やします。確認できない端末にあるスキーマのマイグレーションを保守し、サーバーのスクリプトで壊れた行を直すこともできません。中央データベースなら簡単な、端末に受け取らない内容の端末間全文検索のような機能は、難しくなるか、選択肢から外れます。
取り戻せないものを守るアプリなら、その代金を払う価値があると考えています。ただし代金は存在し、リリースのたびに支払う必要があります。
自分のスマホで試す。
Google Playから無料で利用できます。Android 10以降なら、アカウントなしで記録を始められます。