iOSエンジニアが知るべきProgressive Web Apps開発のエッセンス #iOSDC 2018

f:id:laiso:20180918235716p:plain

iOSDC Japan 2018 に採択されたトーク「iOSエンジニアが知るべきProgressive Web Apps開発のエッセンス」のブログ版記事です。

CfP提出後に内容は二転三転しまして、当初は最新Web開発事情について技術的に突っ込んだ内容にしようと目論んでいたのですが、「iOSエンジニア」へ「伝えたいこと」という軸で作っているうちにこの内容に落ち着きました。

当日聞きに来てくださった方、声をかけていただいた方。このような場を下さったiOSDCスタッフの方々にはたいへん感謝しています。

Introduction📛

f:id:laiso:20180918224204p:plain

昨年末 SafariにService Workersが実装され「iOSがPWAをサポートした」というニュースが業界内で話題になりました。 (※Progressive Web Apps 以降 PWA という略称で話します)

f:id:laiso:20180918224304p:plain

この時話題になっていたSafariのPWAサポートとはすなわちService WorkersのAPIの実装を指していたようです(Service Workersについては後ほど解説します)

このニュースは憶測や曲解を呼び、時には「ネイティブアプリの時代が終わった」という強い主張になって話される場面もありましたので、みなさんもどこかで目にしたことがあるかもしれません

f:id:laiso:20180918224347p:plain

状況を整理しましょう。SafariでService Workersが使えるようになったは事実です。これは既にその時点での開発計画にありましたので規定路線でした。

そして「ホーム画面に追加」でお馴染のSafariのWeb Clipの機能がWeb Manifestファイルに対応してアイコンなどを指定できるようになりました

しかし実際のアップデートはこれだけで、間違ってもAppleの誰かが「PWAに対応しました」などの声明を出したわけではありません

f:id:laiso:20180918224649p:plain

このようにPWAを取り巻く情報の解釈は複雑です。

私が思うに業界内で刺激的な話題が先行してしまったのは、Webとネイティブアプリ開発それぞれの側面で技術をただしく評価できていなかったからではないかと感じました。

ですから先ずWebアプリとネイティブアプリの開発者の目線で、Service WorkersとPWA、iOS Safariのことを理解するのが必要だと考えています。

f:id:laiso:20180918224804p:plain

このトークの前にiOSアプリ開発をしている知り合いのエンジニアたちへ「PWAという言葉を聞いてどう思うか」と質問してみました。

そこではUIやUXのクオリティやアプリストアでのファイダビリティの懸念などの意見をいただきました。

そこで気づいたのですが、PWAと名前が付けられたことによってネイティブアプリと比較して優劣を語る人の多さでした。ここの思い込みを先ず解かないといけなさそうです

f:id:laiso:20180918224911p:plain

また現状はAndroidのChrome上での体験とSafariでの体験は全く別物であると言えます。

その為、同じPWAという言葉を使って話していても、iOSユーザーとAndroidユーザーで捉えている像がそもそも噛み合わないということが起りえました

f:id:laiso:20180918225012p:plain

「PWAがネイティブアプリを置き換える」というストーリーは本質的ではありません

まず私が主張したいのがこれです。

その根拠となる理由を今からお話していこうかと思います

f:id:laiso:20180918225055p:plain

まず私がどういう立場でお話するのかというのを明確にするために、ここで自己紹介をします

私は普段スタートアップで Webエンジニアとして 仕事をしています。

そしてスマートフォンのアプリ開発も長く手がけているので、 iOS エンジニアのみなさんと近い価値観でお話できると思います

新しい技術全般が好きで、特に GUI のアプリケーション開発環境のことをよく調べています

PWAについて本質的な部分を知る

f:id:laiso:20180918225201p:plain

PWAという言葉は、広義ではWebアプリのUXを向上するムーブメント(運動)の通称です

最初はGoogle Chrome開発者らによって提唱されました

PWAに限らずGoogleは一枚岩の組織ではありませんから、Googleのどのチームの人達が言っているのかというのに注目するのがよいと思います

f:id:laiso:20180918225300p:plain

次に各プラットフォーマーにとってPWAがどのような意味を持っているのかというのに触れたいと思います。

Googleは古くはGearsやIE拡張、DartVM、Chrome Appsなどあらゆる方向からWebをよりよくする為の改善を続けています、その延長線上にPWAがあるのは不思議ではありません。

MicrosoftもWindows向けのHTMLアプリの強化を近年進めていて、先日正式にMicrosoft StoreへのPWAの登録を可能にしました。タブレットやデスクトップ向けのアプリ開発市場を活性化させたい意図が見えます。

MozillaにとってWebであることはNativeなのでWeb技術でネイティブアプリを作るのは当然のことです(ex: Firefox OS)

f:id:laiso:20180918230051p:plain

しかしAppleさん、完全にノーポジです。

WebKitにService Workersは実装されましたが、Appleは基本的にPWA関連の戦略を発表していません。

f:id:laiso:20180918230452p:plain

余談ですがiOS SDK誕生以前、アップルはサードパーティの開発者がWebアプリとして自分のアプリを公開するような構想を持っていました

これはセキュリティ上の理由による決定だったらしいのですが、開発者らの猛反発にあい現在のネイティブSDKの提供となったわけです

f:id:laiso:20180918230559p:plain

PWAとは元々、ネイティブアプリでは実現できるがWebアプリではできない体験の溝を埋めるために、ブラウザ側に実装された新機能を使うべしという側面があります。

Service Workers は「Webページ」という層より更に低レイヤー・ネイティブに近い層として処理を記述できる仕組みが用意されています。

そのため、PWA関連機能はService Workersと組み合わせて使うという例がよく出てきます。

