最近のこと (退職 ~ 無職 ~ 転職)

お久しぶりです。Andyです。

前職を辞めてから2ヶ月ほどが経ち、いろいろな事がありました。

将来この2ヶ月を振り返って結構おもろかったなーと思えるよう、備忘録的に記事をしたためます。

f:id:andoshin11:20180729033244j:plain

退職

5/31付で3ヶ月勤めた会社を離れました。

初めはReactを書くつもりでしたが気づいたらVueを書いていたり、100人以上が集まるNuxt Meetupを開催したり、はたまたMicroservicesのアーキの話に首を突っ込んだりと楽しい時間でした。

FinTech領域で優秀なメンバーと仕事ができて学ぶ事が多かったです。

無職突入

退職のタイミングでいくつかオファーをいただいていたのですが、なるべく慎重に次の会社を選びたかったし、なにより自分自身のスキルをもう少し高めなきゃならんなということで無職期間に突入。

ブログの更新は12日で辞めてしまいましたが、当初の想定どおり6月いっぱいは良い感じにアタマとカラダを鍛えられました。詳細は後述。

また時間的な余裕ができたことで、普段はなかなか会えない友人と親交を深められたり、小旅行に出かけられたりできたのが良かったです。

何度か関西に帰省したり、軽井沢に行ったり、横浜に行ったり、幼馴染とNBA Finalsを観戦したり。

今後もしばらくはスタートアップでどっぷり働くと思うのですが、人一倍と休暇には時間とお金を投資していきたいです。

修行編

生来の怠け癖というのはなかなか抜けないもので、このままではダラダラと時間もお金も使い果たしてしまうなと、おバカな頭で直感しました。

そこで「アタマとカラダを鍛える」ということで、いくつか目標を立ててそれに向かって取り組むことに。

studio-andy.hatenablog.com

その際の意気込みというか決意表明的なものは上の記事を参考のこと。

1ヶ月間の主なAchievementsとしては以下の通りです。

カラダを鍛える

ランニング:

なるべく毎日走るようにしました。久々の運動なので少しヒザを痛める醜態もありましたが、それと天気の悪い日を除いてはほぼ達成。帰省中は京都でも鴨川沿いを走れてなかなか気持ちよかったです

バスケット:

Amazonでバスケットボールを購入し、4年ぶりにバスケを再開。駒沢公園のバスケットコートまで自宅から徒歩10分ほどなので、夕方から高校生に混じってプレイしたり、夜中にシュート練習に行ったりする日々です。スリーポイントが届かなくなっててワロタ

アタマを鍛える

React + Redux + Next.js +TypeScript:

転職候補の会社がどこもReactの会社ばかりだったので、Reactの最新情報へのキャッチアップとReduxの勉強をガッツリとしました。はじめてTSと組み合わせて見ましたがJSXで型の補完がゴリゴリ効いて気持ちよかったです。

Saga含めて様々な実装パターンを調査 & 研究できたので、後述のArchitectureの話を理解するヒントになったかなと思います。

Flutter:

まずはDartの基礎文法を学ぶところからでしたが、今まで触ってきた言語のニュアンスに近いところがありそこまでは抵抗を感じませんでした。

GitHub上でinKinoというアプリの実装例を見つけたので、こちらを写経。

Reduxの記述に冗長な部分も感じましたが、少ないコード量でこれだけのNative UIができるのかーと感動しました。

Python(Django), Scala, Kotlin:

Pythonクローラーを使ったり機械学習をしたことはありましたが、Webアプリはまだ作ったことがなかったのでDjangoに入門。認証の仕組みやORMは面白かったですが、あまりワクワクしなかった(失礼)ので途中で放棄。

KotlinとScalaについては簡単に文法を調べて環境構築をしたところでMPがゼロになり終了。本質的で無い作業で疲労する言語は僕には向いてないのかもしれません。JVM系の言語とかJavaScriptとか...

そういえばSpring Bootもちょっと触りました。

Rust:

入門レベルですがかなり好きかも。マルチスレッドプログラミング楽しい!!

チュートリアルも充実していて親切でした。

Clean Architecture

普段は仕事でJSの特定のFWばかりを触っているのですが、いろいろな技術を学ぶ中で良い意味でFWの特徴を相対的に捉えることができたのではないかと思います。

そんななかVue.js / Nuxt.js Meetup Osaka #0 に登壇する機会があったので、「オレだけの最強のFrontend Architectureを作ってやる!」と思いDDDをはじめとした様々なArchitectureの勉強を開始。

speakerdeck.com

最終的には上記のようなClean Architecutreを採用した構成に落ち着きました。

このあと前職の同僚にレビューしてもらったり、Frontend界隈の友人たちと議論するなどして、今ではもう何段階かアップグレードしています。

デザインパターンの歴史を学んだり、様々なアーキテクチャのpros/consを検証したり、自らアーキテクチャを組んだりしたことでエンジニアとしてまた一歩レベルアップできる良い経験でした。

その他

Next.jsの文脈でGraphQLやApolloを触ったり、Goでアプリケーションを作ったり(Go合宿にも参加)、DTNの勉強したりと濃密な1ヶ月でした。

転職活動 ~ 入社

前職のネームバリューもあり、比較的「強い」転職活動だった気がします。

1ヶ月の転職活動で最終的に20社ほどにオファーをいただくことができ、うち半分ほどは経営陣の方と直接お話しをさせていただきました。

改めて自分のキャリアや人生を賭して叶えたい夢について向き合う良い機会だったので本当にギリギリまで悩みました。人生でこんなに悩んだことないんじゃないかなというくらいです笑

結果として創業当初から縁のあるFinTechのスタートアップに決まり、6/28からフロントエンドエンジニアとして働いています。

転職活動中に相談に乗ってくれた友人たちに心から感謝です。

予想通りハイレベルなメンバーばかりで何もできないまま1ヶ月が過ぎてしまいましたが、1日も早く会社の武器になれるよう精進します。

