Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

  ● 星川貴樹 (@oboenikui) ● Androidエンジニア ● 2017年新卒入社 ● Kotlin Fest 2018, 2019スタッフ

Slide 3

Slide 3 text

  ● 医師相談サービスAskDoctorsについて ● AskDoctorsアプリで使われている技術の話 ● AskDoctorsアプリプロジェクトの話

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

  COVID-19に関する相談を無料で行えるように ● 相談には通常有料会員登録が必要 ● COVID-19関連の相談が7/9現在 5,800件以上

Slide 9

Slide 9 text

  COVID-19の一部相談を無料公開 ● 相談の閲覧も有料会員以外は通常制限あり ● COVID-19関連の質問のうち一部を無料公開

Slide 10

Slide 10 text

  テレビでも紹介! ● めざましテレビで紹介されました! 家具レンタルに医師への健康相談も! ステイホームで利用者増の注 目「サブスク」

Slide 11

Slide 11 text

  しかし

Slide 12

Slide 12 text

  アプリがない

Slide 13

Slide 13 text

  メンバー構成 ● アプリエンジニア(私)、サーバサイドエンジ ニアはAskDoctorsチーム外のメンバーとい う強気の構成 ● プロジェクトは1月スタートなのにデザイナー は4月入社というさらに強気の構成 役割 人数 プロダクトマネージャー (メイン・アシスタント ) 2 スクラムマスター 1 アプリエンジニア 1 サーバサイドエンジニア 1 QAエンジニア 1 デザイナー 1

Slide 14

Slide 14 text

  2019年12月 AskDoctorsアプリ 構想が持ち上がる プロジェクト 始動 2020年1月 プロジェクト状況 社会的な状況 1/16 国内最初の COVID-19感染確認 ペーパープロトタ イプv1完成 プロジェクト承認 2月 3月 ユーザーインタ ビュー開始 2/13 東京都在住者初の COVID-19感染確認

Slide 15

Slide 15 text

  3月 アプリ 実装開始 4月 プロジェクト状況 社会的な状況 3/20 国内累計感染者 数 1,000人を超える アプリv1.0.0 完成 5月 6月 ユーザーイン タビュー開始 4/7 7都府県に 緊急事態宣言 5/25 東京都など 緊急事態宣言解除 デザイナー入社 4/18 国内累計感染者 数 10,000人を超える 6/18 自粛要請解除 Flutter未経験ながら 約2ヶ月で両OS実装

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

  ファーストビューでアプリの世界観をつかめるよう に、トップでは以下の3つに絞った ● どんな相談が寄せられているのか ● 相談開始 ● キーワード検索

Slide 18

Slide 18 text

  ファーストビューでアプリの世界観をつかめるよう に、トップでは以下の3つに絞った ● どんな相談が寄せられているのか ● 相談開始 ● キーワード検索

Slide 19

Slide 19 text

  ファーストビューでアプリの世界観をつかめるよう に、トップでは以下の3つに絞った ● どんな相談が寄せられているのか ● 相談開始 ● キーワード検索

Slide 20

Slide 20 text

  ファーストビューでアプリの世界観をつかめるよう に、トップでは以下の3つに絞った ● どんな相談が寄せられているのか ● 相談開始 ● キーワード検索

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

  クライアント 作業するエンジニアは Androidエンジニア1人 ほぼ1コードでiOS, Android両OS対応 できるクロスプラットフォーム技術 サーバー チーム外のエンジニアが担当 Web版と重複する機能が多い 新規でサーバをたてずに 既存プロダクトに機能追加 今日の話はこちら

Slide 23

Slide 23 text

  ● Flutter ● Firebase ○ Push通知やAnalyticsで利用 ● OpenAPI ○ APIの提供先がこのアプリのみなのでGraphQLなどは用いず ○ Dart向けにAPIクライアントの自動生成をしやすいのも強み

Slide 24

Slide 24 text

  ● Googleが提供する、DartのUIツールキット ● 単一のコードベースからモバイル・Web・デスクトップ向けに ネイティブコンパイル可能 ● OSのUI Frameworkのラッパーではなく、独自のレンダリングエン ジン上で動かす

