青空な日々

ITエンジニア関連で興味あることをアウトプットして共有したいブログ

#DroidKaigi 2019 2日目の感想

はじめに

2019年2月8日(金)にAndroidアプリ開発者向けの大規模勉強会、
DroidKaigi2019に行ってきました!
この記事は2日目の感想記事になりますー。

DroidKaigiについて詳細はこちら。

droidkaigi.jp

1日目の感想はこちら。
#DroidKaigi 2019 1日目の感想。 - 青空な日々

目次

今回もメモ多めで長いので、気になったトコだけ推奨。


感想

一日目と同様にセッションを聞いてる最中にメモした内容と感想です。
DroidKaigi2019は同時に複数のセッションが開催されるので、
一人で全ては見れません。
今回は私が生で見たものだけの感想ですー。

あとメモは聞きながら取ったので、正確な内容や詳細は資料を御覧ください。
(メモのフォーマットが毎回バラバラですいません…)

また、当日の様子はTwitterハッシュタグから振り返ることができます。
各部屋ごとにハッシュタグが違うので、気になる方はそれぞれどうぞ!
例:#droidkaigi #room3 - Twitter Search

なお、タイムスケジュールはこちら

10:30 中規模以上のアプリ開発におけるCIレシピとリリースフロー戦略

資料。


サンプルyml
bitrise.yml example · GitHub

属人化している作業が多いとメンバー入れ替えの際に教育コストがかかる。

複数人でのブランチ運用の辛さ
 リリース待ちになる
 など

GitFlowで改善する
 でもチームメンバーで徹底すめの大変。
 学習コストとか。

そこでGit-Flowコマンド
 GitFlowでやりやすいようにコマンドが変更(エイリアス)されている
 SourceTreeでも対応している

巨大なフューチャーブランチを解決する工夫
 親フューチャーと子フューチャーに分ける

Ciツールについて
 どれ使う?
  動けばなんでも良いのでは?(個人の感想)
 スピーカーはBitriseを使ってる
  GUIで組める(エディターがわかりやすい)
  アプリに特化しているので証明書まわりとか楽
  CiツールとGitFlowの連携
 Masterにプッシュしてtag付されたのをトリガーにGooglePlayにアップしている

ワークフローの構築の考え方
 環境変数などに変数を切り出しておくと、新しいワークフローを構築する際に楽。

GoogleDeveloperApiを利用した工夫
 公開比率の自動変更(新バージョンのアップロードとリリースを行うApiで実施できる)
 自動化のサーバーはktor(kotlin)で書いた

CrashlyticsAPIとの連携
 できなくはないが難しい
 データを蓄積したりしないとダメなのでコストがかかりそう

感想

GitFlowの存在は知っていたけど、改めてちゃんと説明を聞くと名前だけ知ってる…状態でした。
複数人で何かを作業するときに共通のルールを適用してコミュニケーションコストを下げ、
かつオンボードしやすいようにコマンドなどを工夫しているのは素晴らしいと思いました。

あと資料のデキがものすごく良かったです!
見やすさ、配色の綺麗さ、絵が可愛い、アニメーションの使い所、絵が可愛い、あと絵が可愛い!
これは真似したいスライド。
ついつい四角い配置をしがちなので、特に斜めのデザインが素晴らしいなぁと思いました。

11:20 Guide to app architectureを踏まえた既存アプリの設計改良

資料。

ターゲット
 初学者
 レガシーコードを抱えている
  なかなか移行して設計パターンを改善する話は少ないのではないか?というのがきっかけ

楽天ラクマ(昔はフリマ)は歴史のあるプロダクト
 これを設計改善していく話。

課題
 膨らんだ画面の変更や拡張のコスト
  フォームがいっぱいあるとか。
 テストができなくて検出できなかった不具合
  Viewに入り込んだビジネスロジックによって起こる
  エラー画面とか…
 画面回転などActivity再生成にたいするアプローチ
  何でもかんでもSaveInstanceに突っ込む
  オレオレアプローチになっちゃってる…

藁にもすがる思いで公式ドキュメントを読んだ
 Guide to app architecture(原理原則)やGoogleの推奨される設計パターンなど
 去年のDroidKaigiアプリが綺麗にできている
  https://github.com/DroidKaigi/conference-app-2018
 ドキュメントはこちら
  https://developer.android.com/jetpack/docs/guide

これらの知見を自分たちの事情に応じて工夫して取り入れる

ViewからViewModelへ分割する

ActivityやFragmentの再生成対応
 savedInstanceStateを必ず意識するようにViewModelにインターフェースとして実装を強要するルールにする