f:id:laiso:20180918231106p:plain

では Service Workers とは何ものでしょうか? それは「ブラウザのオフライン基盤」と捉えるのがより本質的だと思います。

「プログラミング可能なネットワークプロキシ」という表現もされています。

f:id:laiso:20180918231204p:plain

この「ローカル」というのを「アプリがインストールされる」と考えるとiOSエンジニアにも理解しやすいと思います。

実際Service Workersの登録・アップデートの管理をブラウザが透過的に行ってくれる仕組みを含んでいます。

これによってWebページによるアプリの表の面とシステム上で動く「裏の面」が表現されているのです。

f:id:laiso:20180918231504p:plain

その他のブラウザの新機能(API)の例も見ていってみましょう

f:id:laiso:20180918231608p:plain

Android端末ではこのようにManifestとService Workersが定義されたWebアプリを開くとインストールを訴求するバナーが出現し、ホーム画面に追加できるようになります

一方Safariについてですが——

「ホーム画面に追加」 と Safari

f:id:laiso:20180918231654p:plain

PWA関連の記事で、まるで最新のアップデートでWebアプリのアイコンをホーム画面に追加できるようになったかの記述を見かけます

しかし、これは「Web Clip」という機能で、iPhone 3G時代から存在しました。

f:id:laiso:20180918231813p:plain

旧来、独自メタタグをHTMLヘッダに埋め込む形式の仕様だったものがService Workers実装後にWeb Manifest(JSON形式)をサポートしました。

f:id:laiso:20180918231946p:plain

このようにホーム画面に登録したページはSafariから切り離された単独のウィンドウとして管理されます(しかしcredentialの管理など既知の問題もあります)

f:id:laiso:20180918232040p:plain

次にPush Notificationです、Safariは今のところPush APIに非対応です。

デスクトップ向けにSafari Push Notificationsという独自の仕様があり、これとiOS Safari+APNsを統合しないことにはPush APIはiOSにくる未来はおそらくないのでしょう。

f:id:laiso:20180918232323p:plain

Payment - 支払い関連のAPIも最新のSafariで利用できます。

iOS SafariでもApple Payは利用できますし、この機能はうまくWeb標準とAppleの仕様が噛み合った例としてうまく機能しています。

f:id:laiso:20180918232602p:plain

つまりPWAとは、ブラウザに実装された、新機能を使うと、従来のWebアプリに不足していたUXが実現できる。

というだけの話なんです。

もしくは、WebアプリのUX向上のために新たなルートが引かれたと解釈すると良いかもしれません

f:id:laiso:20180918232749p:plain

なのでネイティブアプリと比較して優劣を語るのではなく、すべてのブラウザ共通で動作する従来のWebアプリと比較するべきなのです

Webアプリとネイティブアプリの比較

そうしたことをふまえて、次に「Webアプリとネイティブアプリの比較」です

f:id:laiso:20180918232815p:plain

Webアプリの利点として「動作環境が多用 」ということと「柔軟な配布方法」できる。ということがあげられるかと思います

Webアプリは外部アプリのWebViewの中からでも起動できますし、ブラウザさえあればどこでも動作します(そしてホーム画面からでも)

f:id:laiso:20180918232956p:plain

Webアプリの柔軟な配布方法についてです。Webアプリは常にサーバー上の最新版を参照し、Service Workersによってイントールする単位をインクリメンタルに管理することも可能になりました。

f:id:laiso:20180918233208p:plain

ここでいうオフラインファーストとは何でしょう。 それは、データを取得しなくてもUIを構成できるということです。

具体例としてはキャッシュされたアセットやレスポンスから読み込むことができます。

f:id:laiso:20180918233340p:plain

App ShellモデルというのもChromeチームが提唱したWebアプリのアーキテクチャの名前で、ネイティブアプリのメンタルメデルに近いのでiOSエンジニアには理解しやすいかと思います。

f:id:laiso:20180918233441p:plain

しかしiOS開発でオフラインファーストを意識する場面はどの程度あるでしょうか?

ネットワークのリトライ処理やキャッシュのハンドリングなどを独自に実装されている方も多いと思います。

f:id:laiso:20180918233628p:plain

WebアプリがWebであるがゆえに根本的に抱える問題というのもあります。

OSが持つ機能との接続はAPIが存在するか次第でありますし、ネイティブに見た目を近付けるほどその違和感が出てくるジレンマなどもあります。

UI遷移などはおもたる例で、ブラウザ上のレンダリングエンジンでOS権限でグラフィックAPI叩けてハードウェアに近い最適化のできるネイティブな実装に近付けるのは指南の技でしょう。

f:id:laiso:20180918234558p:plain

一方Safariの課題としては、Windows版Safari廃止以降に進んだOS独自機能の取り込みというのがあげられます

機能によってはWeb標準への準拠の動きはコンフリクトするため、うまく統廃合する必要があるでしょう

f:id:laiso:20180918234654p:plain

またiOSではChromeやFirefoxなどのサードパーティのブラウザはWebKitの利用を強制され、システムのデフォルトにできません。

ホーム画面にショートカットを置けるのもSafariだけです。

このためAPIの実装の進んだブラウザを使うという選択をとることができません

f:id:laiso:20180918234712p:plain

これは個人的な予想と願望なのですが、Appleがなぜ今頃になってWeb標準の実装を進め出したのかというと

既に世界的にシェアがあるモバイルブラウザ向けに作られたWebアプリをiOSで動かし利用者を取り込みたいのだと思います

つまり、AppleはAppleで自社デバイスのUX向上のためにSafariを改善していくのではないか? ということです

iOSエンジニアがWebアプリ技術に注目しておいた方がいい理由

f:id:laiso:20180918234740p:plain

