DropboxとSlackにおける、iOS/Andrioid共通開発の”隠れたコスト”
原文(投稿日:2019/11/25)へのリンク
新しいネイティブモバイルアプリの開発には多大な労力が必要になる。Android用にKotlin/Javaでコーディングしたものを、iOS用にObjective-C/Swiftを使ってもう一度行わなくてはならないからだ。DropboxとSlackはこれまで、C++で共有ライブラリを記述することによって、プラットフォーム間でコードを共有する方法で実装を行ってきたが、最近になってこの方法を止める決定をした。
DropboxのEyal Guthmann氏とSlackのTracy Stampfli氏が先日、なぜC++の使用を止めて各プラットフォームのネイティブ言語に移行することにしたのか、その理由について説明してくれた。その内容を紹介しよう。
2013年にDropboxは、AndroidとiOSのコードを共有するために、極めてシンプルな方法を採用した。JavaやObjective-Cではなく、最初にC++で記述することにしたのだ。Dropboxの開発チームは比較的小規模だったが、iOSとAndroidの両方向けに大量のコードを提供する必要があった。
Guthman氏によると、Dropboxがこの方法を破棄したのは、コードの共有に伴う隠れた(という程でもないが)コストが理由だった。
そのようなオーバーヘッドの対策としてDropboxチームは、フレームワークやライブラリをいくつも開発した。言語間で共有可能な型定義やインターフェースバインディングを生成するツールであるDjinniや、メインスレッドに対してバックグラウンドでタスクを実行する — KotlinやSwiftならば簡単な作業だ — ためのフレームワーク、JSONのシリアライズとデシリアライズを行うjson11、C++で非nullポインタを実現するnnなどだ。
Android StudioやXcodeといったプラットフォーム既定の開発環境を使用できないことも、Dropboxチームにとって大きなオーバーヘッドとなった。バッググラウンドスレッドのフレームワーク内で発生したバグによる、アプリのランダムなクラッシュをデバッグした時の経験について、Gutgman氏は話してくれた。C++とJavaの間を行き来するマルチスレッドコードのデバッグに関係したため、修正には数週間を費やしたという。
プラットフォーム間の差異に関する処理も大きなオーバーヘッドになった。バックグラウンドでのタスクの実行、カメラロールへのアクセス方法といったことも、問題になる場合があったのだ。異なるプラットフォームにコードを統合してプラットフォーム固有のコードを記述するために、チームは非常に多くの時間を費やすことになった。最終的には固有コード自体がひとつのC++レイヤになる場合もあったのだ。
開発者をトレーニングし、雇用し、引き止めておくことも大きな課題だった。Guthman氏が言うには、この方法を採用した当初は、社内に経験豊富なC++開発者のグループがあり、彼らが最初にC++プロジェクトを立ち上げて他のモバイル開発者をトレーニングしていた。その後、これらの開発者たちは他のチームや他社へ移籍したが、残った技術者たちは、その技術的リーダシップのギャップを埋めるのに十分な経験を持っていなかった。非常に特殊なスキルセット(モバイル/C++開発)を備えた開発者を採用しようと試みたが成果がなく、結果として、モバイル開発者たちはC++プロジェクトに関与することを望まなくなり、能力のある一部のモバイル開発者がプロジェクトに残ることになった。
Slackでも状況は変わらない — 同社では、共有ビジネスロジックをカプセル化して、データの同期とキャッシュを処理するLibslackを開発している。当初の計画ではデスクトップ、iOS、Android、Windows PhoneのクライアントでLibslackを使用する予定だったが、キャッシュ処理に関わる不整合が理由となり、実際にはiOSとAndroidのみで使用されている。
Stampfil氏によると、SlackでもDropboxと同じように、Libslackの導入後にオーバーヘッドが発生した。Slackでは、すでに安定しているモバイルアプリを対象にLibslackを追加して、既存の機能を置き換える計画であったので、2つの確立したアーキテクチャにフィットさせる必要があった。Libslack導入前は、各モバイルクライアントが異なるスケジュールで提供されていたが、導入後はリリースサイクルを共有するようになった。これにより、ホットフィックス対象の決定などに問題が生じるようになった。Slackのモバイルエンジニアの大部分は、C++言語や、Libslackの問題を修正するために必要なビルドやデバッグのプロセスに習熟していなかったのだ。
Dropboxが経験したように、C++の経験を持つモバイルエンジニアの採用は難しく、そのためにLibslackの拡張や維持が困難になったと、Stampfli氏は述べている。
最終的にSlackでは、ライブラリ開発のオーバーヘッドがメリットを上回っていると判断したため、プロジェクトを中止し、プラットホーム固有の言語を使って各クライアントアプリケーション毎にLibslackの機能を実装するという、以前のネイティブなアプローチに戻す決定をした。
なぜReactive NativeやFlutter、Cordova、Ionicといった他のフレームワークを使わなかったのだろう、と疑問に思うかも知れない。
実を言うと、Dropboxのケースでは、開始時点にはSwiftもKotkinも存在していなかったのだ。React NativeやFlutterは比較的若いフレームワークだが、React Nativeを使用していたAirbnbなど一部の企業では、デバッグの問題などの同じような理由から、React Nativeの使用を中止する決定を下している。