Viewに反映するもの
 揮発性
  イベントなど
    SingleLiveEventがおすすめ(LiveDataなど)
   ただし、LiveDataは一回しか通知しないので要注意。
 不揮発性
  状態などレイアウトに書き込めるもの
   DataBindingでやりとりする

サンプルアプリ
 https://github.com/nakamuuu/jetpack-architecture-playground
 フォームに項目名がくっついてるのいいな。

段階的に変えていける仕組みを作る
 一気に全部は大変。
 弊社はモデル部分もViewもくっついてるからそこを分離するところから考えるべきなんだろうな。

終わった後のスピーカーへの質問で、 サンプルとしてandroid-sunflowerも良さそうと小耳に挟んだ。
GitHub - googlesamples/android-sunflower: A gardening app illustrating Android development best practices with Android Jetpack.

感想

「既存アプリの設計改良」はまさに弊チームがやらなければならないことで、
何か持って帰れるといいなぁと思い聞かせていただきました。

お話を聞いているとModelの構造が良くできていたため、
Viewからロジックを切り離すだけでどうにかなったのかなぁという印象でした。
自分たちはViewにModel(データ操作)も入っちゃっているので、
まずはViewからModelを追い出すところからやらないとだめそう。

その他、Activity再生成などの対策なども説明されていて非常に参考になりました。
チームとしては動けなくても個人としてはいろいろやっていきたい。

12:50 Best practice for text on Android and its internals.

資料。


Android Textのパフォーマンスについて。

そもそもTextって遅いの?
答えはケースバイケース。
つまり遅くなる場合があるから気をつけた方が良い。
たとえばリストとかに大量にテキストがある場合にスクロールしたときとか。

というわけでベストプラクティスについて持ち帰ってもらいたい。

UIのパフォーマンスについてはAndroid UI Performanceという動画参考になる(資料にある)
systraceという仕組みで計測できる。
ヌルヌルにするにはUIスレッドの処理を16msecで更新できるようにしたい。

サンプルではTextViewのonMeasureが遅い。
別のサンプルで画像とか入れても更新時間の97%はTextView。
Measureは幅と高さを決める処理。

TextViewは文字列と描画パラメータで決まる。
この処理はブラックボックス
これを紐解いていく。

紐解き
 遅いのは1行で描画できるかどうかの判定と改行する仕組み。
 さらにみていくと、doLayoutというAndroid内部で呼ばれている関数が大量に呼ばれている。
 doLayoutは改行時に単語ごとにはみ出るかどうか?をdoLayoutで描画して判定している。
 さらにはみ出るとなったとき、単語の切れ目を探すために単語を切り刻んで描画して試す。
 例えばexampleなら、ex,exam,examp....みたいに描画してみて書けるとこまでを判定している。
 これをhyphenationと呼ぶ。
 で、hyphenationを無効化するとこの切り刻む処理がなくなるので早くなる。
 次の改善点。
 これ以上UIスレッドの処理は減らせないので、処理をバックグラウンドとか別スレッドでやっちゃえば早くなるはず。
 とはいえそんなに簡単に切り出せないので、描画前にキャッシュをさせることで描画時にキャッシュを使わせるようにする。
 そういうAPI、PrecomputedTextCompatを作った。
 これで毎フレームちゃんと画面更新できる(ヌルヌル動く)アプリとなった!

ここまでのまとめ
 可能ならhyphenationをオフにしよう
  日本語には無いけど、英単語を含む場合は早くなる。
 PrecomputedTextCompatを使ってくれると嬉しい

フォントについて最近の変更点の説明
 特に気をつけるべきことはなさそうなので興味があれば資料を参照のこと。

次にレイアウトの話
 こちらも特に気をつけるべきことはなさそうなので資料を参照のこと。

感想

メチャメチャ面白いセッションでした!
面白いというのは興味深いという意味でということ。
特にアプリ開発をしているとOSに近い低レイヤーな部分はあまり意識しないので、
そういった部分まで踏み込んだ話を聞けたのが非常に参考になりました。

PrecomputedTextCompatは問題なく導入できればUXが上がりそうなので、
テキストをたくさん使うような箇所には是非導入したいところ。

自分の過去の経験としてメモリや性能で散々痛い目を見て開発してきたので、
今みたいにメモリや性能をまったく意識していない開発(が多いイメージ)はちょっと思うところが多い。

これを機に最優先とは行かないまでも、簡単に対策できる箇所はしていきたい。

14:00 Android Studio設定見直してみませんか?

資料というか、詳細な内容。
shiraji.hatenablog.com

観客に感心したら「おー!」と言ってほしいと言ったら、
ちょいちょい「おー!」が入って進行に障害がw

喋る内容は後でブログにあげるとのことなので、
ほぼメモは無し。

ショートカット(Shift2回?)でSyncの実行できるの知らなかったなー。
と思っていたら、なんと御本人からこの件についてリプが飛んできました!ありがたや。
cmd+shift+aで実行できるそうです。


上記のブログを見直してこれは良さげだなぁというのを記載。

  • コードフォーマット
  • Inject Languages
  • Preferenceのパスのコピー方法
  • 設定の共有

ぜひ一度上記のブログを見てもらえるといろいろ効率をあげられそう。

感想

本人はネタ枠のようなことを仰っていたような気がしましたが、
非常に参考になる良いセッションでした。

マルチモジュール化のメリットがビルド時間の向上にあるのであれば、
普段の開発効率をあげるこういったTipsは非常に役立つハズです。
その点からも素晴らしいなぁと関心してしまいました。

あとお子さん可愛かったです!w
(観客からのおー!の練習のためにスライドの最初にお子さんが出ていた)

14:50 今日から始める依存性の注入

資料。


DIが有効活用できそうなよくあるケース。
 MVPパターンでの例
  Repositoryでnewしているオブジエクトがある
  コンストラクタでインスタンスを指定する
  そうするとRepositoryを使う側がめんどいし意識する必要がある
  コンテナを作ってそこから使えば意識する必要もないし楽。
 この流れがDI
  Daggerを使うのがDIではない

DIコンテナを自作するといろいろ問題が…
 ActivityやFragmentではコンストラクタで指定できない
 これを工夫するとContextなどのスコープが不必要に長くなってしまう。
  Activityのライフサイクルに依存してほしいのにシングルトンになっちゃうとか。

DIコンテナについて
 DIを実現するためのライブラリ。
 サンプルとしては自作したが、ライブラリを使った方がいろいろ楽。
 Dagger2とkoinがメジャー。

Dagger2
 コンパイル時にコード生成するのでコンパイルエラーで気づける
 逆にビルドが遅くなる
 あと公式ドキュメントがわかりづらい
   Moduleという仕組み
  buildeパターンなどはコンストラクタでnewできないためDaggerで解決できない
  そこでModuleという仕組みでnewするコードを書く。

 とりあえずサンプル通りにやってみるのが早いだそうで。
 多機能だが難しい。
 公式ドキュメントも難しい

Koin
 コンパイル時にコード生成しないので実行時まで問題があるかどうかはわからない
   簡単だがシンプル。
 公式ドキュメントが読みやすい。
  なぜDIするのか(何が変わるのか?)
 単体テスト時にテスト対象のクラスでnewしていると、テスト対象以外のクラスも対象になってしまう。
 DIしていればMockを渡すことで対象をしぼれる。

 結合テストでも使える
  APIなどの外部要因をモックにすることでテストが楽にできる。

感想

事前にもっとも聞いてみたいセッションのひとつでした。
Daggerよくわからないマン。

が、説明を聞いてなんとなく分かったマンくらいにはなれた気がします。
内容にもあったように一度、手を動かしてみたほうが早いですね。

DaggerとKoinの違いについてはメリデメがはっきりしているので、
チームやプロダクトの状況合わせて選べば良さそう。

個人的にはKoinの方が良さげな雰囲気だけど、
Moduleのあたりなどちゃんと理解してなさそうな気がするので両方試してみようと思います。

ありがたいセッションでした!

15:40 multi-module Androidアプリケーション

資料。


モジュールとは?
 Android内でコンパイル単位を分割できる単位。
 ApplicationModule
  APKにできる
 Android Library
  ライブラリとしてAARにできる
 Dynamic Feature Module(DFM)
  インストールごとに追加できる

なぜマルチモジュールにするのか?
 ビルドの高速化
 ソースコードの依存関係のルール化(強制)
 モジュール単位にテスト可能
 デモ版と本番用に切り分けつつリファクタなどのソース全体に影響をあたえる仕組みが利用できる
 さらに分割したアプリを作れる
 kotlinではコードの可視性をモジュール単位に指定できる
 DFMが利用できる

マルチモジュールのビルドの高速化について

Android Gradle Plugin 3.0による高速化
 3.0より前
  間接的に参照できていた
    app -> mod1 -> mod2
    appがmod2を参照できてしまう。
 3.0以降
  直接参照のみ許される
  これにより修正箇所に直接依存しているモジュールのみのビルドが可能(高速化)