2014年に話題になった「ロードマップ指向とエコシステム指向」というブログ記事があります。

ここでは、大きな企業が主体となって推進する技術的なトレンドが、オープンソースのコミュニティを中心とするエコシステム=生態系が技術を進歩されるということが示されています

f:id:laiso:20180918234833p:plain

エコシステム指向とはなんでしょうか? それは技術の革新を牽引する存在がプラットフォーマーなどの大きな企業から、それぞれの意思を持つ小さなコミュニティに移り変わったことだと思います

例えば、Googleのように。モバイルOSの開発をしつつブラウザ体験をよくする、しかしそれを置き換えるような新プラットフォームも開発している。という企業はそれぞれの方向性は違うが時には統合して進化している。という点が、非常にエコシステム的であるといえます

f:id:laiso:20180918234921p:plain

ここで注目したいのは現代でエコシステムを中心に急成長してきた技術としてのWeb開発環境です

ブラウザベンダーは標準化された仕様の実装でそれぞれ競争し、サードパーティのライブラリは各分野で御互いのいいところを取り込んだり、もっと良いやり方を提案したり巨大なOSSプロジェクトを戦略的に企業が運用・参加しています

f:id:laiso:20180918234953p:plain

Web技術のコミュニティではエコシステムで進化を促進する仕組みが機能しているのです。

iOSエンジニアの皆さんに近年のWebアプリ開発技術の進化の速度がすごい! というのを本日は知っていただきたいのです。

f:id:laiso:20180918235109p:plain

なぜWeb技術の進化が早くなるのか。それは、Webに関わる人口の多さが関係しているのだと思います。

ウェブブラウザやデバイスの利用環境は多様化していますし、Webアプリのフロントエンド開発技術はJavaScriptに集約されています。

f:id:laiso:20180918235125p:plain

思い起してみると今から10年前の2008年に「iOSエンジニア」という職業は存在しませんでした。

この10年、CocoaからiOS開発の環境は目紛しく変化しました。毎年OSやIDEが一新され、アプリは壊れ、プログラミング言語すら切り替わってしまいました。

AppStoreとわたしたちデベロッパーが作り出したアプリ開発のエコシステムが「iOSエンジニア」を作りだしたわけです

それと同じようなことはWeb開発の世界では今起っています。

f:id:laiso:20180918235332p:plain

AppleのロードマップによるiOS開発環境の進化を待つだけでは、もはや劇的な進化は訪れません。

私たちデベロッパーがエコシステムを乗りこなし、iOSの開発環境を進化させるべきだと思います。

例えばServer-side Swiftなどはまだまだ未成熟なので、非常にコミットする余地のある領域だと思います

f:id:laiso:20180918235359p:plain

10年後の「iOSエンジニア」を思い浮かべてみてください。Swiftで変わらずにアプリを開発しているでしょうか? それともFlutterでDartを書いているでしょうか?

10年後もiOSプラットフォームがユーザーにとって魅力的であるように…iOSエンジニアという職業を残すには、自分たちで未来を作ることが最良の選択です

そのために最新のWebアプリ開発技術を正しく理解して評価し、iOSアプリ開発に活かすのは重要なことだと思います

f:id:laiso:20180918235454p:plain

スタートアップの技術選定とアプリケーションプラットフォーム

f:id:laiso:20180819210731j:plain photo by pexels.com *1

この記事を書いたきっかけ

niconegoto.hatenadiary.jp

「PinQulをクローズします」にて事業のふりかえりをしている文章の中に「アプリビジネスは完全にダウントレンドにある」という一節があって、ここから話題が広がっていったのを機に上記の記事を読みました。そして色々思うところがあったのです。

(Twitter上で多くの共感を集めた投稿)

例えば「モバイルアプリがWebに負けはじめた理由」ではWebアプリがモバイルアプリに比べて優れているでろうという点を分析させています。

そして僕が注目したのは以下の部分について

もっとサービスレベルの話でいくと、初めからwebでやればよかったというのもミスだったと感じている部分です。

最初にアプリで出すことにこだわりすぎてしまい、プロダクトの検証が遅くなってしまいました。ライブコマースの視聴・購入体験をよくするためにアプリでなければならないと思っていましたが実際にはwebでもほとんど遜色ないものを提供することができました。

PinQulをクローズします - niconegoto Blog

PinQul のこれまでの軌跡をみると、2017年10月にiOS版リリース。2018年04月にAndroid。5月にWeb版。という情報がありました。

つまりiOS版をリリース後に少なくとも半年はAndroid版やWeb版を開発しつつ、iOSアプリの方向性を変えPMF(プロダクト・マーケット・フィット)を探っていたことになる。 その期間を3プラットフォーム並行開発するよりWeb版一本でフォーカスしたかったな、という後悔が出てしまうのは共感できた。なぜなら我々も同じような状況で悩み、現在モバイルアプリを開発しているからです。

そんなPinQulのIF...を元に、改めてスタートアップが新規プロジェクトなモバイルアプリを今0から作りはじめるとき、技術的な観点でどの道具を選択するのか、というのを考えてみたかった。

新規プロジェクトというのは俗に言うスタートアップでなくても1企業の新規事業部が0から作り出すソフトウェア製品のことでもいいです。

2012年のビーンボール

最初にPinQulの記事を読んだ時に2012年のマーク・ザッカーバーグのインタビューから起ったネイティブ/Web論争を思い出してしまいました。

これは当時Firebug作者でありiOS向けフレームワークthree20開発者でもあるJoe Hewittを中心に開発されたネイティブ実装で評判もそこそこ良かったFacebookの公式iOSアプリを、ある時に全面的にWebベースのハイブリッドアプリに置き換えようとした所、パフォーマンス問題などが顕著になりネイティブアプリに作り替えた時のものです。

マーク・ザッカーバーグのこのきわどい発言は、その場では投資家向けの弁明も含むもので、補足もされたのですが。様々な反論や憶測を呼び、業界を騒がせることになりました。

その後FacebookはPHPの魔改造Javascript拡張からReactを生み出し、2度3度ネイティブアプリ開発への移植に挑戦した後にReact Nativeを軌道に乗せているわけで、先の弁どうりWeb技術を諦めていない。というのはガチであったことが伺えます。

www.publickey1.jp

この一件は、PinQul とFacebook のビジネスのフェーズが全く異なるにも関わらずダブって見えます。おそらく2012年時点で「Webアプリはダウントレンドで、我々はネイティブアプリにフォーカスする必要がある」という空気が業界を襲ったことへの揺り戻しを感じさせるからでしょう。

当時の時代背景を知る手段として「Webはクソ。ブラウザはマジなんとかしろ」の記事をあげます。ここでは進化の遅く足並みの揃わないWebアプリ開発プラットフォームはネイティブアプリに比べて遥かに劣っているという意見が述べられています。

blog.mirakui.com

いま、Webは重要な転換期の中にいると私は思う。Webはデスクトップアプリケーションと同等になるのに10年以上かかってるし、しかもイマイチだ。そしてネイティブアプリが加速していく中でWebは絶滅の危機に瀕している。

PosterousのCEO「Webはクソ。ブラウザはマジなんとかしろ」 - 昼メシ物語

——そして話は現代に立ち戻ります

モバイルWebファーストと貧者のツール

「貧者のツール(道具、技術)」とは、より少ないリソースしか消費できない環境で、なんとか道具を工夫して製品開発を達成するための考え方の通称で、「人ナイ物ナイ金ナイ」のスタートアップ向きであると言えます。

この貧者のツールとして、スタートアップが新規プロジェクトにモバイルWebファーストを採用する利点としては以下があげられると思います。

チームのエンジニアや開発するコードベースを最小にして高速に開発できる

通常のアプリ開発プロジェクトではWebバックエンド/iOSアプリ/Androidアプリ/フロントエンド。など技術やプラットフォームによって開発担当者をアサインすることが多いかと思います。

モバイルWebファーストにすることで、iOSアプリやAndroidアプリの開発に1-2人ぶんのリソースが取られることはなくなります。またWebアプリ開発者はバックエンド開発の片手間にフロントエンド開発も身に付けている人材が多いので、API→アプリクライアントサイドのコミュニケーションも短縮できる可能性があります。

高速に仮説検証できる

変更する対象コードが少なくデプロイも早い。担当する開発者間のコミュニケーションも省ける。となると高速にプロダクトを仮説検証できる 、というのが想像できると思います。

留意すべき点

しかしモバイルWebファーストの良い面の裏に、思わぬ落し穴が隠されているケースもあります

高速な開発を実現する為に選んだモバイルWebファーストが逆に開発の遅延を招く可能性も考慮すべきです。以下はその一例です

  • Webアプリの方が実現が難しい機能
  • デバイスに近いAPIを活用するアプリ
  • ネイティブアプリで楽に実装できるパターンがよく知られている機能

例えば「QRコード決済アプリ」。これを僕が最初に想像した時はMediaDevices系のインターフェイスでWebでもサクっと実現できそうだなー、という印象でした。

しかし現実の QRCode Scanner のデモコードを見るとC言語のライブラリをJavaScriptに変換し、バックグラウンドでカメラをオーバーレイしたcanvasから抜き出した画像データを送りつける、という過激な実装で実現されています。

またデバイスに近いAPI、OSの機能を呼び出して実装するアプリはウェブで自力実装しづらいだけでなく、実現不可能=詰み状態が訪れる危険性もあり、注意が必要です。

その機能要件はネイティブアプリのが実現しやすいのか? Webで充分に開発できそうか? というのは結局両プラットフォームに精通した視点が要ります。貧者の組織にそのような人物の助けを借りることができるか? というのは怪しかと思います。

PinQulの開発が開始されたであろう2017年の春頃にライブECの要件(明日にはガラっと変わるかもしれない!)はWebアプリで充分に満たせるはずだ! と0ベースの状態で断言できるエンジニアはいないと思います。

スタートアップはスピードが命ですから、もしそれをやるにはプロジェクトの開発が決定する前からアイデアの技術的な検証を普段から行っていないとできません。

Komercoの技術選定

Backend as a Service (BaaS)を活用してサーバーサイド開発の工数を減らし、徹底的に仮説検証して高速に新規サービスを開発するぞ! という考え方があります。

理想的なプロジェクトではバックエンド開発に携わる工数を大幅に削減でき、貧者のツール的であると言えます。

この思想でFirebaseをフル活用して作られたサービスに、クックパッド新規事業「Komerco」というアプリがあります。

jp.techcrunch.com

Komercoは2018年6月にリリースされ、現在はiOSアプリしか提供されていません。

Komerco開発チームがこのままAndroidアプリやWeb版を開発するつもりなのか、iOSだけでサービスを検証してゆくのかは注目どころです。

※ 同じ手法で開発された「Cookin'」というプロジェクトはiOSアプリだけをリリースした後に、7ヶ月でサービスが終了しました*2

螺旋の原則

「技術選定の審美眼 」という名スピーチがあります。

ソフトウェア業界の技術トレンドは、一見振り子のように同じ場所に戻ってくるように見えるが、螺旋状に変化している。螺旋を作り出す技術要素の差分と、変化の中でも変らない抽象的な考え方に注目することの重要さが説かれています。

www.publickey1.jp

この螺旋の原則でいうと。モバイルシフト、アプリファーストの後にWeb回帰というストーリーに中に以下のような差分が潜んでいるのだと思います

  • アプリがコモデティ化して、ネイティブアプリであること自体の競争力が弱くなった
  • PCのWebブラウザからモバイルのブラウザへ主戦場が移った
  • ブラウザやフロントエンド開発環境が劇的に進化した

例えばフリルやメルカリが世にリリースされたのは奇しくもFacebook HTML5ショックの2012-13年です。この時期にモバイルアプリファーストの開発に注力しているサービスは少なかったと記憶しています(そしてフリルはTitanium Mobileによるハイブリッドアプリ技術を選択し、メルカリはネイティブアプリSDK開発を選びました)。

多くのサービスは先ずデスクトップ向けサイトがケータイ対応し、それを元にスマホ対応→アプリリリース。と開発うるのが通例だったと思います。

この時期にネイティブアプリのUXを高めることにすべてを投資したプロダクトは現在も伸びています。

はたして2018年にモバイルWebファーストで開始するサービスはどうなるでしょうか、非常に気になるところです。

私たちのケース

締め括りに身の上話をさせていただくと、先日私たちもPinQulと同じような状況でネイティブアプリ開発に舵を切りました。

その時は直前までWebアプリ以外にもReact NativeやFlutterでの開発を考えて綿密にプロトタイプ開発をして準備を行っていましたが、スタートアップにありがちな「ある日状況が変わった」というやつが発生しました。

その時の意思決定の理由は以下です

  • 一番手を動かしてコミットしてくれそうな新入社員のエンジニアがネイティブアプリ開発が得意だった
  • それをサポートするエンジニア(僕)がだいたい何でも対応できた
  • AWSからGCPに切り替えることができ、Firebase(BaaS)を全面採用できた
  • 開発対象の要件がだいたい想像できた

そこから学んだことは以下です

  • 仮説検証やPMFは1プラットフォームで行った方が良い
  • 選択するプラットフォームは人的要素で決める
  • 「隣の芝生は青い」を乗り越えるにはプロトタイプを作り続けるのが重要

P.S. 現実のプロジェクトとして実際に手を動かし、そのふりかえりを共有してくださったPinQulチームと井手さんに心から感謝します

iOSDC Japan 2018 に laisoから 1名 が登壇いたします

f:id:laiso:20180808124405p:plain

iOSDC Japan 2018

iOSエンジニアが知るべきProgressive Web Apps開発のエッセンス」と題しまして、PWAムーブメント以降のWebアプリ開発のお話しをさせていただきます。

10年ビジネスとしてiPhoneアプリ開発を、個人の楽しみとしてウェブ開発とクロスプラットフォームのフレームワーク研究を嗜んできた私が現在関心を持っているのがこの最新のWebアプリ開発手法についてです。

おそらく以下のような内容になるかと存じます

「PWAとは?」でウェブ検索してキャッチできないような技術者的観点からレビューしたPWA論

マーケット、ビジネス的、組織的観点のPWA評はおそらく期待できません。ウェブに情報が溢れているので自身で見てもらった方が良いと思います。

クロスプラットフォームツールとして見たWeb開発

近年最も高速に進化しているGUI開発環境であるWebアプリのフロントエンド開発について、私見を交えiOS開発者にとって参考になるような内容にします。

抽象的で観念的なGUI開発の蘊蓄

好きなので。

複数のプラットフォームに精通するとGUI開発を多面的に捉えることができ、そこから発見できる自己理論を持ち出すことができます。

以下は本トークの雰囲気に近そうな窪塚洋介氏のインタビューです。

Google Docs でiOSアプリの画面を作る

アプリ内に設置する「利用規約」や「プライバシーポリシー」を前々から Google Docs のドキュメントを直でホストすればいいんじゃないと思っていたので実現方法を調べた。

Google Docs のドキュメントは

  • URL末尾 /edit で共同利用する状態
  • /preview で書類フォーマットの閲覧だけするURL
  • /pub でWebページとして公開する時のURL

という3つのものがあり、 /pub をアプリ内に WKWebView で直接埋め込む。

Google ドキュメント、スプレッドシート、スライド、フォームの公開と埋め込み - パソコン - ドキュメント エディタ ヘルプ

見た目が気にいらない部分はJSで書き換えてしまう(Googleの標準フッタの表示を消してしまうと怒られそうではある)

webView.evaluateJavaScript(
            ["document.getElementById('contents').style.margin='0 50px';",
             "document.getElementById('header').hidden=true;",
             "document.getElementById('footer').hidden=true;"].joined()) { result, err in
                assert(err == nil, err?.localizedDescription ?? "")
            }

様子

Drawingや他ツールと連携できるので比較的表現力の高い利用規約が作れるような気がする

まとめ

  • 作っては見たものの、アプリとウェブサイトで共有するために結局自社でホストするURL振った方がいいのかもしれない
  • 閲覧者がリビジョン履歴を見たり「現在利用規約の見ているユーザー数」などを共有して盛り上がれるといいと思ったけどパブリッシュ済みのドキュメントはその機能はなかった

Gist

gistc621a0b6ca5d3571f19ea801ded7fb8e

無法地帯にテストケースを追加する時にいつもやっている戦略

数年開発続いてるけどテスト全くないみたいなよくあるコードベースを想定。

不具合を修正する時についでにリファクタリングしてドメイン層のテストを書く。

  1. 手動テストで不具合を再現
  2. ViewからロジックをControllerへ移動し、Viewからは値の参照のみにする
  3. 移動したロジックをController内でプライベートメソッドに切り出す。返り値を(2)の値にセットする
  4. プライベートメソッドを外に出して関数→モジュール化する
  5. (4)のメソッドに対してテストを書き、失敗するのを確認する

ポイントとしては

  • 運用的観点ではなるべく早く不具合を修正してデプロイしたいので、リファクタリングだけ別のブランチでゆっくりやる
  • 依存がでか過ぎで解決できなさそうなど問題があれば、その時点ではテストを書くのを諦める。行動したことで学んだIssueを起票する

具体的なリファクタリング方法は

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

  • 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
  • 出版社/メーカー: 翔泳社
  • 発売日: 2009/07/14
  • メディア: 大型本
  • 購入: 45人 クリック: 673回
  • この商品を含むブログ (157件) を見る
とか
新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

新装版 リファクタリング―既存のコードを安全に改善する― (OBJECT TECHNOLOGY SERIES)

とか

テストケースが蓄積されるとリアーキテクチャリングにも手を出しやすい

レガシーソフトウェア改善ガイド

レガシーソフトウェア改善ガイド

けど現実ではエイヤで全部捨てるプロジェクトが多くてもったいないなーと思っていた。

バンコクへ来た🇹🇭

上京してから10年程東京で単一障害点を構成してきたのだけど、今年からバンコクで暮しはじめた。バンコクというのはタイ王国の首都の名前なんだけど「タイへ来た」という程バンコクの外のことを知らないのでもっぱらバンコクがどーだこーだと呼んでる。

仕事に関してはPAYで過した楽しい時間を終えて*1 ドリコムの海外子会社で就労ビザサポートしてもらってiOSアプリとAndroidアプリのメンテができるRailsエンジニア的な役割で働いてる。たまにタイトルがEngineering Managerになってたりするけどエンジニア俺一人しかいないので多分に正確ではないと思う。

バンコクという都市について

日本人が住みやすい海外都市の筆頭には毎回上ってるらしい。繁華街に日本語の看板をちょいちょい見かける。でも日本語が通じるかといえば通じないと思う。

街に外国人が溢れていて中国日本欧米東南アジアの人々が全部ごっちゃ混ぜな雰囲気がある。英語はそれなりに通じる。日本人の英語返せない比率から考えると、外国人として東京でローカルなサービスを受けたい場合のがハードル高そうだと思った。

物価については解釈が必要で、大きく「観光客向け」「外国人向け」「現地向け」の経済圏があって慣れてくるとどの程度のコストでどこのサービスを受けるかというのを自分でコントロールできるようになるのだと思う。

治安についてはBLACK LAGOON のモチーフがタイらしいのだけど銃撃戦も起きないし、爆発物も持ち込めないし平和な方だと思う。

たぶん日本人の頭の中には10年以上前の新興国真っ只中の時代のアジアのイメージが残っていて、観光向けの宣材には過剰にキラキラした歓楽街とか高級ホテルやバーの写真が使われてたりするけど、実際の感じはGoogleストリートビューで見てみるのがいいんじゃないかなーと思います。

個人的には東京の冬の気候(寒さや乾燥)と花粉にやられていたので快適になってよかった。空気と水の質も良い気がするけど東京が合わなさ過ぎただけなのかもしれない。

BASEについて

このままBASEにいれば好条件な待遇を受けて楽しい仲間たちと働けて会社や事業や業界も気絶しとけばどんどん成長していくし、手放すのはとても惜し過ぎたんだけど、前々から人生一度ぐらいは海外に住んでみたいもんだという思いがあってわがままを言わせてもらった所がある。

開発していたプロダクトの PAY ID もやっとモバイル版をリリースしてこれからやっていくぞ! というところだったので最悪といえば最悪だけど幸い強力なメンバーたちが加入してきてくれたので全部任せることができてよかった。

あとそういえば社外取締役の家入さんには一度も会わなかった。むしろ避けてた。

キャリアについて

就労に関しては「転職活動!」みたいな意識はあまりなく移住先行だったので正式な面接フェーズもなく、まわりの共通の知人などに推薦してもらってことがすすみ、流れにのってたらそのままビザをもらえた。 エンジニアが「海外!」という時の8割はアメリカを指して残りはヨーロッパを指してる場合が多いので、他の人に「タイに行きます」というと「なぜタイに……?(タイなんかに?)」という反応をされることが多かった。

でも幸運なことに僕はどこでもいいっすという性格だったので、こちらから見ると「なんで行かないの?」という感じであり話は平行線だった。

今の仕事は海外市場のサービスの開発に携われることと、公用語が英語なこと、あと久しぶりにサーバーサイドをやりたかったのでその点も好都合だった。

語学について

英語は本当にできないまま渡航して、なんとかやるだろうぐらいのナメた気持ちでいたんだけど、全然なんとかならなく、とて〜も色々な人に迷惑をかけて死にたくなるところなんだけど社内の日本人に助けを求められるしコード書いてりゃいいし。恵まれた環境を引いたと思う。

タイ語はこっちで会う日本人にも聞いてみると「全然できない」という人が多く、できなくてもなんとななるようだ。というか外国人生活圏で暮せるよう最適化されるのだと思う。

いざとなれば現代の翻訳こんにゃくのGoogle Translate app も所持してるのでタクシーレベルーのコミュニケーションは問題ないと思われる。

コミュニティについて

欧米人も結構住んでるので meetup.com などで結構イベントが見つかる。でも東京もたぶんたくさん開催されてるだろうけど。日本人や東京会社がやってるような聴講者が一斉に着座してMacbookでスライドのメモを取り寿司を食う「勉強会」スタイルのものはなく欧米式のミートアップが主だと思う。

渋谷の地域コミュニティ*2 をもともとやっていたtejitakさんたちの GAOGAO はバンコクを拠点として活動されているので参加しはじめた。