Slide 25

Slide 25 text

  プラットフォーム固有のコードをほぼ書かずに済む ● ビジネスロジックに加え、UIもコードをほぼ共通化できる ● コードを共通化してもジェスチャーナビゲーションやアニメーション が各プラットフォームで自然

Slide 26

Slide 26 text

  プラットフォーム固有のコードをほぼ書かずに済む Android iOS

Slide 27

Slide 27 text

  Material Designが標準 ● Material DesignはAndroidエンジニアに馴染み深い ● ガイドラインのドキュメントがFlutterのドキュメントとリンクし ており、コンポーネントの正しい使い方と関連付けしやすい ● Material Designガイドラインの新コンポーネントの実装が早い

Slide 28

Slide 28 text

  Hot reloadが爆速 ● Widgetの微調整で多大な恩恵を受ける ● ただし修正箇所によってはHot reloadが効かないケースもある

Slide 29

Slide 29 text

  Hot reloadが爆速

Slide 30

Slide 30 text

  他のプロジェクトでも使っていた ● Androidエンジニアが関わる他の社内プロジェクトでも採用してお り知見共有しやすかった ● 結果的に社内でクロスプラットフォームで作るならFlutterという 風潮に

Slide 31

Slide 31 text

  Flutter導入時の疑問 ● Dartってどうなの? ● UI構築とかやりやすい? ● ライブラリちゃんとあるの?

Slide 32

Slide 32 text

  言語仕様はとっつきやすく、流行を取り入れてきている ● Dartの言語仕様はJavaやJSに少し似ておりとっつきやすい ● 例えばNull-safetyも言語仕様として導入されており今後に期待 (Flutterではまだ使えない)

Slide 33

Slide 33 text

  Future createFile(String fileName) async { try { var file = File('$fileName.txt'); if (await file.exists()) { var modified = await file.lastModified(); print('$fileName は既に存在します。 $modified に変更されました。'); return; } await file.create(); } on IOException catch (e) { print('$fileName を作成できません: $e'); } } より、一部改変

Slide 34

Slide 34 text

  好きなIDEを使える・補完機能などは改善中 ● 補完などの機能はdart analysis serverに委譲 (LSPも対応) 原理的に特定のIDEに依存しないので好きなエディタを使える ● ラムダ式の補完がDart 2.8 (5月リリース) で実装されるなど発展 途上ながらも、現行バージョンでも十分利用に耐えられる

Slide 35

Slide 35 text

  Web開発に近いスタイル ● 基本的にシングルスレッド・イベントループ ● 文法は全く異なるが、Reactと同じく宣言的UIを採用しているので 経験があればスッと理解できそう ○ CSSはないのでカスタマイズ性でつらいところはある

Slide 36

Slide 36 text

  Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('$_pageTitle'), ), // AppBar body: Center(child: Text('$_count 回')), floatingActionButton: FloatingActionButton( onPressed: () => setState(() => _count++), tooltip: 'カウンタ', child: const Icon(Icons.add), ), // FloatingActionButton ); // Scaffold } より、一部改変

Slide 37

Slide 37 text

  Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('$_pageTitle'), ), // AppBar body: Center(child: Text('$_count 回')), floatingActionButton: FloatingActionButton( onPressed: () => setState(() => _count++), tooltip: 'カウンタ', child: const Icon(Icons.add), ), // FloatingActionButton ); // Scaffold } より、一部改変

Slide 38

Slide 38 text

  Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('$_pageTitle'), ), // AppBar body: Center(child: Text('$_count 回')), floatingActionButton: FloatingActionButton( onPressed: () => setState(() => _count++), tooltip: 'カウンタ', child: const Icon(Icons.add), ), // FloatingActionButton ); // Scaffold } より、一部改変

Slide 39

Slide 39 text

  Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('$_pageTitle'), ), // AppBar body: Center(child: Text('$_count 回')), floatingActionButton: FloatingActionButton( onPressed: () => setState(() => _count++), tooltip: 'カウンタ', child: const Icon(Icons.add), ), // FloatingActionButton ); // Scaffold } より、一部改変

Slide 40

