OurCarの構築: UX、状態管理、そしてノーと言う技術

家族と車を共有することは、ガスタンクが空になるまで簡単に思えることが多いです。Mendel Greenberg にとって、燃料費の分担やスケジュール調整の摩擦が、技術プロジェクトのきっかけとなりました: OurCar。ガス代に関する「千切りの死」を回避しようとした試みが、クロスプラットフォーム開発、ユーザーエクスペリエンス(UX)デザイン、そしてニッチなアプリケーションを維持する現実への深い探求へと発展しました。

問題点: 調整の摩擦

根本的な問題は、古典的な調整失敗でした。家族が長距離旅行後にタンクを補給しようとしても、ちょっとした用事でタンクは徐々に減っていきます。その結果、タンクが空になる瞬間に車を運転していた人に不公平な負担がかかっていました。

Greenberg の目標は、"WhatsApp グループよりも車の共有に適したもの" を作ることでした。これには次の3つの主要機能が必要でした:

  1. Location Tracking: 車が利用可能なときにどこに駐車されているかを把握する。
  2. Status Monitoring: 誰がいつ車を使用しているかを追跡する。
  3. Fuel Accounting: 燃料使用量を監視し、誰が給油すべきかを判定する。

技術スタック

プロトタイプから本番へ迅速に移行するため、Greenberg は軽量なスタックを選択しました:

  • Frontend: Flutter を使用したクロスプラットフォーム対応。
  • Backend: Pocketbase によるシンプルな BaaS 体験。
  • State Management: Riverpod を用いて複数ページ間のデータ同期を実現。
  • Navigation: Auto Route でディープリンクと複雑なルーティングを処理。

Claude Code のようなエージェント開発ツールはトラブルシューティングや二次機能(例: アカウント削除ポータル)の構築に利用されましたが、コアアーキテクチャは手作業で実装し、システムへの深い理解を確保しました。

"Native" デザインの課題

最も大きなハードルの一つは、iOS と Android の両方で "ネイティブな感触" を実現することでした。Flutter は Material(Android)と Cupertino(iOS)という両デザインシステム用のウィジェットを提供しますが、自動で切り替える機能はありません。

この問題を解決するために、Greenberg は flutter_platform_widgets パッケージを利用しましたが、レイアウトの慣習はプラットフォーム間で依然として大きく異なり、微妙な差異に対処するために "スパゲッティコード" が生まれがちでした。最も効果的な UI 設計方法は、すでにクロスプラットフォームのバランスをマスターしているアプリ、特に WhatsApp を参考にすることだと彼は述べています。

"標準的な慣習に従えば、人々はすぐに全体の仕組みを理解します。なぜなら、彼らはその種のインタラクションを何度も経験しているからです。"

スコープクリープとノーと言う技術

アプリが家族に広がるにつれ、メンテナンススケジュール、オドメーター走査のコンピュータビジョン、リアルタイム GPS 追跡などの要望が次々と寄せられました。これにより、"アンチ機能" に関する重要な意思決定が迫られました。

たとえば GPS 追跡は、バッテリー消耗とプライバシーの二つの理由で却下されました。アプリは車がどこに駐車されているかを知る必要がありますが、すべての移動を追跡するとユーザーの私生活に関するプライベート情報が露呈してしまいます。これらをアンチ機能として明確にすることで、開発者はコアユーティリティを保ちつつ、ユーザーの信頼とデバイス性能を損なうことなくアプリを維持できました。

エンジニアリングの落とし穴と反復

State と Performance

初期バージョンは "jank" と同期問題に悩まされました。開発者は "mega-widgets" を作成すると、親ウィジェットの小さな状態変化がすべての子ウィジェットの再描画を引き起こし、過剰な repaint が発生することに気付きました。解決策は、状態を分離した小さく管理しやすいウィジェットへと徹底的にリファクタリングすることでした。

State-Machine アプローチ

当初は燃料ログと走行ログが別々に管理されており、ユーザーは混乱していました。Greenberg はこれを単一の統合タイムライン、すなわち状態機械へと移行させました。ロジックは二元的になり、車は "返却されたときにだけ借りられ、借りられたときにだけ返却できる" という形になりました。

"より抽象的な state machine — データ保存方法に依存しないロジック — を採用すれば、ユニットテストがしやすくなり、バグも減少したでしょう。"

コミュニティの視点: オーバーエンジニアリング vs. ユーティリティ

このプロジェクトは Hacker News で議論を呼び、アプリの必要性について意見が分かれました。一部の批評家は、鉛筆とメモ帳、あるいはシンプルな PWA(Progressive Web App)で十分だと主張し、"オーバーエンジニアリング" の例だと指摘しました。

しかし別の意見では、専用アプリの価値は単なるデータ記録ではなく、ワークフロー を強制する点にあると述べられました。あるコメントは次のように書いています:

"みんなが実際に開く粗い UI は、1 人が管理するきれいな紙のログを上回ります…目的に合わせて作られたヘルパーは、記録だけでなくワークフローそのものになるのです。"

技術的な提案としては、OBD-II Bluetooth ドングルを統合し、燃料とオドメーターの読み取りを自動化して手動入力の摩擦を完全に排除する案も出されました。

結論: ニッチアプリのライフサイクル

結局、OurCar は "永遠のアルファ" のままでした。家族が離れ住むようになると、アプリの即時的な必要性は消え、さらなる開発への熱意も枯渇しました。それでも、このプロジェクトは痛点の特定、プロトタイピング、アプリストア認証の複雑さ、反復的 UX デザインといったソフトウェア開発ライフサイクル全体を体験する包括的な演習となりました。

Sources