ちょうどiOSDCで隣でHEIFのトークしてた*3 Yoshidaさんも偶然(!) バンコクにやってきたので一緒になってる。

まとめ

  • 学歴や英語が皆無でも東南アジアのビザはなんとかなる*4

あとエンジニアを募集しています

iOSエンジニア向けのイベントでReactの話をした

f:id:laiso:20170918034140j:plain

TL;DR

iOSDC Japan 2017 というイベントが先日開催され、そこでReact Nativeを題材に何かトークをしようと応募したら、まんまと枠をもらえたので話をしてきました。

事前のリサーチでiOSのエンジニアはReactやReact Nativeについて名前や概要ぐらいは知っているけど使ったことのある人は多くないということが分ったので、まずは興味を持ってReact Nativeの環境をインストールしてもらうことをゴールに、Reactプログラミングのパラダイムや思想について、iOSエンジニアが普段行なっているネイティブアプリ開発とどのように違うのか? という内容にしました。

いくぶん抽象的な話に終始してしまい力量不足で本当はもっとわかりやすい説明をしたかったなと反省しつつも、実践的な内容はこれからも各所で見られることになると思うので是非React Nativeにご注目ください。

*

以下は当日に上映したスライドに、スピーカーノートして書いたテキストを交えたものになります。資料だけでは情報が不足していると思われるのでご参考ください。

f:id:laiso:20170918031603p:plain

このトークのテーマは「Viewをどう作るか?」という大きな問題に対して、React Nativeが提供するプログラミングモデルをiOSアプリ開発者の視点でお話します

f:id:laiso:20170918032130p:plain

前提にあるのは「Viewの開発は難しい」という問題です。

Viewはユーザーにも開発者にも心理的な距離が近いので、現実のアプリケーションを作る上で「Viewをどう作るか?」というのは重要な点になっています

f:id:laiso:20170918032200p:plain

その中でFacebookは20億人とも言われるユーザーに対して日々Viewを開発し続けている、世界最大のViewの生産者であると言えます。 そんなFacebookの開発の現場で生まれたUI開発のための考え方を紹介したいと思います。

f:id:laiso:20170918032259p:plain

思い出したように突然の自己紹介です。

私は普段はSwiftとKotlinでiOSとAndroidのネイティブアプリケーションを開発しているのですが、趣味でアプリケーションフレームワークを研究している者です。

f:id:laiso:20170918032320p:plain

まず始めにReact Nativeを一言で説明すると「React でiOSやAndroidのネイティブアプリケーションが開発できるツール群」ということになります

f:id:laiso:20170918032338p:plain

Reactはもともとブラウザ向けのViewを開発するライブラリとして登場しましたが、ブラウザとそれ以外のプラットフォームにViewの解釈が拡大してからは、フレームワークやUIプログラミングのためのプラットフォームの側面が強くなっています。

f:id:laiso:20170918032401p:plain

早速React Nativeを使ったViewのコードをお見せします。

ReactではReact Componentという単位でViewを開発します。

React Componentの考え方はUIViewControllerに近いので、あえてViewControllerという名前をつけました

Interface BuilderやStoryboardは利用せず、Viewの定義はすべて render() 関数以下に埋め込みます。

これはUIKitでいうところの loadview() メソッドになるでしょう

f:id:laiso:20170918032438p:plain

React Native がViewを書き出すまでの仕組みです

React Nativeで書いたJavaScriptのコードは、仮想的なViewのデータ構造としてバックグラウンドスレッドでJavaScriptCoreによって処理され、最終的に1つのルートUIViewとなって出力されます

このためネイティブアプリの中の一部分のView以下にReact Nativeを使うという方法も可能になっています

f:id:laiso:20170918032510p:plain

そして、私達がUIKitでViewをどのように作っているのか? というお話にふれます

UIKitでのプログラミングではInterface Buildを通じてViewControllerが扱う初期状態のViewを定義します

ViewController内部プロパティでプレゼンテーションのための状態データを管理し、イベントが発生するごとに操作してViewを書き換えるコードを書いています。

Viewを更新するコードの積み重ねは、1つのViewControllerが抱える要件が増えていくことによってどんどん肥大化していきます。

ここにViewの開発は難しいという問題の根本があると思っています。

f:id:laiso:20170918032635p:plain

これに対しReactコンポーネントはViewに必要な状態が変る度にView全体がフレームワークによって自動で再構成されます

開発者はViewを更新するための具体的な手順を記述せずに、Viewが描画された後の結果を直接XMLのコードで表現します

これを宣言的なViewと呼びます

f:id:laiso:20170918032728p:plain

Reactの宣言的なViewの利点は、フレームワークによって「Viewをどう表示するのか」という手続きが隠され、「どう表示された」だけを抽象的に考えてViewを作ることができます。

Interface Build が表示する前の状態を定義するのとは対照的に、ReactのViewは表示するViewそのものをコードで表現します。

この為、状態変数によってViewの内容が変わる、というコードを render() 関数内にすべて書くことができます。

これは継続的なUI開発で変更しやすく複雑になりにくいコードを維持することにつながります。

f:id:laiso:20170918032826p:plain

次に複数のReact Componentを使ったコードを見ていきたいと思います

React NativeではUIKitの各コンポーネントはReact Componentとしてフレームワーク内に用意されているので、直接UIViewControllerなどを操作することはありません

開発者は独自のReact Componentを定義して、それらを組立ながら画面を構成していきます。

これをReactではコンポーネント指向なViewといいます

コンポーネント間のデータのやりとりは一般的には、より上位のコンポーネントから差しこんだり、ハンドラ関数を登録し任意のコンポーネント内で処理が実行されるようにしたりします(Delegateパターンに少し似ています)

f:id:laiso:20170918032951p:plain

