DroidKaigi 2018 に参加してきました。

droidkaigi.jp

2/8, 9で開催された、DroidKaigi 2018に参加してきました。

前回は、DroidKaigiアプリへのコントリビュートだけで、現地には行けなかったのですが、
同僚の根回しのお陰で、会社のお金で参加できました!(「来年からは、スピーカーじゃないと金出ないですよ?」と脅されましたがw)

雪のせいで、ちゃんとたどり着けるのかが不安でしたが、予約していた高速バスは無事運休になり(キャンセルする手間が省けた)、
朝の6時台の新幹線に乗って、10時には余裕で着席出来ました。
(建物の入口を探して、ちょっと迷いましたが。。。建物デカすぎ。)

今年も、事前にアプリのコントリビュートは出来ましたが、この3件だけ で、あんまりインパクトのある修正はできなかったなーという反省はあります。
ただ、気がついたら私の作った danger-checkstyle_format が使われていたのは嬉しかったです。 https://github.com/DroidKaigi/conference-app-2018/pull/219#issuecomment-357939250

全体的な感想

  • お祭り感があって、とりあえず最高だった。(語彙
    • セッションごとの民族大移動も、今思えば楽しかったようなw
  • スライドに出てくるサンプルコードは、ほとんどがKotlin。(Javaもいくつかは見かけた)
    • Kotlinやっとかないと、、、という焦りは覚えました。
  • アーキテクチャ系の話になると、Dagger2やRxJavaが当たり前に出てくる。
    • これも、やっとかないとついていけなくなる、、、という焦りが。
  • 聞きたいセッションが同時間帯にいくつもあり、体が足りない。
    • あとで動画は公開されるそうですが、いつでも見れると思うとなかなか。。。
  • 1日目のアフターパーティーで初めましての人と、そのまま飲みに行け、次の日にはセッションの合間に喋れた。
    • ただ、2日目のスピーカーは、顔と名前が一致してないので、風船つけててもどう声をかけていいのかわからない。。。(コミュ力。。
  • アーキテクチャ系のセッションを多めに回りましたが、唯一の正解はなさそう。
    • 当たり前かもですが、Android Architecture Componentの登場も決定打にはならない。

あとは、個別のセッションの感想メモ。

ウェルカムトーク

久々(始めてかも?)の大規模なカンファレンスでした。
オープニングのアニメーションがちょーかっこいい。

Kotlinのカンファレンスを日本でやるらしい。やっぱり、Kotlinは熱いっすね。

Kotlinアンチパターン

Kotlinアンチパターン

Kotlinは、言語仕様的なところはちらほら見てますが、がっつり実戦投入したことはないので、とてもためになったセッション。

実際に使い始めると、このへんで困りそうなので、そのときに見返すべきですね。

全般的に、Kotlinは表現力が高いというか、いろいろ書き方があって、うまいこと使いこなせれば便利だけど、下手なことをすると可読性が下がりそうな印象。
やるときは、メンバー間でいろいろと事前学習、共通認識の作成が必要な気がしました。(コーディング規約とか)

Android アプリの中を覗いてみよう

DroidKaigi 2018 // Speaker Deck

やる場合は自己責任で。

大体は知っていた内容でしたが、改めて最新の情報がまとまっていたので良かったです。

やはり、「Androidのコードは覗かれる前提で作る」というのが大事ですね。

Android における Model-View-Intent アーキテクチャ

Android における Model-View-Intent アーキテクチャ // Speaker Deck

MVIという、あまり聞いたことが無かったアーキテクチャの話。

Twitter見てても、やはりFluxと概念が近そう。

RxJavaの知識が足りなくて、ついていくのがやっとでしたが、処理の順番にうまく説明してもらったおかげで、逆にRxJavaの勉強になった気がします。(subjectをプロキシとして作ったり、autoConnectでUIの死に対応したり。)

やはり、Kotlin + RxJavaの表現力というか、きれいに書ける感じがすごい。

責任の分割がうまくされていて、慣れてしまえばうまくいくのかも?と思いますが、学習コストはけっこう高そうな印象。
テストは書きやすそう。

NavigationやSnackBarの表示方法などのデメリットは、MVVMで普通に作ってても感じるところなので、MVVMにも近そうな印象を受けました。

うちの会社でこれをそのまま取り入れるのは難しそうだなーと思う一方で、部分的に取り入れることもできそうな印象を受けたので、もうちょっと理解を深めてみたいところ。

まだAPI定義管理で消耗してるの?〜Swaggerを用いた大規模アプリ時代のAPI定義管理とコードジェネレート〜

まだAPI定義管理で消耗してるの?〜Swaggerを用いた大規模アプリ時代のAPI定義管理とコードジェネレート〜 // Speaker Deck

いい感じの煽りタイトル。

Swaggerは、軽く触ったことがある程度でしたが、あまり"コードの自動生成"を好きになれず、
そうなると、あまりメリットを感じられずに逃げた経験あり。

ただ、今回聞いていると、コードの自動生成も悪くない気がしてきたので、機会があれば実戦投入してみたい。
Javaで、Retrofit+RxJavaでいい感じのインターフェースを生やしてくれてるっぽいし、ValueObjectはふつーに作ってくれるだろうし。

手軽に作れるモックサーバの方は、なるほど?と思う反面、データの種類によって到達できる画面が違う、とかはどうするんだろう?とは思いました。リストのアイテム数も2以上に出来ないっぽいですし。
このあたりは、個人のアプリで一回やってみる必要がありそうです。

FOLIOさんでは、マイクロサービス+BFF(Backend For Frontends)という構成だから、という部分もありそう。
特に、ワークフロー周りではそれを感じました。

MVVMベストプラクティス

MVVMベストプラクティス // Speaker Deck

MVVMの案件を外部から見ていたことがあるので、「実際に作ってみると...」という部分は、完全に同意でした。

実際の開発の現場だと、「テストコードを書いて、メンテしていく暇がない」というのは、残念ながらよくある話で(スキルが足りないのが一番の問題ですが。。。)、とはいえ書かないにしても「テスタビリティの高いコードを書く」ことを指標にするのは確かに良さそう。

他の発表でもあったけど、Repository?Model?UseCase?がObservableを公開しつつ、"コマンド"を外部に公開するってのが良さそう。
ViewModel側では、DataBindingのObservableFieldとする必要がありそう。

ダイアログとか、画面遷移はたしかに悩む。
Navigatorは、Daggerが無いときれいにならない印象があるので、やっぱり早急にDagger2の学習が必要。。。

RecyclerViewについては、なるほどなーと思う部分と、あまり理解できなかった部分があるので、やっぱり一回ちゃんと実践してみる必要がありそう。
他の発表でもあったけど、とりあえずKotlinのsealed classは便利そう。これだけでも、Javaをやめたくなった。
RecyclerView関連のライブラリは食わず嫌いしてたけど、使ったほうが便利そう。

複数のViewModelが親子関係になるのは、やっぱりやばそう。
単一のデータソースを、複数のViewModelを見るのが良さそう。それぞれの生存期間をちゃんと考えないとですね。
(DroidKaigi関係ないですが、 iOS/Androidアプリエンジニアが理解すべき「Model」の振る舞い をまた読み直そうと思いました。)

マルチモジュールのすヽめ

DroidKaigi 2018で「マルチモジュールのすヽめ」という内容で発表して来ました - アナログ金木犀

興味はあるけど、なかなか実案件で投入できていないマルチモジュールの話。

いままでは、レイヤードアーキテクチャの層ごとにわけて、間違った依存を防ぐため、という意識が強かったのですが、機能単位でもわけるというのはなるほどなーと思いました。
このへん、Annictという使ったことのあるサービスを例にしてもらえたのは分かりやすかったです。

DataBinding周りのつらさは把握してなかったですが、もうすぐ解消されるのであれば実戦投入しやすいし、素振りを始めないと、、、という機運。

いままでは、モジュール分けたら未熟なチームでは学習コストが高すぎるのでは?という躊躇もあったのですが、依存関係を明確化して強制する、というメリットも知れて、弊社でも導入したほうがよいのでは?と思い始めました。

アフターパーティー、そして二次会?

顔の広い同僚のおかげでスピーカーの人とちらっと話せたり、
業務委託?で数年前に来てもらっていたエンジニアの紹介で企業の人と話せたり、
数年?前に転職してしまった人と久しぶりに話せたり、
初めましての人と喋って、そのまま飲みに行けたり、いろんな人と交流できました。

あまりスピーカーの方とは話せなかったのは残念でしたが、一人でぼーとしてる時間はほとんど無かったので良かったです。

Day.2

Android Studio30分集中超絶技巧100選

Android Studio30分集中超絶技巧100選メモ DroidKaigi 2018 #DroidKaigi #DroidKaigi_room3 · GitHub

BuriKaigiぶりの山本ユウスケさん。

UpsourceなどのJetBrains関連製品の話は、BuriKaigiで聞いていた部分でしたが、それ以外のIDE機能の部分はすごかったです。(語彙

印象に残ったのは、下記の通り。

  • ウィンドウの操作などは、いつもトラックパッドでしていたのですが、そんなに複雑なコマンドでも無いので、覚えて活用していきたい。
  • あらゆるポップアップはインクリメンタルサーチできる
  • Cmd + F12の構造ポップアップは、Eclipseでは常時表示させてましたが、ASでは見つけられてなかったので、検索ばかりしてました。活用せねば。
  • Ctrl + Gや、option + ↑などの選択範囲系のは活用の機会も多いと思うので、使っていきたい。
  • XocdeやAtomなどのエディタも常用している関係から、すべてのコマンドを覚えることは出来ないだろうけど、Shift + Cmd + AやCtrl + Tなどの起点となるコマンドは覚えておき、いろいろと活用していきたいです。

Surviving a discontinuous world

Surviving a discontinuous world // Speaker Deck

名前とか覚えるのが苦手なのですが、声を聞いて dex.fm の人だと思い出しました。

たしかに、Androidアプリの開発においては、いろんな非連続性があり、正しく動くアプリが作りづらい気がしています。
また、それを下手に回避しようとすると、プログラムがとっちらかって、保守性の悪いコードになってしまう。

RxJavaやAACのViewModel、EventBusなどを使って、いくつかの問題は解決できそうですが、学習コストが高そうだったり、使ってもそこまできれいに書けない場面もありそうな印象。
ただ、こういった不連続性があることを理解しておくことが大切だなーと思いました。
特に、他のプラットフォームに慣れた人とかは、陥りやすそう。

Relay Activityのところでは、プロセスは死んだけど、途中のActivityから復帰する場合がある、ということを知り、自分が勘違いしていたことに気づきました。
また、Emulatorやadbコマンドを使えば再現できることも学べたので、不安なときやCrashログから再現させるときは試してみようと思います。

詳解 Android Auto - 使い方からそれを支える技術まで

詳解 Android Auto - 使い方からそれを支える技術まで - // Speaker Deck

普段から車に乗るので、興味はあったAndroid Autoの話。
途中まで部屋が暑かったし、登場人物(音楽アプリ、Autoアプリ、Systemとそれぞれの中のクラス)が多く、理解しきれない場面もありましたが、概要は理解できた気がします。

Messageの部分では、CarExtenderという拡張があることを知れて、アプリ側としてこれだけは対応しておく、というのもありかも?と思いました。(Android Autoを使っている人がどれだけいるのか不明ですが。。。)

むかーし、 カーナビもどき なアプリを作ろうとした経験があるので、いまからやるのであればAuto互換みたいなアプリを作るべきなんだろうなーと思いました。まぁ、DrivemodeとかAuto自体を使えよ、という気もしますね。

Dagger2を活用してAndroid SDKの依存関係をクリーンにする

Dagger2を活用してAndroid SDKの依存関係をクリーンにする // Speaker Deck

サンプルリポジトリ

GitHub - kr9ly/dagger2-sampleapp

たしか、前説の間で「初参加で初登壇」と言っていた記憶があります。強いですね。(私は日和りました。。。)

Dagger2の話でしたが、一部は理解できましたが、一部はちゃんと理解できなかったと思います。
資料やサンプルを見直す必要がありそうです。

理解できた部分でいくと、Contextの処理をwrapしたクラスを作るってのは良し悪しだなーと。
ただ、下手なメソッド使われるよりは、制限つけたクラスを渡すというのはいいなーと思う一方で、作るのはめんどいなーとも。

すばらしきGraphQLのSEKAIへようこそ

すばらしきGraphQLのSEKAIへようこそ // Speaker Deck

アイコンしか見たことなかったので、どんな奇抜な人かと思ってたけど、見た目は普通の人でした。

GraphQLは気にはなってるけど、サーバ側の負担が高そうな印象があり、外部公開しない(開発アプリ用のサーバサイド)APIという案件が多い中では、あまり使えないかなーと思ってました。
今回は全体感の話と、クライアントサイドの話だったので、そこの不安は残ったままですが、クライアント開発者としては「面白そう」と思えました。

Schema-Driven Development(SDD)は確かに大事だなーと。
個人で小さいものを作っていても、数カ月後には忘れているので、きちんと定義しながら開発を進めるというのは大事ですね。

GraphQLは、取得系の処理が柔軟に記述出来るそう。ただ、更新はそんなに強くないとのこと。
このあたり、アプリの特性に合わせて、SwaggerやgRPCなどと使い分けて行ければ良いのかなと思いました。

GraphiQLというIDE的なツール?は便利そう。補完を利用しながら、リアルタイムで結果が見れるっぽい。

Relayというライブラリは面白そうですね。
View Componentとqueryを同じ場所に書くというのは、ある意味スマートUIとも言える気がしますが、面白い解決方法という印象。

Android Things codelab / Android Things であそぼう

  • 認証と認可と君と / The Triple-A: Authentication, Authorization, and Android
  • All you need is isolating the domain (How to apply DDD to Android Application Development 2)
  • 体育会系女エンジニアの孤独なアプリ開発教室

の3つで悩んでたら、ちょっと興味はあったAndroid Thingsのハンズオンに捕まりましたw

たしか、「5分で終わるよ!」と言われた気がしましたが、さすがに5分では終わりませんww

Android Things であそぼう!

こちらの機材が用意してあって、Android Studioから利用できるサンプルを順次試していく形。
全体の電力消費とかはそれなりにでかいかな?と思いますが、Androidの開発の延長線上で、物理世界とインターフェース出来るのは面白いですね。

おみやげにRainbow HATを頂いたので、家にあるRaspberry Pi 3と組み合わせて、ちょっと遊んでみたいですね。

ウィンドウサイズの変更に強い堅牢な画面の構築

ウィンドウサイズの変更に強い堅牢な画面の構築 / DroidKaigi 2018 // Speaker Deck

Surviving a discontinuous worldにつづいて、Androidのつらい部分をどうにかする話。

画面回転だけではなく、マルチウィンドウが当たり前になってきつつあり、対処が必要なアプリが増えてくる印象。

fitsSystemWindows はあまり気にしたことが無かったですが、NavigationDrawerだとステータスバー部分も描画しているのは、これをうまく使っている、ということなんですね。
たしかに、雰囲気で使ってしまっています。

二つ目は「構成の変更時の画面の状態保持について」。
受託でやる際には、いろいろな問題があって縦固定にしてしまうことが多いので、configChanges使っておけば?とか雑に思ってましたが、たしかにリソースの切り替えなどを考えるとActivity/Fragmentは再生成されるべきですね。

onSaveInstanceStateと、setRetainInstance(true)なFragment(AACのViewModel)のそれぞれのメリット・デメリット、使い分けには「復元が可能なのか」を考える、といったことがきれいに説明されてたのはありがたい。
ちゃんと使い分けていかないと、と思わされました。

マルチログインの実装方法

droidkaigi-2018 // Speaker Deck

サンプルは GitHub - yuyakaido/Android-Blueprint

TwitterInstagramなどで出来ている、アカウント切り替え機能をどのように実装するかの話。

個人的にはあまり使ったことも無かったので、想定されるバグなどが事前に知れてよかった。

設計方針としては、アカウントを透過的に操作できる層を追加して、そこでの切り替えをしっかりやる、というイメージかと。

ここでもDagger2をうまく利用していたようなので、やっぱりDagger2をやらねば、、、と再認識しました。

Gradleプラグインを作って開発効率を改善しよう

最後のセッション。

個人的に、Gradleプラグインを使って最低限品質の向上とか、プロジェクト間での便利機能の共通化に興味があるので、事前にスライドも読んでました。
結果としては、スライドに書いてあった情報がほぼすべてだった(スライド単独でもわかりやすい)ので、聞かなかったら聞かなかったかなぁともw

Plugin自体は簡単に作れそうで、公開も簡単そうなので、どこかのタイミングでやってみたいな。と思いました。
(おそらく、Android Plugin DSL Referenceや、groovyの記述周りで詰まりそうではありますが。。)

最後のセッションということで、mhidakaさんに事前に「いい感じに締めておいて」的なことを言われて、実際に発表後に締めていたのは単純に、すげぇな、と思いました。

期間中に書いていたメモ

あとはメモです。

# DroidKaigi 2018

## Day.1

## Kotlinアンチパターン

普段使ってる人が半分ぐらい。

リリース済みの巨大なアプリのフルリニューアル。
最大11名という大人数の開発チーム。

### lateinitと

Kotlinでは、基本的に初期値が必要。(Javaはnullが初期値)

Androidでは、onCreate以降に初期化。強制unwrapなどが必要に。

アンチパターン:通信後に得られる情報をlateinitにする。
通信中にonClickListenerなどでアクセスしてしまうなど。

解決策の例:Nullableにする。

isInitializedが導入された。
もともと、テストコード用に導入された。
プロダクションコードでの仕様は避けたほうが良さそう。

### スコープ関数

let/run/also/apply/withの5つ。
null関連の制御に便利。
初期化処理をまとめる。

アンチパターン:apply内でプロパティアクセス形式の処理を書く
ローカル変数を定義すると、アクセス先が変わる。

解決策の例:apply内では関数呼び出しにする。
2:this必須というルールにする。alsoと似た感じになってしまう。
3:apply禁止。alsoを使う。

### NullableとNonNull

アンチパターン:Nullableのままデータを引き回す。
いたるところでnullチェックが必要になる。
すべてNonNullにするために無効なデータを入れる。

解決策の例:「nullが何を表すか」で処理するレイヤを決める
nullではなく、例外を投げる、別クラスにするなど

### data class

アンチパターン:インスタンス生成用のメソッドで、制約を保証したい。
data classにはcopyメソッドがあるので崩壊する。

解決策の例:なんでもdata classにしない。

### interfaceとabstract class

アンチパターン:Baseクラスを肥大化させる。
解決策の例:「継承よりも異常」より、interfaceのデフォルト実装でも良いかも。

状態を持ちたい場合も、class delegationを使うと出来る。

### トップレベル関数と拡張関数

ファイルに直接関数を書ける。
クラスに関数を追加する事ができる。

アンチパターン:一般性がない、局所的にしか使わないメソッドを追加する。
アンチパターン:公式でありそうなのに、雑に実装。

チーム内で拡張関数を作る基準・間隔を揃える。
interfaceのデフォルト実装で、スコープを限定する。

### lazyとcustom getter

lazyは一回、custom getterは毎回計算。

解決策の例:値の性質に応じて、適切に使い分ける。

delegated property
プロパティのget / setを別のクラスに移譲出来る。

### Fragmentとlazy

アンチパターン:FragmentのViewをlazyにする
onCreateViewが複数回呼ばれ、古いViewを参照し続けてしまう。

解決策の例:lateinitを使う。

### custom getter

アンチパターン:値を取得する過程で副作用がある場合。
2:計算量が多い

呼び出す側からは、通常の変数と同じに見えるため、性能劣化しやすい。

custom getterを使いすぎない。

### custom setter

変数の移譲

アンチパターン:常に必要ではない処理を書いてしまう。
それにより、値だけを変えることができなくなる。

更新用の関数を公開する。

### last one

無理やり使わない。
operator overload, infix, tailrec
チーム開発では、わかりやすさも大事。

## Android アプリの中を覗いてみよう

内容を試す際は、自己責任で。

Androidアプリの中身は、簡単に覗ける。

APKを用意する。
ミラーサイトから入手 or 端末から入手
APK Downloaderというサイトも有る。自己責任で。
APK Extractorというアプリで、端末から抜き出せる。

APKを解析する
ASでBuild -> Analyze APK
中身を見れる。dexファイルの数とか。

APKTool コマンドラインから実行できる。
AndroidManifestがそのまま参照出来る。

unzip/dex2jar/JD-GUI
拡張子をzipにしてunzip。
dexファイルをdex2jar
jarをJD-GUIで見れる。

kotlinのライブラリ?ランタイム?が入ってる。

著作権法違反:
見たコードをそのまま使う。
リソースの流用。
非公開のAPIを叩く。

アプリの実装をブログで解説するのは、かなりグレー。

Androidアプリは覗かれる前提で作る。
会社の重要なビジネスロジックは書かない。

英語版があれば、そっちを使ったほうが、そのままコードで利用されている可能性がある。

## Android における Model-View-Intent アーキテクチャ

AさんとBさんが会話する=AさんのInput -> BさんのOutput
人とAndroid端末も同じ。それをアーキテクチャに落としたもの。

user -> intent -> model -> view -> user...
view(model(intent()))

ユーザの操作・初期化処理などをTasksIntentに各クラスをつくる。
sealedクラスの中にdata classとobjectで作る。

Fragmentの中に、Observableを返すintentsメソッドを作る。
mergeでつなぐ。
intentから、actionを作る。whenでマッピング出来る。

switchMapであれば、前の実行をキャンセル出来る?ネットワークの複数リクエストが不要な場合に便利そう。
startWithの位置が大事。

1つのクラスがあれば、1つの画面を作れるようにしておく。
SnackBarの表示についてもbooleanプロパティとして保持する。
初期値も定義しておく。

StateとResultをもとに、new stateを作るのがreducer

画面を変更するメソッドは、renderにしかない。

side effects
複雑性のもと。スコープを制限する。
intentsを作るところ。ただし、UIの変更は禁止。
Processor部分。ただし、UIの変更は禁止。
reducer部分。ただし、データの読み込みは禁止。stateにあるはず。

user interfaceの影響を制限する。ViewModelでは、Androidの世界と切り離す。

イベントが詰まったあとに、onStop。
ViewModel以降のやりとりがonStopで止まらなければ、Stateの更新は進む。
onResumeで再描画出来る。(renderはべき等)
AACのViewModelのスコープを前提としている。

Rxだと、sourceが消える(UIが死ぬ)と、Stream全体が死ぬ。
ViewModel内のsubjectをプロキシとして作る。
subscriberもUIの死で死ぬ。autoConnect(0)を使う。
reply(1).autoConect(0)で、最新の状態を再度受け取れる。

Fragmentでは、viweModelをlazyで初期化。
onStartでsubscribe
CompositeDisposableに入れておく。
onDestroyでdispose
subscribeしてから、intentを投げる。

initialはtake(1)でmergeする。

テスト。
UI層は、それぞれEspressoなどでテスト出来る。
ViewModel内は通常のJavaとしてテスト出来る。

oldergod/android-architecture にサンプルあり。

デメリット
・クラスの数が増える。
・Rxの知識が必要。
・Navigation
・SnackBar。booleanをいつ解除する?Timerで消している。

メリット
・処理の責務が明確。問題が発生したときの切り分けがしやすい。


## まだAPI定義管理で消耗してるの?〜Swaggerを用いた大規模アプリ時代のAPI定義管理とコードジェネレート〜

FOLIOという証券会社。

暗黙知を残さない。形式化する。
暗黙知を書き出す。→ドキュメント化。
事例の共有。→サンプルデータ。

API定義を管理するメリット
認識齟齬をなくす。

Swagger / Protocol Buffers / api blueprint / Excel

Swaggerを用いた管理
OpenAPI InitiativがAPI記述のためにSwaggerを採用

REST APIの設計、ドキュメント化、テスト、デプロイまでをカバー
Core/Editor/UI/Codegen

Editor
API定義をレンダリングしながら編集できる。
必須と任意のプロパティを定義できる。
exampleデータは書いておいたほうがよい。
type+formatで型が決まる。

UI

コードは機械的に生成しましょう。(ミスを無くすため)
Java+Retrofitだけでなく、Kotlinも使える。(完璧ではない)
codegenを使うことで、工数が削減できる。
ドキュメント通りの実装が出来る。

Kotlinであれば、NonNullなども反映される。
Javaであれば、Retrofitのinterfaceも出てくる。ただし、Kotlin版は微妙。

codegenでモックサーバも作れる。
サーバの実装がまだでも、アプリが作り始められる。
サーバに反映されても、アプリは古いモックで動き続けられる。
デメリット:リストのアイテム数は常に1つ

FOLIOでの運用
Microserviceで運用してる。BFFでまとめていて、スマホはそこと通信している。
BFF開発者がPRを出し、スマホエンジニアがレビュー。
スマホエンジニアが意見をPR、BFFエンジニアがレビュー。

masterにタグを切る。
該当のタグをsubmoduleとして参照している。
BFFは、フロントに向けて作っている。

編集時は分割 -> multi-file-swagger。
API定義のバリデート -> swagger-cli
pre commitでチェックしている。

gRPC+ProtocolBuffersであれば、あまりいらない。
SwaggerUIは使える。
Swagger用のJSON定義を出力、Swagger UIで見る。

proto3でrequiredがなくなった。
互換性を保つため。
BFFがあるから、型が欲しい。
広報互換性は、v1, v2などで管理できる。

Flowtypeの型が生成出来る。
iOSは自動生成の結果を利用しやすい。

codegenのカスタマイズ
XxxClientCodegen+mustacheのテンプレート
生成時のコマンドラインオプションで、テンプレートを指定できる。
swagger-codegenのresources以下に言語ごとのテンプレートがある。
FOLIOでは、kotshiを使ってる。

codegenのリリースサイクルは遅め。新しいものはmasterブランチ。
Javaはいい感じ。Kotlinはまだ発展途上。

## MVVMベストプラクティス

カカクコムの新規事業担当。

VMが大きくなりがち。
RecyclerViewとか。
VMが複数存在したり。
反省を踏まえて、ベストと思われるプラクティスの紹介。

### 関心の分離

VMが太ってしまう。
再利用性・保守性の向上。
PDS

#### MVVMにおける、関心の分離。
V+VMがP、MがDomain。

Viewはデータの表示・イベント。
ModelはV+VM以外。
ViewModelは、Viewの状態を抽象化して保持。ModelとViewの接続。

ViewはVMを持つが、逆は持たない。
VM -> Modelの状態変更を要求。

Androidにおける実践的な方法
・テスタビリティを基準として使う
ViewModelのUnitテストが出来るかを基準にする。
テストを書かなくても、指針としては使える。
依存するオブジェクトは、Mockへの差し替えを可能にする。Dagger2など。
・ViewとViewModel
DataBindingを使う。
Viewに発生したイベントを、ViewModelに通知。
メソッド参照を使うと、Viewが引数に渡ってしまう。Lambdaで切る。
ViewModelはViewに状態を公開。
カスタムセッターを使ったり。Picassoに画像URLを渡したり。
Kotlinであれば、拡張メソッドを使える。
・ViewModelとModel
Modelの状態変更を要求する。
ViewModelがModelの状態を監視する。RxJavaなど。

例:設定画面。SharedPreferencesにデータが保存されている。
悪い例:VMの中でSharedPreferencesを読み取る。
→間にRepositoryを挟んで、VMはRepositoryの変更を監視する。
RepositoryではPublishSubjectを使う。外部にはObservableで公開する。
VMでは、初期化時にsubscribe。依頼があれば、repositoryにloadを依頼する。
別の画面でSharedPreferencesが変更された場合などに強い。

・ダイアログ表示・画面遷移
ViewModelからはトリガーを引く。
Navigatorを使う。
ActivityScopeなインスタンス。
・Context
機能が多すぎるので、各層で必要になってくる。
ラッパーを作ったりして、ViewModelでのみ使って良いメソッドを制限したほうが良い。特に、大人数の場合。

#### RecyclerView

・基本的な実装
Viewの種類が複数あるパターン。
sealed classでViewTypeを表現。
画面全体のVM。それぞれのVM。

ActivityのonCreateでAdapterを生成。
AdapterにModelを渡す。custom setterを利用する。
Adapterが、行ごとにMVVMを作る。
BindingをViewHolderで持つ。

・変更検知
FABで新しいタスクが作られる想定。
まるごと更新(notifyDataSetChanged) -> 変更のアニメーションが出来ない。
差分検知には2パターン
 ・ObservableListを使う。
 ObservableArrayListという実装がある。
 callbackで変更を通知できる。
 Adapterでcallbackを登録。
 ObservableListには、onItemRangeInsertedなどのそれぞれのメソッドがある。
 Adapterでハンドリングする。
 ・差分検知
 差分を自分で計算する。
 Rxとかで、新しいリストが流れてくるだけであれば、こっちのやり方が楽。
 DiffUtil support libraryに入ってる。 参考:http://blog.takuji31.jp/entry/kanmoba17
 Epoxy というのもある。

・実装の効率化
Adapterはボイラープレートが多い。
いくつかライブラリがある。プロジェクト要件にあったものを。
カカクコムの1つのプロジェクトでは、Epoxyを使ってる。(それはflux)
Airbnbが開発してる。

#### データフロー

ViewModel間が複雑に依存する。親子関係など。

例えば、メニューにタスク数を表示する場合。
1つを完了させると、ItemViewModel->Repository->WebAPI
ItemViewModle -> ViewModelにデータを渡す。

Repositoryだと、Singleで結果を一回だけ流すように作る。
Item側では、repositoryのcompleteを実行。parentに結果を渡す。

ViewModel間でのやりとりを行うこで、データフローが複雑化。

改善方法としては、それぞれのVMが参照しているRepository(実態)を一つにする。
Repositoryから、Observableで公開。そこに更新を流していく。


## マルチモジュールのすヽめ

何故するのか。

複雑化してきている。
サブ機能も多くある。
ログイン・ログアウト機能、強制アップデート、お知らせ、ログ収集。
それをモジュールで分けてしまう。
サーバ側でマイクロサービスになると、APIのまとまりも分割されることがある。

波が来ている。
Instant Apps
Gradle Plugin3.0.0でパフォーマンスが上がっている。
KotlinのMultiplatform Projectではcommonモジュールが最低限必要。

個人的に。
レイヤードアーキテクチャー。
認証機能。他のAPIからもtokenが必要。domainに置けない。
別の認証モジュールを作って、認証の上位層から別のinfra層が取ってくる。

databindingとの相性が悪い。
少し前までは、そもそもできなかった。module側でbindingが見えない。
いまでも、dependenciesに重複して記述しないといけない。
解消されようとしている。
DabaBindingCompilerV2が正式リリースはされてないけど、存在はしている。
enableV2のgradle.propertiesへの追加が必要。

モジュールの分け方
・レイヤーで分ける
依存関係
・意味のあるまとまり
独立している機能を分ける。

おすすめ
意味 or レイヤー+意味

例えば、ユーザログはUI層でしか送らない、ということが制限できる。
主要機能が3つ以上の独立した者で出来ているなら、意味のあるまとまりで分けたほうがよい。
チームが未熟なら、強制力が働くのでよい。

Annictでの事例
ユースケースを洗い出し、何を実現しているかを考える。
主要機能以外をまずは切り出す。独立しているものを。
機能ごとの依存関係を考える。
次に、実装上の依存を考える。

New Moduleしたら出来る。
Androidに依存していないならJava Module、それ以外は

modulesディレクトリを作る。
projectDirを書き換える。

モジュール間の連携について

Case1: モジュールをまたがった情報の表示
たとえば、ホーム画面にいろんな情報を表示する。
Fragmentで分けて、attachしているだけ。
Fragmentは各モジュールで定義している。

Case2: 他のモジュールから情報を取得したい。
あるモジュールのAPIが、認証モジュールからトークンを取得する。
認証モジュールで取得サービスを公開して、そこから取得する。
View/Serviceだけを公開する。domainのものは使わずに返す。primitiveやDTO。

## アフターパーティー

弊社エンジニアのお陰で、Widgetの話をしていたスピーカーの方と話せたり、(ただし、発表は聞いていない。。)
2, 3年ぶりにあった人に紹介されて、UZABASEの方と話したり、
転職していった人の近況を聞けたり、
飲み物を取りに行ったところで偶然話し始めた人と、そのまま飲みに行くことになったり(次に続く)、
あっという間の時間でした。

## 2次会

同じ会社のAndroidエンジニアの誘いもあって、
愛知から夜行バスで来た方、富山大学を出て新卒でエンジニアしてる方、弊社Androidエンジニア、自分という4名で飲むことに。

今日のセッションの振り返りや、明日のセッションどこ行く?の他にも、
「新卒」ブランドは賞味期限があるから使えるときに使っとけ、という話や、
勉強会は懇親会が本番、とかって話をしてた気がします。

## Day.2

## Android Studio30分集中超絶技巧100選

メモは後で公開予定。
https://gist.github.com/yusuke/e30257656a78ca007627e0762a5a7fbc
Eclipse使ってる人はほぼいない。
Mac OS X 10.5+ を使うべき。
Power Save Modeを使うと、バッテリー効率が良くなる。
Cmd+1 -> Escで、プロジェクトペインとエディタを行き来出来る。
ポップアップは、typeすることで絞りこめる。
Shift+Cmd+F12でエディタだけに出来る。戻せる。
Window -> Store current --> Shift+F12
Cmd+Oで、* がワイルドカード。:数字で行数。
Ctrl+tabで戻れる。
Cmd+Eでファイル選択。
Cmd+7でstructureが表示。Cmd+F12でウィンドウ表示。
Cmd+Bで定義に飛ぶが、定義で押すと使ってる箇所を表示。
Option+Cmd+bでinterfaceの実装。
Ctrl+Gでカーソル増殖。
option+↑で選択範囲を拡大。
Ctrl+Tでリファクタリング系のメニューが出る。

## Surviving a discontinuous world

不連続性。Android開発における難しさ。
大体のプログラムは上から順番に実行される。
Androidでは、callbackとかのlambdaで順番にならない。
非同期の結果が返る頃に、画面が生きているかはわからない。

コードが直感的じゃなくなる。
事前条件(実行されるスレッド、画面の生存)を、つねに気にする必要がある。
再現性のないバグになりやすい。

### 非同期処理
ボタンクリック->非同期取得->画面の反映
暗黙的にActivityを参照しているので、処理結果が帰ってこなかったらリークする。

まずは手持ちで。
runOnUiThreadでUIスレッドで実行できる。
isDestroyedでActivityの存在を確認できる。if文。

RxJava or Kotlin Croutine
RxJava
先にデータフローを定義する。
disposableで、メモリリークを防げる。
Kotlin Croutine
コードが上から下に実行される。
非同期の場合に、コードが一時停止する。スレッドはブロックしない。
suspension pointで止まる。
launchの引数で、実行されるスレッド、ライフサイクルを定義できる。

### 画面回転

バックグラウンドスレッドの結果が、古いActivityに通知される。

AsyncTaskLoader
いまはそんなに使われていない?
AACのViewModel
FragmentのsetRetainInstanceを使ってる。

### シュレディンガー Activity
リスト->詳細の構成で、詳細でいいね押して戻ってくるなど。

2つのシナリオがある。
・Activityが再生成される場合。(リスト画面が死んでる)
一般的に、サーバから取り直すので、あまり問題にならない。
・Activityが再生成されない場合。
実装が必要。

・startActivityForResult
setResultで状態の変化を詰める。
onActivityResultで反映させる。
・EventBus
Activity間でEventを送受信。
いいねのタイミングで、Eventを送信。
死んでれば、再生成時にAPIアクセスなど。
・Persistent repository
local storageで保存しておく。
Google I/Oのアプリでやっている。
まっとうな方法だけど、結構複雑。

### Relay Activity
複数の画面で、1つのデータを作成する。
下書きデータみたいなものを、複数のActivityで作る。サーバには送らない。

singletonで、下書きデータを保持する。Application classで保持するとか。
ただ、問題が起こる。
バックグラウンドの際に、データが死ぬ可能性がある。ただ、Activityは復帰される。
普通のテストで再現させるのが難しい。
Emulatorで、DeviceMonitorからStop processを押す。
or adb shellから、run-asでkillする。

・startActivityForResult
データをお手玉していく必要がある。
・Local Storage
データを永続化する。
・Fragmentを使って、データを保持する。
Fragmentは嫌われているけど、現実的な解決策。


## 詳解 Android Auto - 使い方からそれを支える技術まで
https://speakerdeck.com/keithyokoma/xiang-jie-android-auto-shi-ifang-karasorewozhi-eruji-shu-made

Autoアプリを入れて、Auto readyの車に接続すると、ナビ画面に出てくる。
Audio, Messages, Calls, Navigationが主要機能。
音声入力で操作する。
電話とNaviは公開されているAPIが無い。

### Audio Framework

登場人物
App(media contentの配信), Autoアプリ, Android system

AppとAutoアプリはプロセス間通信。
MediaSessionで状態を管理。
MediaControllerで操作。sessionの発行したtokenを受け取る。permission的なもの。
MediaSessionがMediaPlayerに支持を出す。

appのMediaSessionから、AutoアプリのMediaControllerにプロセスを超えて通信する。

app側で、Serviceを作る。
その中で、MediaSessionを作る。(support libraryにある)
callbackを設定し、isActive = trueとする。
Binderを経由して、tokenを渡す。
tokenはParcelable

Auto側でActivityを作る。
ServiceConnectionでbind、onDestroyでunbind。
onServiceConnectedでbinder経由でtokenを取得。
MediaControllerを作成、prepareを呼ぶ。(ストリーミングであれば、ダウンロード始めたりしてくれる)

App -> System
MediaSessionManager->MediaSessionService
ISessionControllerが中継して、プロセス間通信をしている。
プロセスの片方が死ぬ可能性がある。DeadObjectExceptionが起こる。

プロセスが死ぬと、binderDiedが呼ばれる。
IBinder.DeathRecipientで検知。

...登場人物が多すぎて、メモ取れない。

MediaSessionManagerだけ、5系から。support libraryも無い。

Auto側で、プレイリストなどを表示することが出来る。
MediaBrowserService -> MediaBrowser
onGetRootで、どのプロセスから来たかがわかるので、そこで拒否できる。nullを返すと、拒否扱い。
署名を見て判断もできる。
app側が許可する一覧を持っている。base64の署名。
`__ROOT__`などの構造が定義されている。
MediaItemに、BROWSABLE/PLAYABLEといったフラグを持たせる。

onLoadChildrenは、同期でも非同期でもよい。
非同期の場合は、detachしてから、非同処理を行う必要がある。
searchで、検索も行える。

### Message

アプリ側のNotificationを、Autoアプリが受け取る。
NotificationCompat.CarExtender というものがある。
UnreadConversationに、既読用・reply用のPendingIntentを渡せる。
PendingIntentは、BroadcastのIntentにしておく。
conversationIdは、任意に決める。
reply用のPendingIntentにRemoteInputを渡す。Auto側が音声を詰めて返してくれる。
対応するBroadcastReceiverを作る。

Auto側では、NotificationListenerServiceを使っている。
StatusBarNotificationの形式で受信する。
carExtenderは、フラットに、文字列をキーに取得する必要がある。
messageも、Parcelableのリストが来る。

### まとめ

プロセス間通信。
Google Assistantも、似たようなことをやっている。


## Dagger2を活用してAndroid SDKの依存関係をクリーンにする

https://speakerdeck.com/kr9ly/dagger2wohuo-yong-siteandroid-sdkfalseyi-cun-guan-xi-wokurinnisuru
https://github.com/kr9ly/dagger2-sampleapp

Kodeinというのも出てきている。
DIを使う目的は、本来色々。
Androidにおいては、SDK周りの依存を切りたい。

ベタープラクティス集の紹介。

### @Scopeを活用する

代表的なのはSingleton。
@Scopeを使うと、スコープ管理が可能。

ViewScopeアノテーションを作る際に、@Scopeを付ける。

Subcomponentを使うのがらく。

...頭が追いつかなかった。...

Component分け
Component定義が1つで済むほうがよさそう。
Module内で処理を分ける必要がある。

### Context依存を切り離す

2つやり方がある。
Context自体を公開するか、そこを隠蔽するか。
プロジェクトに依存する。

### 画面遷移を整理する

画面遷移用のinterfaceを定義する。
Intent生成用のIntentBuilderを作ってしまう。

### Activity/Fragmentのコールバックイベントを整理する。

・AACのLifecycleを使う
・自前でコールバックを定義する

## すばらしきGraphQLのSEKAIへようこそ

https://speakerdeck.com/gfx/subarasikigraphqlfalsesekaiheyoukoso

Kibelaを作っているgfxさん。

Kibelaで、GraphQLを採用。
GraphQL rubyを使っている。
アプリはReactNativeを採用予定。GraphQLと相性が良い。

### Schema-Driven Development
APIとデータ構造の定義と、ロジックの開発を同時に進めること。
schemaをベースにコミュニケーションしやすい。
自然言語ではないので、変更箇所の検知がしやすい。

SDDで有名なもの。
Swagger, gRPC, GraphQL

他人・他チームとの界面はしっかり定義しておく必要がある。
そうしないと、あとから困る。

### GraphQLについて

クエリ言語。SQLと同じ領域。
WebAPIを想定している。
プロトコルはHTTP
内部APIとしても、外部APIとしても使える。

リソース取得系が非常に柔軟かつ強力。
更新は、GraphQLであるメリットは少ない。
Fileアップロードとかは、かなり難しい。

GraphiQL(ぐらふぃくる) GraphQL IDE
補完が効く。
GraphQLの仕様の中に、Deprecatedもある。GraphiQLで見れる。
ドキュメントビューアーもついている。

リクエストを見ると、レスポンスの構造がわかる。
計算が必要なカラムも、必要な場合だけ取得できる。(サーバに優しい)
intとfloatが区別される。
すべての方はnon-nullに出来る。

Mutation
自由に名前を点けられる。

Relay

1. GraphQLを前提としたViewFramework
2. Relay(1)がサーバに対して求める仕様であるRelay Server Specificationのこと。

これに従っておくのが無難。
Relay Connection
リソースリストのページング。RESTだと、特に指定が無いので、自由に作りがち。

クエリは手書きしろ、という設計意図を感じる。
GraphiQLで書いて、それをコードに貼り付ける。
クエリは静的に書いて、ビルド時にデータ型を作成する。

### GraphQL in Android

本番で使っているわけではない。
Apollo clientが有名。
クエリから、Javaコードを生成する。Kotlin対応はまだはじまったばかり。
ORMのように、コードからクエリを作るわけではない。
リクエスト・レスポンスクラスを生成する。
通信はOkHttpに依存。
viewと同じファイルに置きたいが、Apolloは別ファイル。Kotlin対応がすすめば。。?

JavaScriptであれば、Relay。JSそのままでも扱える。
View componentと同じ場所にqueryを書く。

Kibelaでは、TypeScriptとの相性が悪い。
発想は良さそうなので、そこは参考に出来る。

モデル・腐敗防止層という概念は不要なのでは?
(他の会社のAPIを叩く場合は別かも。)

スキーマの共有。
スキーマをエンドポイントで返す。
ビルド時にエンドポイントを叩いて取得する。

HTTPのステータスコードは複数のところが返す。(proxyとか)
GraphQLでは、処理が成功したら200。

まとめ

## Android Things

https://codelabs.developers.google.com/codelabs/androidthings-playground-jp/#0

## ウィンドウサイズの変更に強い堅牢な画面の構築

定義
画面回転・マルチウィンドウ

問題
レイアウト崩れ。マルチウィンドウの下側なのに、ステータス領域をとっていたり。
画面の状態が失われる。ロードが発生したり。状態が保持できていない。

考慮することが増えた
・幅・高さともに表示領域が狭いレイアウト
・通常と異なるシステムUIの配置。WindowInsets周り。

ステータスバーの一部が欠ける端末の登場など。

「ステータスバーの高さを取得する」は疑うべき。
fitsSystemWindowsをつかうべき。ただし、使うのが難しい。
FrameLayoutにfitsSystemWindows=trueのものが複数あっても、反映されない。場合もある。
自身・子Viewで、解釈をカスタマイズ出来る。DrawerLayoutなど。
オーバーライドしなくても、OnApplyWindowInsetsListenerで処理を横取りできる。
consumeしない、という選択肢もあるが、混乱を招く。
高さを取得しなければならない場合は、setOnApplyWindowInsetsListenerで取得する。

### 構成の変更時の画面の状態保持について

ウィンドウサイズの変更時は、Activity/Fragmentは再生成される。
新しい構成用のリソースを使用した表示にするため。
ゲーム、WebViewなど、仕方ない場合のみconfigChangesを使う。
Handling Configuration Changesに詳しく書いてある。
・onSaveInstanceState
シリアライズなどを伴うので、速度面が問題。
一部のViewは、自前で状態を保持する。
7.0以降で、大量のデータを保存すると、1MByte TransactionTooLargeExceptionが発生する。
toolargetoolというツールで確認できる。
・setRetainInstance(true)なFragment
シリアライズを伴わない。
AACのViewModelも、この方式。
・onRetainCustomNonConfigurationInstance は非推奨?
Android 2.xでは推奨されていた。

使い分けには、データの「寿命」を考える。
onSaveInstanceStateは、プロセスの破棄でも残り続ける。
setRetainInstance(true)は、Activityの破棄で消える。

targetSdkVersionを24にすると、TransactionTooLargeException

復元可能なものは、setRetainInstance(true)
ユーザの入力中の内容などは、onSaveInstanceState

これまでは、ほぼすべての画面でIcepickを使用していた。
Retainerというライブラリを作った。Icepick風に、状態保持出来る。

寿命の違う2つの状態
StateAwareViewModelを作った。
ViewModel側のテストで担保できる。(片方生きてる、両方生きてる)

## マルチログインの実装方法

サンプル https://github.com/yuyakaido/Android-Blueprint

eurekaの開発をしている。
テストおじさん→Rxのエラーハンドリング

Pairs本体には、マルチログインの機能は無い。

定義
複数アカウントで同時にログインできる。
TwitterやInstagramは出来ている。

会場内で5名ぐらいが経験者。

実装時の問題
・別アカウントのデータが見える。
グローバル変数や、状態を持つシングルトン
・データを上書きしてしまう。
データや非同期処理がアカウント単位になっていない
・コードが複雑化
アーキテクチャ的に考慮されていない

実装時の設計方針
Activity - ViewModel - Repositoryが一般的。ただ、これだとマルチアカウントだとつらい。
Repository以下をアカウント単位で管理するとよい。
ApplicationとAccountを明確に区別。
Applicationでは、Accountに依存しないもののみ。
各レイヤーのライフサイクルが異なる。
Dagger2などのDIコンテナを使うと、楽に実装できる。
ApplicationScope, AccountScope, PresentationScope(画面単位)
個人GitHubアカウントの、Android-Bluepirntでサンプルを公開中。

OkHttpClientも、AccountScopeで管理。

## Gradleプラグインを作って開発効率を改善しよう

build.gradleはGroovyスクリプト
JavaでもKotlinでも書ける
gradleファイルは、リモートにおける。gistとか。

Pluginというinterfaceを実装したら、それはPlugin。
メソッドは一つ。applyだけ。

設定を持つためには、ExtensionというJavaBeanを使う。
いつものandroid{}も、AppExtensionというExtension。
通例として、末尾が"Extension"というクラス。

afterEvaluateコールバック
設定値の反映とか、タスクを生やすとか。

タスクになっていれば、コマンドラインから呼び出せる。依存関係がある。

Android Plugin DSL Referenceというドキュメントがある。

applicationVariants.allで列挙、追加できる。

--stacktraceで、stacktraceが出るようになる。(デフォルトは出ない)
Androidプラグインの中身もデバッグできる?

buid.gradleから外に出すと、importが必要になる。

Gradle Plugin Portalに公開する。