サンプルとして規模が大きいプロジエクトを作ってシングルとマルチで計測してみる(s)
        フルビルド  インクリメンタルビルド
 シングル    36.4     14.2
 直列マルチ   38.8     10.2
 並列マルチ   30.0      7.0
  gradleのサーバーに送り込んで時間を計測できる
 builde時に-scanを指定する

Annotation Processingはインクリメンタルに対応していない
 そのためモジュールに分割して速度を担保する

realmなどの特殊なライブラリはビルド後に動的に書き換えられる
 そのため書き換え対象を検索する処理に時間がかかる
 だからモジュールに分割して対象を限定することでビルド時間を早められる

高速化できるモジュールの分割について
 モジュールの大きさ
  大きいモジュールの場合は遅い
 参照される数
  参照されるが多いと辛い
  最新にアップデートして使う
 アルゴリズムが進化してるので新しい方が効率が良い。

分割の方針
 縦方向は機能、横方向はレイヤー。
  両方を組み合わせても良いのかも
 sansanのeightの場合
  あとで見れる資料をみる
 既存アプリに対する方針
  16:30のtsuyoyoさんのセッションで解説されていたのでおすすめ
  appは最小限のコードだけにして、legacyというモジュールに移動する
   ただしDugger2の場合は循環参照に注意
 最小限のappは役に立つ
  細かい単位のアプリを作れる
  CleanArchitectureがやりやすい
  新機能は新しいモジュールにしてレガシーには触らない
 なるべくレガシーには触らないようにする

感想

マルチモジュールという概念を知ったのが今回のDroidKaigiだったので、
まさに自分にぴったりなセッションでした!

弊社のアプリの設計を見直すのにマルチモジュール化が役立ちそうなので、
ちゃんとメリデメをチームに伝えていきたいところ。

やはり分割の方針が一番悩みそうなので、
そういった考え方や事例を出してくれているのが非常に助かりました。
とはいえ絶対的な答えは無いので、
レガシーappに追い出してからじっくりと取っ組み合って行く感じかなぁ。

基礎から説明してくれている素晴らしいセッションでした!
ありがとうございます!

16:50 Navigation Architecture Component によるアプリ内遷移の管理

資料。


諸事情でメモが取れなかったので感想のみ。

感想

Navigation Architecture Componentは一度調べたことがあって、
そのときはバージョンが新しすぎて断念したんだけど、
最近はバージョンを上げることも出来ているので聞かせていただきました。

なんとなく画面遷移が楽できそうとかで使いたいって話だったんですが、
デザイン原則やDeppLink時のスタック再現の話など気をつけなきゃいけない点もあって非常に勉強になりました。

あとUpボタンの事が良くわからなくてあとで調べたら、
左上に出てくる詳細から一覧に戻るために使うようなボタンだと認識。
素人過ぎるな…w

17:40 ああ、素晴らしきTDD ~アプリとエンジニアの心に安寧を~

資料。

www.slideshare.net

ヤフオクはLEAN XPで開発されている。

TDDとは
 テスト駆動開発
 対象はユニットテスト
 3つのフェーズ
  3つのフェーズをひとつのユニットテストごとに繰り返す
 3つのルール
  資料より。
  コンパイルエラーはテストコードのエラーも含むのか!なるほど。

ルール通りにいくと最初はテストを書く
 テストコードの書き方基本
  arrange
   準備
  act
   実行
  assert
    チェック
 ソースを横に並べて、テストコードを書きながら平行して右側にASのサポートでコードを書いていく。
 TDDではテストコード1個1個が仕様となる
  その仕様を最小限で満たすだけのコードしか書かないことが重要。
 それでテストが通ってしまったら?
  テストが足りないことを考える?
 リファクタフェーズは「テストコード」もリファクタする
  ポイント
 テスト書かないとプロダクトは書かない
 テストとプロダクトを行き来する

3つのメリット
- テストの漏れが発生しない - 良い設計になる - 常にキレイなコードになる

なぜTDD?
 より早く質の高い価値を提供するため、安心してコードを直せる状態が必要。
 安心はTESTを担保できる。
 そのためにTESTを書きましょう。
  実感として安心感がすごい。

AndroidTestは時間がかかるので、大事なところだけ使う。
 大事なところ?
  HappyPathという考え方
  ユーザーのハッピーが実現できるパス

テストの粒度
 public関数の数分
  それが振る舞いのテストとなるはず。
 privateはpublicから呼ばれるのでpublicだけやりばOKなはず

TDDに関するQ&A
 UnitTestの大変さじゃん?
  確かに。
  作りを見直してみるとよいかも?
 ポイント
  UIとロジックの分割
  依存を注入する
  View以外(ViewModelやModelなど)がAndroidに依存していないか?
 テストにLiveDataが出てきた場合?
  argmentキャプチャが大事
  詳細は資料にて。
 RxJavaは?
  トランポリンとかある