これからのこと

方針としては大きく2つ。

1. Frontendのエキスパートを目指す

巷ではUIフレームワークに関する論争ばかりが目につきますが、Frontendの本質的な部分(Architecture, CI/CD, Testing, Accessibility, etc...)にフォーカスしていきたいです。

幸い今の職場でも経験方法なメンバーに囲まれているため、どこでも胸を張ってFrontend Developerを名乗れるようにスキルを盗み、磨いていきます。

2. 「広く浅く」

何かの分野でそこそこのレベルは目指せても、業界トップレベルのスキルを身につけるには途方も無い努力が必要です。そしてエンジニアリング以外にも情熱を注ぎたいぼくがそのレベルにたどり着ける可能性はとんでもなく低いでしょう。

なので合わせ技で攻めます。

具体的にはバックエンド領域、とくにSRE分野の領域を学んでいきます。

いまはまだ現場で一番下っ端のエンジニアですが、数年後にもう何段階か上のポジションからビジネスに関する意思決定ができるようになるはず(予定)です。その時にバリューを発揮できるための投資を今から開始したいなと思います。

また無職期間にも改めて実感しましたが、様々な技術を学んでそのそれぞれを相対的に評価していく手法は、今扱っている技術のレベルを大きく高めてくれます。

繰り返しにはなりますが変化の激しい業界だからこそ、ビジネスに必要な道具(技術)の本質的な価値を評価できるように視野を広く保ちたいです。

ということで絶賛サイドプロジェクトで実践中です。

Vue.js + Node.js + TS + Go + Firestore + k8sというかなりエキサイティングな構成で開発しています。年末くらいにはカタチにして世に出したいな。

まとめ

  • 会社選びは悩みすぎるくらいがちょうど良い
  • 短期間でも意外といろいろ勉強できる
  • 持ち玉の数は正義

言語やFWに関係なくアーキテクチャ話に付き合ってくれる人、ご飯行きましょう

【翻訳】Sunsetting React Native

はじめに

この記事は2018年6月20日Airbnb社のGabriel Pealによって公開された記事を日本語に翻訳したものです。

公開にあたっては氏本人の同意を確認中ですが、誤訳や問題のある表現等を見つけた方は僕のTwitterアカウントまでDMいただけますと幸いです。

元記事:

medium.com

本文

この記事はAirbnb社におけるReact Native体験と 次の時代のモバイルアプリケーション開発について記したブログシリーズの第四弾です。

これまで多くのチームがReact Nativeを信頼して今後も利用し続ける計画を立てていましたが、結論としてReact Nativeが私たちのゴールを達成することはできませんでした。継続してReact Nativeに投資を続けるための数多くの技術的な問題組織構造の問題に対して、私たちは解決策を見出せなかったのです。

この経験を活かして前に進むため、AirbnbではReact Nativeから漸次的に退いて全ての力をネイティブに再投資します。

目標達成の失敗

より早く動くこと

React Nativeが期待通りのパフォーマンスを発揮していた頃、エンジニアたちはかつてないスピードで開発を進めることができました。しかしこの一連の記事で触れている技術的な問題組織構造の問題によってフラストレーションが蓄積され、予見できなかった様々な遅延が多くのプロジェクトにおいて発生しました。

品質を保つこと

React Native自体の成熟度が上がったことや、私たちの中でより多くの知見が蓄積されたことなどで、近頃はかつて実現可能性すら分からなかった多くのことが可能になりました。Shared Element TransitionsやParallaxを作ったり、フレームレートの低下が頻繁に起きていた画面のパフォーマンスを劇的に向上させたりといったことです。しかしながら初期化処理や非同期なファーストビューの描画に関するものなどの様々な技術的チャレンジによって叶わなかったものがあるのも事実です。社の内外におけるリソースの不足により、これらの問題は一層難しくなりました。

Write Code Once Instead of Twice

私たちのアプリにおいてはReact Nativeの大部分が複数のプラットフォームで共有されているものの、そもそもReact Nativeが使われているのはアプリ全体のわずかな部分でしかありません。更に、プロダクトエンジニアの生産性を担保するためには大量のbridgingが必要になります。その結果として私たちは(2つではなく)3つ全てのプラットフォームに対する統合的な補助コードを作ることになりました。私たちはWebとネイティブにおけるコードシェアリングの可能性を信じ、実際にいくつかのNPMパッケージを共有することができましたが、それを除けば本当に意味のある"Write Code Once Instead of Twice"は実現しませんでした。

撤退計画

上記のようにReact Nativeは私たちが定めたゴールを達成することができなかったため、私たちに適した道具ではないということを結論づけました。目下、複数のチームと力を合わせて最適な移行プランを計画中です。既にReact Nativeを利用した全ての機能開発は取りやめ、高いトラフィックを持つ画面については年内を目標に大部分をネイティブに置き換え予定です。これらは必ずしもReact Nativeのみに責任があるわけではなく、予てより予定されていたスケジュール変更の影響もあります。私たちのネイティブインフラチームも2018年中はReact Nativeのサポートを行う予定です。2019年からは徐々にサポートを減少させ、起動時のランタイム初期化等のReact Nativeがオーバーヘッドする部分も削減してく予定です。

Airbnb社は、オープンソースの力と意義を信じています。私たちは積極的にOSSを利用するだけでなく、世界中の多くのプロジェクトにコントリビュートしており、React Nativeに関するものも公開してきました。社全体として徐々にReact Nativeから離れていくなかでReact Nativeレポジトリに対して十分なメンテナンスが行えなくなってしまいますが、コミュニティにとってのベストを考えていくつかのプロジェクトをReact Native Communityに移譲します。既にreact-native-mapsについては取り組みが始まっており、native-navigationlottie-react-nativeについても対応予定です。

そんなに悪くなかったよ?