Slide 40 text

  完璧にOSに寄り添ったデザイン、というのは厳しい ● OSごと両方実装するのでなければ、iOS UIとMaterial Designの どちらかを選択する必要がある ● Material Designを使っている人の方が圧倒的に多そうなので無難 にやるならMaterial Designを採用した方がよさそう ○ iOSのMaterial DesignなGoogleアプリを許せるなら問題ない

Slide 41

Slide 41 text

  標準コンポーネントが若干拡張性に乏しい ● 状態を持つWidgetの場合、継承してカスタマイズが難しい場合あり ● 他にも可視性がprivateに設定されたクラスが多く、継承できない 問題は多い

Slide 42

Slide 42 text

  ほぼSwift/Kotlinのコードを触る必要がないほどまで発展 ● Flutterライブラリがある ≒ Swift/Kotlinを触る必要がない ● Webサイトと同等機能を有するアプリであればライブラリを利用すれ ば困らない ● 今回使ったOpenAPI GeneratorやFirebaseもDart・Flutterに 対応

Slide 43

Slide 43 text

  ライブラリの質は…… ● かなり使われているものでも数ヶ月メンテナンスされていないライブ ラリが結構あるのが欠点 ● デファクトスタンダードと呼べるものはまだ少ない ● プルリクチャンスが多い

Slide 44

Slide 44 text

  (WebViewを扱うライブラリのissueにて) Q. 「Cookie取得したいんだけどどうしたらいい?」 A. 「evalJavascript("document.cookie") で取得できるよ」 HttpOnly Cookie 取得できないじゃん ドメインを指定して 取得とかも厳しい

Slide 45

Slide 45 text

  (特に)iOSのバージョンアップに追従できていないケース Androidエンジニアが作ってることが多いのか、iOSでバグることがそ れなりにある

Slide 46

Slide 46 text

  ● 新規アプリ ● UIを共通化しても問題ない場合 ● エンジニアのリソースが限られている場合 ● OS固有の処理が少ないケース ● 機能的にはWebでも実現できるサービスのアプリ

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

  ● デザイナーが4月入社 & 即アサイン ● ペーパープロトタイプや実装はデザイナーなしでその前から着手

Slide 49

Slide 49 text

  ● デザイナーが4月入社 & 即アサイン ● ペーパープロトタイプや実装はデザイナーなしでその前から着手 ● デザインを凝らずにプロトタイピング & 実装 ● Material Designのガイドライン的にこうだろう、という判断で仮 決め

Slide 50

Slide 50 text

  ● Google, Apple共にCOVID-19関連アプリは基本的にリジェクト ● 社内でも「感染を回避する行動を取ろう」というコンセプトのアプリ がリジェクトされまくった

Slide 51

Slide 51 text

  ● Google, Apple共にCOVID-19関連アプリは基本的にリジェクト ● 社内でも「感染を回避する行動を取ろう」というコンセプトのアプリ がリジェクトされまくった ● 苦渋の決断でCOVID-19無料相談の実装を削除

Slide 52

Slide 52 text

  ● いざ審査を出すとGoogleは問題なく通ったがAppleはリジェクト ● 「医者が答えてる保証はあるんですか?」

Slide 53

Slide 53 text

  ● いざ審査を出すとGoogleは問題なく通ったがAppleはリジェクト ● 「医者が答えてる保証はあるんですか?」 ● AppStore Connectでコミュニケーションを取って医師が回答して いることの説明を数回

Slide 54

Slide 54 text

  ● Apple「アプリ外課金してますよね?」

Slide 55

Slide 55 text

  ● Apple「アプリ外課金してますよね?」 ● 課金リンクを消しても、一部例外を除き有料サービスのアプリは AppStoreの課金を実装する必要あり (Netflixアプリとかそういう方針だから行けるかと ……) 関連記事: https://gigazine.net/news/20200617-apple-hey-pay-subscription/ ● アプリ内課金は現在実装中のためiOS版は未リリース……

Slide 56

Slide 56 text

  ● Android版AskDoctors使ってみてください! ● Flutterはいいぞ! ● 医療のコンシューマプロダクトに興味あるエンジニア募集中!!!