感想

TDDについて非常にわかりやすく説明して頂けて感激。 特に実際にイメージが湧くようにコードを書いてくれたのがすごいよかったなぁ。

お話を聞いていて、結局はシンプルかどうか?というのが大事なポイントの一つなんだろうなぁと思いました。
テストの書きやすさの大きな要素の一つがシンプルだと思います。
思慮にもある通りテストが最も根本にあるので、
テストが書きやすい(書ける)ということは価値の高いプログラムなのだろうと思います。

これは実際に試してやってみたくなったので、是非やってみたい。

18:30 Google Play Consoleのリリーストラックを有効活用してリリースフローの最適化を行った話

資料。


解決したかった問題
 リリースマネージャーという役割が大変
  周りとの調整が大変
  単純に作業が多い

対策
 リリースマネージャーを二人にした
  分担にしたので作業は楽になった
  が、二人にしたのでコミュニケーションコストが増えた

その後
 スケジュール調整の問題は解決してない
 リリース期間が短いので価値検証期間が回せてない

根本原因
 原因は人間に機械をあわせていた
  自動化はしていたが、トリガーは人間。
  つまり人間側がボトルネックになってしまっていた
 だから、機械に人間が合わせるようにした

変えたこと
 毎週勝手にリリース作業が走るようにした
  最終的な判断だけ人間がやる
 段階公開の廃止によりリース期間を短縮した

リリース前レポートについて
 メールが届くらしい
 ただし時間がかかったり、ラグがあったりするらしい。

定期リリース予定から遅れるけどどうしてもリリースしたいものが出てきた
 主動でリリースできる仕組みを用意して回避した

クローズドテスト版を使うことで全社員が気軽に触れるよにうなった
 これいいなぁ
 弊社は小さい会社なので不要だけど、ある程度の規模がある会社では良さそう。

感想

自分たちのチームが抱えている問題を的確に把握して、
その対処を工夫して動いたのに感動。
また一度だめでも別の方法でだめな点を潰して良い方向に持って行けているのがスゴイなぁ。

リリース前レポートは自分もリリース前によく見ていて、
単にクラッシュしてないねーという使い方のみ。
それでも一度だけそこで問題に気付いて対処できたので結構良い仕組みだと思う。
APIとかでもって細かく結果が知れると良いかもというのは同意ですが。

このリリースフローの改善はエンジニアのツラさを軽減するのもそうだけど、
ユーザーに価値を定期的に素早く届けるという点にも効果がありそう。
一つの大きい機能開発をしていると小さいバグフィックスなどがおざなりになるので、
毎週リリース予定があると次回はどうする?という会話が自然に発生して対処できそうな気がしました。

終わりに

2日目は懇親会は無く、びっしりとセッションを聞いて来ました。
RSGTのときもそうだったけど、スポンサーブースに行かなかったなぁ。
ブースの人と話すのが億劫になっていたというのもありますが…。
(服屋の店員に話しかけられるイメージw)

というわけで初DroidKaigiの感想記事でした。
規模や仕組みの都合上しょうがないのですが、
聞けなかったセッションで「これは聞きたかった!」というのがいくつかあったのが残念。
あとで動画が見れるという噂を聞いたのだけど、
公式からは特になにも無いので半信半疑。
行けなかった知人や会社のチームのためにも動画があると嬉しいです。
(不参加の人は見れないかもですが…)

全体を通して思うのは、やはり熱量が凄まじいということ。
カンファレンスから得られる知見や人脈、楽しさもそうですが、
自分が興味あることに対して同じように興味ある人から貰えるエネルギーというのは素晴らしいものです。

まだまだAndroidを始めたばっかりの自分ですが、
なにかしらでこういった熱量を伝える、発信できるような事ができればと思います。
まずは現場と自分にちゃんとフィードバックするところからですね。

DroidKaigi楽しかった!
スタッフ、登壇者の皆さんどうもありがとうございました!
皆さんお疲れ様でした!


最後に宣伝です!
平成の情シスおかしんさんのご厚意により、
技術書典6は委託という形で技術書の頒布ができることになりました。ありがたい!
私は「はじめる技術 つづける技術」というタイトルで、
何かを始める時、続ける時の工夫や事例などを書いたノウハウ本を出します。

おかしんさんはゼロトラストアーキテクチャについての本ということなので、
こちらもぜひよろしくお願いします!

ブース番号などの詳細は決まり次第、告知していきます。
またハッシュタグ#はじめる技つづける技術でもいろいろ呟いていきますので、よろしくお願いします!