コンポーネント指向でViewを構成することの利点は、各Viewが小さな部品となり取り扱いやすくなることにあります。

一般的なプログラミングでクラスや関数を作ることと動機は同じです。

コンポーネントはただのデータ構造なので、それ自体が引数と戻り値がある関数であるととらえることができテストも書きやすいです

大きくなったコンポーネント下位コンポーネントへ分割し小さくしたり、内部の詳細はカプセル化されているので他のコンポーネントと共有化することもできます

またUIViewControllerモデルではどうしてもViewControllerの切り替え=画面遷移して移動。となってしまう場面でもいつの画面内で済ませられるように感じます

f:id:laiso:20170918033021p:plain

React Component と UIViewController を比較した時に UIViewController側に不足しているのは複数のコンポーネントを組み合わせる時の協調性です

各ViewとViewControllerがどのような親子関係にあるのかをaddChildViewController() で記述することになります。

Reactのような自動でViewを描画する仕組みもないので、データが更新された時に適切に内部通知されデータが渡される仕組みを作り、開発者が手動で必要なViewを探し更新する、もしくはデータバインディング系のライブラリで補うことになります

f:id:laiso:20170918033051p:plain

ReactはどうViewを作るのか? についてまとめます

ReactのViewは内部状態の更新以降の処理をライブラリ側で行ってくれます

命令ではなく結果をコードで記述するようになるので、よりアプリの本質的な部分だけを考えることができます

ReactのViewはコンポーネント単位の環境に依存しないデータ構造になります

小さな部品を組み立てるようにViewを構成するので複雑なUIをより開発しやすくします

f:id:laiso:20170918033118p:plain

これに対しUIKitプログラミングでは、Interface BuildとViewControllerを駆使してViewを作ります

基本的にViewcontrollerを起点に開発者がすべてViewを手動で記述するので、Viewが複雑になりがちです

f:id:laiso:20170918033134p:plain

React Nativeのすごいところは、UIKitプログラミングの考え方とは全く異るパラダイムで同じアプリケーションを開発できるという体験を持ち込むことに成功しています

UIKitをそのまま動かした上で、既存の開発環境の抱える問題をうまく解決しているという点が非常に夢がある技術だと感じます(しかし現実は厳しい事もたくさんあります)

f:id:laiso:20170918033238p:plain

Interface Builder で構成するViewは状態管理に弱く、命令的なコードを開発者自身が記述しないといけないため、Viewの複雑さを引き起します

また、1画面すべてをViewController以下に収めるプログラミングは拡張性に乏しく、柔軟性に欠けます

React Nativeが解決する問題は現在のUIKitの制約と深く結びついています

つまりiOS SDKやXcodeの進化によって改善するべき点を示唆していると思います

f:id:laiso:20170918033304p:plain

最後にこれらの問題を解消すべく、UIKitがどう進化するといいのか? という話題について個人的な妄想を話します

f:id:laiso:20170918033323p:plain

宣言的なViewを実現する方法としてUIデータバインディングがあります。

MacアプリにはCocoaバインディングというInterface Builderでネイティブに動作するデータバインディングの仕組みが既にあります。

これを是非UIKitプログラミングの世界にも統合して使えるようにしてほしいです

f:id:laiso:20170918033345p:plain

さらに次世代のInterface Buildでは、WindowsやAndroidの開発環境のようにプレーンテキストとプレビュー形式でUIを構成したいです

もしくは、コンパイラレベルの拡張が必要だと思いますが、JSXのようにSwift内でViewの構造を宣言できるのも面白いかもしれません

f:id:laiso:20170918033406p:plain

またReactのコンポーネント指向を例に、複数のUIViewControllerが協調して画面を構成できる仕組みを強化して欲しいところです

Appleらしいやり方としてはStoryboardを拡張してグラフィカルに記述できるようになるというのもいいかもしれません

その時はReactのFluxアーキテクチャのようなコンポーネントツリーを横断してデータを取得する方法の研究も必要になってくると思います

f:id:laiso:20170918033435p:plain

皆さんもReact Nativeで「未来のiOSプログラミング」を想像(創造)しませんか?

以上で私の発表は終了させていただきます

おまけ

尺の関係で個人的には好きだが技術的な解説に寄ってしまうので削った部分がありました、別の機会で何か残したいと思います

  • React DOM
    • React + (View)
    • View=DOM, Native, Canvas, SVG, WebGL
    • ^ 一方ウェブブラウザ上で実行されるReactはReact DOMと呼ばれています。
    • Reactのシステムによって最終的にViewが描画されるプラットフォームごとにパッケージ化されており、そのうちの1つがReact Native となります
  • React for iOS を実現するツール
    • AsyncDisplayKit
    • ComponentKit
    • React Native
    • ^ React Native 以前にReactにヒントを得てiOSのUIKitで動作するライブラリとして「AsyncDisplayKit」と「ComponentKit」が存在します。
    • Facebookの社内プロジェクトとして開発は独立していて、それぞれ発展を遂げているのですが、現在のReact Nativeに影響を与えています。
  • React Nativeの仕組み
    • JavaScriptコードをバンドル
    • RNランタイムをロード
    • バックグラウンドと通信してRootViewが更新される
    • ^ React NativeではコンポーネントのレイヤーをJavaScriptで記述し、JavaScriptCore経由でネイティブのUIKitコンポーネントのViewへ適応します。
    • 前述のように内部的には各Viewに相当するデータ構造を保持していまして、バックグラウンドスレッドや最小限のコストで描画処理が走るよう最適化されています。
  • Virtual DOM or Virtual View
    • Viewのデータ構造を生成し
    • 差分を部分的に描画する
    • 高速なViewの描画が可能になる