私たちのゴールを達成することこそ叶いませんでしたが、React Nativeに触れていたエンジニア達は概ね肯定的な意見です。内訳をみると、

  • 60%が「素晴らしい開発経験だった」と感じた
  • 20%がやや肯定的
  • 15%がやや否定的
  • 5%が強く否定

となっています。また63%のエンジニアがまたチャンスがあればReact Nativeを選択すると答え、74%が新しいプロジェクトにおいて選択肢に含めると答えました。注目すべき点は、これらの調査対象が全て一度はReact Nativeを使っていたエンジニアであるということです。

彼らは80,000行ものプロダクトコードを産み出し、220もの画面を作り、40,000行ものJavaScriptのインフラストラクチャを書いたエンジニアです。参考のために触れておくと、私たちはネイティブにおいてはこの10倍ものコードと4倍もの数の画面をそれぞれのプラットフォームで開発しています。

React Nativeは成熟してきている

この一連のポストは今日の時点における私たちのReact Native体験を振り返るものです。ですがFacebookやReact Native CommunityのメンバーはRNがハイブリッドアプリでもスケールするよう身を砕いています。かつてないスピードでReact Nativeは発展しているのです。昨年には2,500ものコミットが反映され、Facebook自身も私たちが直面したような問題を真摯に受け止めています。私たちがこれ以上React Nativeに投資することはありませんが、これからの開発を見守れることを楽しみにしています。なぜならReact Nativeの成功は私たちのプロダクトを使ってくれる世界中の人々の幸せにつながるのですから。

学び

私たちは急速に発展を続けるアプリケーションにReact Nativeを組み込みました。その中で直面した問題の多くは、私たちがハイブリッドモデルのアプローチを選択したことに由来します。しかし小さな会社では十分なリソースが無く、このスケールの会社だったからこそ得られたことや解決した問題もあるでしょう。React Nativeをネイティブとシームレスに統合することは可能です。ですが難しいことです。React Nativeを使う全ての会社が、そのチームの構成や、既存のアプリや、プロダクトの要求や、React Nativeの成熟度によってユニークな経験をするのだろうと思います。

全てのピースがはまった時(そういう場面はたくさんありました)、React Nativeは開発のイテレーションスピードや品質、そして開発体験全体において私たちの期待通りもしくは期待以上のパフォーマンスを発揮してくれました。そういう時には、私たちはモバイル開発自体を変革させる瀬戸際に立っているのだというような気持ちになりました。もちろんそのような素晴らしい体験も是非していただきたいですが、改めてその恩恵と痛み、そして今の優先事項やエンジニアリング組織のリソースを比較したとき、それは私たちにふさわしいものではないと結論づけました。

新たなプラットフォームの採用はとても大きな決断で、あなたのチームが抱える様々なユニークなファクターによって決まります。私たちが経験したことやReact Nativeを手放すことになった理由は、あなたのチームには当てはまらないかもしれません。実際にたくさんの会社がReact Nativeによる素晴らしい体験を継続しており、多くの人々にとってはいまだにベストなツールかもしれません。

私たちはこれまでもネイティブに投資をし続けていましたが、React Nativeから離れることでかつてないほどのリソースをより良いアプリを作ることに投下できます。次の記事で私たちの新たなネイティブに関する取り組みを知ってください!

その他の記事

  • Part 1: React Native at Airbnb
  • Part 2: The Technology
  • Part 3: Building a Cross-Platform Mobile Team
  • Part 4: Making a Decision on React Native(本記事)
  • Part 5(未完了): What’s Next for Mobile

【翻訳】React Native at Airbnb: The Technology

はじめに

この記事は2018年6月20日Airbnb社のGabriel Pealによって公開された記事を日本語に翻訳したものです。

公開にあたっては氏本人の同意を確認中ですが、誤訳や問題のある表現等を見つけた方は僕のTwitterアカウントまでDMいただけますと幸いです。

元記事:

medium.com

本文

この記事はAirbnb社におけるReact Native体験と 次の時代のモバイルアプリケーション開発について記したブログシリーズの第二弾です。

React NativeはAndroid, iOS, Webで横断的に動作する、それ自体が比較的新しく急速に発展しているクロスプラットフォームフレームワークです。2年間に渡って使ってきた今、React Nativeは多くの点において革新的なツールであると自信を持って言えます。それはモバイル開発におけるパラダイムシフトであり、私たちはReact Nativeが掲げるゴールから多くの恩恵を受けることができました。しかしその利点を得るために多くの痛みが伴ったことは無視できません。

上手くいったこと

クロスプラットフォーム

React Nativeを利用することによる一番の利点は一度書いたコードがAndroidでもiOSでも動作するということです。React Nativeで実装した機能の多くでは95-100%のコードを共有することができ、 プラットフォームに依存したファイル(*.android.js/*.ios.js)は0.2%にすぎませんでした。

共通のデザイン言語システム(DLS)

私たちはDLSと呼ばれるクロスプラットフォームデザイン言語を開発しており、AndroidiOS、React Native、Web、それぞれのバージョンがコンポーネントごとに存在しています。クロスプラットフォームに開発を進める上で、一貫したデザイン、コンポーネント名、そして画面を定義できる共通のデザイン言語を持つことは当然の帰結でした。

しかし同時に必要に応じてプラットフォーム固有のデザインを適用することもまた可能でした。例えばAndroidにおいてToolbarを利用するがiOSではUINavigationBarを使う、Andoroidではプラットフォームのデザインガイドラインに適さないdisclosure indicatorsを隠すなどといったことです。

私たちはネイティブのコンポーネントをラップするのではなく、React Nativeでコンポーネントを書き直す方法を選択しました。なぜならその方が個別にプラットフォーム固有のAPIを叩く上で信頼性が高く、React Native上での変更をテストする手段に詳しくないネイティブエンジニアのメンテナンスにおけるオーバーヘッドを削減できるからです。ただしこのアプローチはネイティブとReact Native間でのバージョンの乖離を引き起こすこととなりました。

React

Reactが最も愛されるWebフレームワークと呼ばれるのには理由があります。シンプルかつ強力で、より大きなコードベースへスケールしやすいからです。特に私たちが気に入っている点としては、

  • Components: 適切に定義されたpropsとstateによってReact Componentは開発における関心の分離を実現します。これはReactのスケーラビリティにおける大きな要因です。
  • 簡潔なライフサイクル: Androidと(多少はマシですが)iOSのライフサイクルは非常に複雑なことで知られています。適切に動作するリアクティブなReact Componentはこの問題を根本的に解決するため、React Nativeの学習をAndroidiOSのそれと比べて非常に容易にしています。
  • 宣言的: Declarative(宣言的)であるというReactの特徴は、内部のStateとUIの整合性を保つ上でとても役に立ちます。

検証スピード

React Nativeを利用することでアプリケーションの変更を即座に確認できるhot reloadingを活用することができます。ビルド時のパフォーマンスこそネイティブアプリに軍配が上がりますが、開発・検証スピードにおいてはReact Nativeの足下にも及びません。最速で15秒もあればネイティブアプリをコンパイルすることはできますが、長い時にはビルドに20分ほどかかることもあります。

インフラへの投資

私たちはネイティブのインフラに対して広い範囲でのIntegrationを実現しました。'networking', 'i18n', 'experimentation', 'shared element transitions', 'device info', 'account info'というコア機能をはじめとした多くの機能が個別のReact Native APIとしてラップされました。既にあるAndroidiOSAPIをReactのために整合性を持たせたり正規化する必要があったため、それらのBrdigeはとても複雑なパーツとなりました。高速な開発サイクルの中でこれらのBridgeを常に最新の状態に保つ作業が必要になりましたが、インフラチームがこの部分に投資してくれたことによってプロダクト開発がずっと容易になりました。

このインフラ部分への大きな投資がなければ、React Nativeによる開発はもっと中途半端なものなっていたでしょう。React Nativeを既存のアプリにつっこむためには、このような投資が必要不可欠だろうというのが私たちの結論です。

パフォーマンス

React Nativeにまつわる最も大きな心配事の一つがパフォーマンスの問題です。ですが実際はほとんど問題になることはなく、React Nativeで実装した多くの画面がネイティブと遜色なく動作しました。パフォーマンスというものは一面的に捉えられがちです。ネイティブエンジニアがJSに対して「JAVAより遅い」と考えているのをよく見かけますが、ビジネスロジックlayoutをメインスレッドから分割することで描画のパフォーマンスが向上することは多々あります。

パフォーマンスの問題が発生することもありましたが、大抵は過度な描画によるものでshouldComponentUpdateremoveClippedSubviewsを活用したりReduxの使い方を改善することで和らげることができました。

しかしながら初期化処理と最初の描画時間に関するパフォーマンスは低くReact Nativeで作った起動画面やディープリンク、画面回遊時のTTIなどに大きな影響を与えました。それに加えてYogaがReact Native coponentをネイティブのviewに変換するため、スクリーンフレームの低下時にデバッグするのが難しいという問題もありました。

Redux

StateとUIの整合性を保ちやすい、画面をまたいだデータの共有が簡単に行える等の有用性から私たちはReduxを採用しました。ですがReduxは悪名高いboilerplateで知られ、学習の難易度も高いです。一般的なテンプレートを生成するジェネレータも用意しましたが、ReduxはReact Nativeで開発する上で最も難しい部分であり混乱を招きやすい部分であることに変わりはありませんでした。React Nativeに限った問題ではありませんが。

ネイティブの支え

React Nativeの中で起きる全てのことはネイティブのコードにBridgeできるため、開発を初めた時点では予期しなかった多くのことが可能になりました。

  1. Shared element transitions: 私たちはAndroidiOSのネイティブコードと連携した <SharedElement>コンポーネントを開発しました。これはネイティブとReact Nativeのスクリーン間でも利用できます。
  2. Lottie: AndroidiOS向けのライブラリをラップすることでLottieをReact Native上で動かすことが可能になりました。
  3. ネットワーク機構: React Nativeは既にあるネイティブの通信スタックとキャッシュ機構を利用します。
  4. その他のコアインフラ: Networkingだけでなく、'i18n'や'experimentation'のようなその他のネイティブインフラもラップすることでReact Nativeからシームレスに利用できます。

静的解析

AirbnbはWebでのeslintの利用について確固とした実績を持っていますが、prettierを導入したのは私たちのプラットフォームが社内では初めてでした。prettierはPull Requestにおける細かな指摘やミスを軽減するのにとても有効で、Webインフラチームでは活発に試されています。

また描画にかかる時間とコストを解析することで、改修の優先度が高い画面を調べています。

React NativeはWebと似ているだけでなくそのさらに先を行くプラットフォームであるため、新しいアイディアを試すのに持ってこいです。React Nativeのために開発した多くのツールやアイディアが今ではWebにも持ち込まれています。

アニメーション

React Nativeのアニメーションライブラリのおかげで効果的なアニメーションを実装可能になり、スクローリングやパララックスなどインタラクションドリブンなアニメーションも手に入れました。

オープンソース

React NativeではReactとJavaScriptという巨人の肩に乗ることで、redux,reselect, jestといった膨大な数のJSプロジェクトの恩恵を受けることができます。

Flexbox

C言語で書かれたクロスプラットフォームなライブラリでありFlexbox APIによるレイアウト計算を行うYogaをReact Nativeでは利用しています。はじめこそアスペクト比が使えないなどYogaの機能的制限に悩まされましたが、その後のアップデートで解決されました。flebox froggyのような楽しいチュートリアルもオンボーディングで活躍しています。

Webとのコラボレーション

開発が進むにつれて最近ではWeb, iOS, Androidの開発を一度に行えるようになりました。WebでもReduxが使われていることからWebとネイティブで広範囲に渡るコードを、特別な調整なしで共有できることに気が付いたのです。

上手くいかなかったこと

React Nativeの未熟さ故の問題

新しく、野心的で、急速に発展してはいますがReact NativeはAndroidiOSに比べてまだまだ未成熟なプラットフォームです。多くの状況でReact Nativeは上手く機能する一方、その未熟さ故に些細な問題を解決するのがとても難しくなってしまうことがあります。残念ながらこれらのケースは予測が難しく、ワークアラウンドを行うのに数時間で終わることもあれば何日もかかることもあります。

Forked React Nativeのメンテナンス

React Nativeは未成熟であるため場合によってはソースコードに修正を加える必要があります。すぐに修正を反映するためにはReact Native本体にコントリビュートするのみでなく、Forkした独自のレポジトリを用意して管理する必要がありました。この2年間でReact Nativeに対して約50個ほどコミットを積みましたが、これによってReact Nativeのアップデートが恐ろしく大変なものとなったのです。

JavaScriptツール

JavaScriptは動的型付けの言語です。型安全でない言語を扱うことはスケールが難しいだけでなく、型のある世界からやってきたネイティブエンジニアとの争いの元となりました。彼らは型の問題がなければよりReact Nativeの学習に興味を示してくれたでしょう。

私たちはflowの導入を試みましたが、まるで暗号のようなエラーメッセージに開発者のフラストレーションはたまる一方でした。TypeScriptも調査はしましたが、既にあるbabelmetro bundlerとの統合に問題があります。そのような状況ではありますが、今後も私たちはTypeScriptの調査を継続していくつもりです。

リファクタリング

JavaScriptという型のない言語を扱った結果、リファクタリングがとても大変な作業になり多くのエラーが吐かれることとなりました。props名の変更、特に複数のコンポーネントにまたがって継承される onClickのような広く使われるpropsを正確に変更する作業はまるで悪夢のようでした。更に悪いことにコンパイルは通るのにプロダクション環境で壊れるリファクタ、静的解析を適用するのが難しいリファクタなどもありました。

JavaScriptCoreの不安定性

React Nativeのトリッキーな特徴としては、それがJavaScriptCore environmentで実行されるということです。それによって以下のような問題に直面しました。

  • iOSは初期状態で独自のJavaScriptCoreを持っているため動作も概ね安定しており、大きな問題はありませんでした。
  • Androidは自前のJavaScriptCoreを持たないため、React Nativeが自身のものをバンドルすることで実行環境が作られます。問題なのはこのランタイムがとてつもなく古いものであるということです。結果的に私たちは新たに自前で新しいJSCをバンドルしてやる必要がありました。
  • React Nativeはデバッグ時にパワフルなChrome Developer Toolsに接続します。素晴らしい!ですがデバッグモードに入ると同時に、React NativeのコードはChromeのV8エンジンで実行されるようになります。99.9%のケースでは特に問題はないのですが、ただ一度だけ、 toLocaleStringメソッドがAndroidではデバッグモードでしか動かないという問題に引っかかりました(iOSは大丈夫でした)。どうやらAndroidJavaScriptCoreにメソッドが含まれておらず、そこでエラーも吐かずに落ちていたようです。当然デバッグ時に利用するV8環境では動作していました。このような問題に対処できる深い技術的知識がなければ、何日も現場のエンジニア達は悩まされることになるでしょう。

React Native向けのオープンソースライブラリ

任意のプラットフォームについて学び、習熟するのには長い時間がかかります。多くの人は1つまたは2つのプラットフォームについてのみしか理解してないと言えるでしょう。mapやvideoといったネイティブとのbrdigeを持ったReact Nativeライブラリを開発するには3つ全てのプラットフォーム知識が求められます。残念ながら多くのReact Native向けオープンソースライブラリの開発者は十分な数のプラットフォーム知識を有しているとは言えないでしょう。それはAndroidiOSどちらかのプラットフォーム上では動作が不安定になることを意味します。

Android向けの多くのReact Nativeライブラリではパッケージの読み込みにmavenではなくnode modulesの相対パスによる記述を要求しますが、これはコミュニティの期待する品質に比べて安定性が低いやりかたです。

インフラの二重管理と機能開発

私たちは長年に渡ってAndroidiOSにおけるネイティブのインフラストラクチャを構築・蓄積してきましたが、React Nativeに向けて全ての既存のインフラに対するBridgeをゼロから作成する必要がありました。つまりエンジニアが新しい機能を開発する際に、よく理解していないプラットフォームに対しても自らの手でBridgeを用意するか、誰かがそれを作ってくれるまで待つ必要があったのです。

クラッシュレポート

私たちはネイティブランタイムでのクラッシュレポートにBugsnagを利用しています。AndroidiOSのどちらのプラットフォームでも大抵は動作する一方で、あまり信憑性は高いとは言えず特定にプラットフォームに向けたオプティマイゼーションも必要でした。React Nativeは新興であるが故に、私たち自身の手でsource mapアップロードのようなインフラを大量に作成したり、BugsnagがReact Nativeで起きた問題のみをトラックできるようなフィルタリング機能を追加する必要がありました。

このように多くのインフラレベルの機能をReact Nativeに実装しなければいけない状況下であるため、クラッシュしたのにレポートが送信されない、source mapが適切にアップロードされないといった問題に悩まされることになりました。

もう一つ付け加えると、ネイティブとReact Native間でスタックトレースは別れてしまうため、双方を跨いだ問題のデバッグはとても大変なものになるでしょう。

ネイティブブリッジ

React Nativeにはネイティブと通信するためのbridge APIがあります。このAPIは期待どうりの動作をしてくれるものの、実装するのがものすごく面倒です。まず初めに3つのプラットフォーム向けのそれぞれの開発環境を適切に設定する必要があります。JavaScriptから返ってくるデータ型が予測不可能という問題もあります。例えばinteger型はしばしばstring型にラップされてしまい、bridgeを通ってみるまでどうなるのか分かりません。またAndroidではクラッシュするのにiOSではフィードバックもなく落ちることがあります。私たちは2017年の終わりにかけてTypeScriptの型定義ファイルからbridgeコードを自動生成する方法に取り組みましたが、その時にはもう遅すぎました。

初期化の時間

React Nativeがファーストビューを描画するには、まずその前にランタイムを初期化する必要があります。残念ながら私たちほどの規模になると、たとえそれがハイエンドデバイスであっても数秒かかってしまいます。このような問題があるなかでReact Nativeをアプリの起動画面に採用することはほぼ不可能です。私たちはアプリの起動時にReact Nativeの初期化を行うことでファーストビューの描画にかかる時間を最小化しました。

ファーストビューの描画時間

ネイティブの場合とは異なりReact Nativeでファーストビューに必要な情報をあつめて描画するためには、メインスレッド -> JS -> yogaレイアウトスレッド -> メインスレッドというサイクルを実行する必要があります。ファーストビューを描画するまでの平均時間はiOSで280ms、Androidで440msでした。AndroidではpostponeEnterTransition APIを利用しています。通常はshared element transitionにおいて描画までのディレイを適用するために使われるものです。iOSにおいてはNavBarの設定にReact Nativeだと時間がかかりすぎるという問題がありました。最終的に私たちはnavbarの設定が読み込まれるまではインタラクションが発生しないよう、全てのReact Nativeでのページ遷移に50msのディレイをかけることにしました。

App Size

React Nativeによるアプリケーションサイズへの影響も無視できません。Androidの場合、React Nativeのトータルのサイズ(Java + JS + Yoga含むネイティブライブラリ + JavaScript Runtime)はABIごとに8MBとなりました。x86とarm(32bit only)を含めたAPKなら12MBほどになるでしょう。

64bit

この問題により、今の所はまだAndroidに向けて64bitのAPKを配信できていません。

ジェスチャー

タッチコントロールに関するサブシステムはAndroidiOS間での違いが大きすぎることもあり、それらを統合するAPIを開発することはReact Nativeコミュニティ全体にとって大きな課題です。そのようなこともあり現在Airbnbでは、複雑なジェスチャーを要求する画面ではReact Nativeは利用していません。しかしながらreact-native-gesture-handlerのv1.0が最近リリースされるなど、まだ取り組みは活発なようです。。

リスト表示

FlatListのようなライブラリが登場したことでReact Nativeでもこの分野が発展してきているようです。ですがそれはまだAndroidRecyclerViewiOSUICollectionViewには到底及びません。スレッドの機構により多くの制限がなかなか解決されないでいます。Adapterの持つデータには同期的なアクセスされないため、高速にスクロールしていても非同期でViewを描画することも可能なはずです。テキストもiOSでは非同期で取得されるため、事前にCellの高さを計算することが難しいです。

(* 訳注: あまり意味が理解できておらず申し訳ないです。)

React Nativeのアップグレード

React Nativeにおけるほとんどのアップグレード作業は難しくありませんが、とても大変なケースがいくつかありました。具体的な例を挙げるとReact Native 0.43(2017年4月リリース)からReact Native 0.49(2017年10月リリース)へのアップグレード作業では、前者がReact 16のα版、後者がβ版を利用していた関係でほぼ不可能とも思える作業になりました。多くのReactライブラリがWebを想定して設計されているため、最新版のReactへの対応がなされておらず手こずることとなりました。2017年中頃のインフラチームはこの依存解決の問題に追われ、結果的に大くのコストが費やされたこととなります。

アクセシビリティ

2017年に私たちはアクセシビリティに関する大幅な改修を行い、ハンディキャップを抱えた人たちが最適なリスティングを見つけ、予約できるように努力しました。しかしながらReact NativeのアクセシビリティAPIにはいくつもの穴があります。最低限のアクセシビリティ要件を満たすためだけでも、私たちはForkしたReact Nativeをメンテナンスして修正をマージする必要がありました。AndroidiOSならば1行加えるだけですむような修正でも、React Nativeでの実装方法を考え、変更を加え、React Native Coreに修正を出してケアするのには膨大な時間がかかりました。

やっかいなクラッシュ

私たちはいくつかの修正が難しい奇妙な問題にもぶつかりました。例をあげるとこちらの@ReactPropに関する問題を現在も調査中で、同じ端末同じソフトウェア上であっても問題を再現・究明できずにいます。

Androidでのプロセスの永続化

Androidは頻繁にバックグラウンドプロセスをリフレッシュしますが、その対策としてアプリケーションバンドルにstateを同期的に保存することが可能です。しかしながらReact Nativeにおいては全てのstateに対してJSからしかアクセスできないため、この同期的な保存を利用することができません。もしできたとしてもReduxにはシリアライズ可能なデータと不可能なデータが混在していますし、savedInstanceStateの容量では足りない大きさのデータも含まれるため、どちらにせよプロダクションでクラッシュしてしまいます。

その他の記事

  • Part 1: React Native at Airbnb
  • Part 2: The Technology(本記事)
  • Part 3: Building a Cross-Platform Mobile Team
  • Part 4: Making a Decision on React Native
  • Part 5(未完了): What’s Next for Mobile

【翻訳】React Native at Airbnb

はじめに

この記事は2018年6月20日Airbnb社のGabriel Pealによって公開された記事を日本語に翻訳したものです。

公開にあたっては氏本人の同意を得ている最中ですが、誤訳や問題のある表現等を見つけた方は僕のTwitterアカウントまでDMいただけますと幸いです。

元記事:

medium.com

本文

この記事はAirbnb社におけるReact Native体験と 次の時代のモバイルアプリケーション開発について記したブログシリーズの第一弾です。

10年前にAirbnbが立ち上がった頃、スマートフォンはまだまだ未熟なものでした。それから時が経ってより多くの人々が世界を旅するようになったこともあり、今や私たちの生活においてスマートフォンは欠かせない道具になっています。

旅行中はモバイルデバイスが数少ない、もしくは唯一の通信デバイスになるということは往往にしてあります。世界トップレベルのアプリを開発することは、何百万人という人々に新しい旅のカタチを提供する我々のようなコミュニティにとってとても重要なことなのです。

2008年に私たちが最初のゲストをRausch Street(訳注 Airbnb創業者のアパートメントがあった場所)に迎えた時から、年間のモバイルからの予約件数はゼロから何百万という数字に増加しています。私たちの提供するアプリによってホストは簡単に自分のリスティング(訳注 Airbnbに掲載している物件)を管理できるようになり、また旅行者も新しい旅のアイディアを見つけられるようになりました。

このような急速なモバイル体験の普及に伴って、Airbnbでは100名以上のモバイルエンジニアと共に新機能の開発や既存の機能の改善に取り組んでいます。

React Nativeへの投資

私たちはAirbnbを利用するホストとゲストにとってより良い体験を提供し、また我々自身の質の高い開発体験を可能にするような新しいテクノロジーを常に検証しています。2016年の私たちにとって、その答えの1つがReact Nativeでした。その頃から我々はAirbnbのビジネスにとってモバイルというものが重要な位置を占めることを理解していましたが、単純にモバイルエンジニアの数が目標の達成に対して不足していたのです。そのような状況下で我々はその代替となるような選択肢を模索し始めました。

AirbnbのWebサイトは主要部分がReactで作られています。AirbnbにおいてReactは高いパフォーマンスを発揮し、誰からも好かれていました。そこでReact Nativeを採用することでクロスプラットフォームで高速でコードを配信できるだけでなく、より多くのエンジニアがモバイル開発に取り組む機会になると思ったのです。

React Nativeに対して投資を始めた時点で、私たちはリスクがあることを知っていました。コード資産を統一する可能性もあればバラバラにしてしまう可能性もある新興のプラットフォームを導入しようとしていたのですから。React Nativeに投資すると同時に、正しい使い方をしたいと私たちは思っていました。React Nativeを導入する上で私たちが掲げたゴールは以下の通りです。

  1. 組織全体の動きを加速する
  2. ネイティブと同等の品質を保つ
  3. モバイル向けのコードは1度しか書かない。2度は書かない
  4. 開発体験を向上させる

私たちの経験したこと

この2年間、実験的に始まった取り組みはより本格的なものになってきています。 'shared element transitions', 'parallax', 'geofencing'といった複雑なネイティブの機構だけでなく、 'networking', 'experimentation', 'internalization'といったネイティブが提供するインフラへのbridgeを可能にする強力なintegrationを私たちは開発しました。

私たちはこれまでに数多くのAirbnbにとって重要な役割を果たすプロダクトをReact Nativeでローンチしています。ExperiencesというAirbnbにとって全く新しいビジネスだけでなく、レビューからギフトカードに至るまで何十もの機能がReact Nativeによって実現しました。これらの多くはまだ私たちが十分な数のネイティブエンジニアを有していない時代に開発されたものです。

それぞれのチームごとにReact Nativeを通して体験したことは異なります。技術的な問題や組織的な問題は残っているものの、現時点でReact Nativeは素晴らしいツールだと言えるでしょう。このシリーズではより詳しくReact Nativeの開発中に体験したことや、私たちのこれからの取り組みについて紹介します。

パート2では技術的な側面からReact Nativeにおいて上手くいったこと、そうでなかったことを挙げています。

パート3ではクロスプラットフォームなモバイルアプリを開発する上で直面した組織的な問題について紹介します。

パート4では今日におけるAirbnbとReact Nativeの関わり方と今後について触れています。

パート5(未完了)ではReact Nativeで開発する中で学んだことがどのようにネイティブで活きるかを書いています。

修行編 - 12日目

進捗ほぼありません。

やったこと

1. Rustフレームワークの調査 & お勉強

Ironが最初に手をつけるものとしては一番良さそうですね。情報もたくさん転がってるし。

2. Chrome Extensions入門

なぜかちょっとしたChrome拡張が作りたくなってドキュメント読んだり manifest.json書いてました。

画像用意するのが面倒で中断してしまいましたが思ったより手軽にDOM制御も出来て良いですね。

3. 会食

以前一緒にNuxt Meetupも主催した某社のエンジニアさん達とランチへ。

「社長がエンジニアの論理理解してるのすごい」「Nuxt使ってる会社で知名度No.1目指してるやつ、もう達成してるのでは?」

みたいな話をしてました。業界のドメイン知識は全然ないので恐縮ですが、チームとしてとても魅力的だなーと勝手に前から思ってます。

今度Tシャツもらいに行きたいです!

4. 青山探訪

用事があったため初めて青山学院大学にお邪魔して、ついでにその周辺を散策してきました。

渋谷から徒歩15分くらいなので歩くにはちょうど良いですね。

青学のキャンパスからはどこか同志社感を感じました。

factory.cr

青山ブックセンターで本を買ってから立ち寄ったのがこちらのfactoryさん。電源とWi-FIが完備されているのに加えてフカフカのソファーが作業スペースに最高でした。

残念ながら今月で閉店してしまうようなので、もう少し早く出会いたかったです。

5. 居酒屋ひとり飯

うちのシェアハウス御用達の駒沢魚庵 直で晩御飯のソロプレイをしました。

tabelog.com

お一人様も歓迎してくれる雰囲気だったのでとても入りやすかったです。

オススメはなんと言っても大将の寿司盛り!ネタのセンスも質も良く、近所でこの味が楽しめるのかーと嬉しい気持ちになります。

調子に乗っていろいろ頼んでいたら6k円くらいになったので、あまりハマりすぎないように注意。

6. Ninteno Direct at E3

MS、Sonyと来て本日は任天堂のプレゼンテーションでした。

www.nintendo.co.jp

深夜1時からライブ配信を視聴。内容てんこ盛りで脳みその処理が追いつきません。

特に印象に残ったものは以下。

スマブラやばいですね。昨日冗談で「オレ、アイスクライマー使うからwww」という話をしていたら本当に登場してビビりました。

ビッグブルーで8人対戦するのが楽しみで仕方ないです

明日やること

  • 面談
  • 打ち合わせ
  • Rustアプリケーションの立ち上げ
  • 明後日の準備

論文読んだり頑張ります。それでは良い水曜日を!

修行編 - 11日目

やったこと

1. Rustチュートリアル

こちらのチュートリアルの4~6章に目を通しました。

シンタックスとセマンティクス

2. Apollo入門

GraphQLのクライアントであるApolloに入門しました。

www.apollographql.com

先日の@vvakame氏と@gfx氏による勉強会に参加したことなどがきっかけでサーバーサイド目線でのGraphQLは少し調べていましたが、おそらく自分が実装に関わるであろうクライアントサイドについてはまだノータッチでした。

後述の面談の際にRedux Storeの代替としてのApolloの可能性について伺う機会があったため、面白そうだなと思いドキュメントに目を通すところから初めています。

Django -> Kotlin -> Rustと来てこのタイミングでGraphQLに目移りするのは流石にマズいのでもう少しだけRustメインで進めます。

勉強しなきゃいけないことがありすぎて焦るんだよなー

3. Rustプロジェクトのスケジューリング

Todoistで管理しています。ラベリング機能が便利です。

4. 面接

例の会社の三次面接で、実際にフロントエンドの担当者の方と2時間ほどおしゃべりしました。

フロントエンドが弱い業界なのかと勝手に先入観を抱いていましたが良い意味で想像以上に「強い」構成だったのでビックリ。Clean Architectureで設計されているようで非常に参考になるお話でした。

先に挙げたGraphQLの件も含めてこの会社で働くことになればたくさんの未経験な領域に取り組めそうでワクワクします。

余談ですが初めてコーディングテストというもの行いました。隣の席から画面を覗かれて一挙手一投足を評価されるので死ぬほど緊張しますね笑

5. ウォーキング

一昨日、愛用していたイヤホンが壊れてしまったため新しくJaybird RUNを購入しました。

携帯性もデザインも音質も全てがバランスが良いためJaybirdの製品は4年ほど愛用しています。今回も当たりです。

amzn.asia

心配していた天気も夜には快復していつものようにランニングに出かけましたが、なんかめっちゃヒザ痛い・・・

f:id:andoshin11:20180612031529j:plain

一昨日から痛みはあったのですが今日は全く走れないレベルでした。「こりゃ炎症おこしてるなー」と思いつつも5kmほど競歩を実施。

完全に運動不足の弊害ですね。今の体重を支えられるほどヒザの状態が良くなかったようです。まずは体重を落とさねば・・・

明日からはしばらく走るのを控えて室内での筋トレに専念します。

明日やること

走れなくなったのは辛いですが、引き続きアタマを鍛えていきます。Rustで実際にWebアプリケーションを作っていきたいのですがどうやらフレームワークが乱立しているようですね。

github.com

簡単に調べたところIRONというやつが良さそうなのですが、もう少し調査が必要・・・

Iron - Rust web application framework

というわけで明日やること。

  • Rust Web Framework調査
  • Rustチュートリアル続き
  • Rustアプリケーションの立ち上げ
  • 会食

それではみなさん良い火曜日を!

修行編 - 10日目

やったこと

1. Gradleの勉強

MavenMakefileも全然分かっていませんが、Spring Bootに必要なようなのでGradleおよびGroovyの使い方を勉強しました。

qiita.com

主に上記の記事を参考にしましたが、また前職の同僚が書いていました。流石です・・・

テック系の技術記事におけるメル社の人間のヒット率は異常ですね笑

2. Spring Boot入門

@maeharinさんの記事を参考にSpring Bootで簡単なKotlin APIサーバーを作ろうとしました。

qiita.com

ですが無限にエラーで怒られガン萎え・・・

IDEの設定やら使い方を調べるのに膨大な時間が取られてしまい、肝心のKotlinのコードが全然書けていません。つらぽよ

3. Rust入門

Kotlin諦めてないよ!ただの気分転換だよ!!

シュッと環境構築もできるRustを触ってみました。Cargoはシンプルで使いやすいですね。

プログラミング言語Rust

こちらのチュートリアルの3章までの内容を手元で試し、型システムの基本、標準入力の扱い方、スレッドプログラミング等に触れました。

書き心地も大変良く、スマートな言語だなという印象です。明日からKotlinとどっちをやろうかなー

4. ランニング

雨につきおやすみ(罪悪感)

5. 映画鑑賞

二子玉の109シネマズでようやくDeadpool 2が観れました。久々のIMAX

www.youtube.com

やっぱ最高に面白いですね。監督が変わったので心配してましたが、相変わらずジョークがキレキレです。

トレイラーで推されていたX-Forceのメンバーがまさかあんな扱いになるとは予想もしていませんでした。そしてなによりあのポストクレジット映像。個人的にMarvel史上最高なんじゃないかと思ってます笑

終始映画館では笑いが起きていたのですが、正直なところ字幕が邪魔で仕方なかったです。本音声と字幕ではそもそもニュアンスが全然違うしオチのタイミングも違うので、字幕がなければさらに面白かったのではないかなと思います。

日本でも字幕無し上映やってるところないのかな。

6. カラオケ

こちらも久々でした。

最近の邦楽も仕入れてレパートリー増やさないとです。(危機感)

明日やること

明日からまた会食 & 面談ラッシュです。勉強はできそうですが悪天候でランニングができないのが残念。筋トレもやってカロリー消費するしかないですね。

最近夜更かしをしがちなので、徐々に生活リズムも取り戻していきたいです。

それでは良い一週間を!