$30 off During Our Annual Pro Sale. View Details »

Flutterを使って医師相談アプリを短期リリースした話

 Flutterを使って医師相談アプリを短期リリースした話

コロナ時代の医療業界を支援するエムスリーのプロダクト開発の舞台裏 にて発表
https://m3-engineer.connpass.com/event/180876/

AskDoctorsのアプリをFlutterで開発したときの話です

Takaki Hoshikawa

July 09, 2020
Tweet

More Decks by Takaki Hoshikawa

Other Decks in Programming

Transcript

  1. View Slide

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

    View Slide

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

    View Slide

  4. View Slide

  5. View Slide

  6. View Slide

  7. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11.  
    しかし

    View Slide

  12.  
    アプリがない

    View Slide

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

    View Slide

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

    View Slide

  15.  
    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実装

    View Slide

  16. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  21. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  29.  
    Hot reloadが爆速

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  33.  
    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');
    }
    }
    より、一部改変

    View Slide

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

    View Slide

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

    View Slide

  36.  
    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
    }
    より、一部改変

    View Slide

  37.  
    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
    }
    より、一部改変

    View Slide

  38.  
    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
    }
    より、一部改変

    View Slide

  39.  
    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
    }
    より、一部改変

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  47. View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide