DroidKaigi day2
前振り
Yahoo天気アプリ 雨雲の接近がわかる
スライドに背景画像あるの意図を共有しやすくなってそう
OpenGL
リファクタリングで10めも以上の高速化
基本的なことの積み重ね
前振りがわかりやすい
Java/Kotlin 遅い?
ART Android5.0からは改善が進んでいる
Kotlin のデメリットとして、実行コストが見えにくい
モバイルはそもそも大量のデータを高速に処理するのに向いていない
実行時間を多く使う箇所に限定して高速化(パレートの法則)
メモリは遅い(CPU と比較して I/O は遅い
メモリアクセスの無駄を排除し最適化する
メモリに保存するより、計算する方が速いこともある
メモリのコピーに気をつける
インスタンスの使い捨て(メモリを確保してしまう
隠れたコスト
出力データクラス、タプル、分解宣言
- インスタンスの使い捨てが発生している
- 書き込み先を引数で渡す out
- 出力インスタンスを使い捨てない
プリミティブラッパー
- Kotlin で区別しない
コレクション操作
asSequence 呼び出しコストがかかる
forEach などのベタ書きが良いケースもある
可変長+スプレッド演算子
配列のコピーが発生する
SpreadBuilder では、コピーして追加して、コピーする
計測する
コストを推測できるようになっておくと良い
メモリは遅い
アルゴリズムとデータ構造
ランダウ記法は十分に大きなn
メモリは遅いので、データ構造がアルゴリズムの計算量よりも重要なこともある
先入観で決めつけずに扱うデータ数によって結果は変わる
必要な正解性以上を求めない
必要な計算精度になっているか
ロジックの正確性はどこまで必要か
- 距離の計算
無駄な処理を省略する
境界条件を整理して必要な処理を明確にする
繰り返し行われる処理はないか
高速化のためにもコードの可読性を大切にする
標準の実装から外れてしまうことがあったら、
カプセル化して、影響範囲を最小限にする
計測して改善
Android Profiler
Java での表現を想像すると、メモリイメージもつきやすい
カプセル化というのがモジュール化においても繰り返されていたのが印象的
ここでいうカプセル化は単一責任、責務の分離の手段として
Bumblebee で聴くのは、音が混ざってやはりちょっと大変だった
権限の設定
ShareCompat が良い感じにしてくれる
使わない場合はフラグの設定が必要
画像の編集
ファイルフォーマットが変わる可能性がある
jpg -> png
画像を受け取るアプリではそれを想定してフォーマットの許可をする
ワイルドカードも使える
アプリのポリシーで受け取って表示できなくてもよければあり
そうでない場合は、ワイルドカードは避けて限定する
複数の画像を送る
SEND_MULTIPLE の action を受け付ける
Android の Action を MVI の StateMachine に絡められないか
まとめ
ShareCompat が優秀
ファイル共有は FileProvider
直接共有
共有アクションでシートのトップに表示される部分
ユーザの利用頻度は高く、アプリに組み込む価値が高い
動的なショートカットを作成して利用している
share-target のマニフェストを作る
ShareCompat.IntentReader で受け取る
どう作るべきか
- メッセージを出す時
- メッセージの通知を受け取った時
-
addCapabilityBinding("actions.intent.SEND_MESSAGE")
でメッセージを出す時 - ShortcutManagerCompat
- pushDynamicShortcut でショートカットを作る
- removeDynamicShortcut でショートカットを消す
- 23までサポート
共有シート
カスタムの共有シートをやめて欲しい
Chrome など移行中
標準の共有シートでできないことはないはず
できること
- 任意のアクションを追加できる
- 34 からはカスタムアクションがある Intent で表現
- 並び替えできる
- 初期インテント
- 除外できる
- 自分自身を出さない
- 共有先を知ることができる
- PendingIntent と BroadcastReciever
- createChooser
- intentSender
標準でできないことがことがあればフィードバックが欲しい
Rich UI
Compose Preview はすぐに確認できる
SpanStyle
AnnotatedString
appendInlineContent
Brush
SweepGradient で時計のようなグラデーションができるので、タイマー表示にもリッチな表現に使えそう
ComposeShader
Shader を合成できる
Modifier.drawWithContent
AndroidVew では onDraw メソッドをオーバーライドして実現が必要だったことが Modifier で簡単にできるようになっている
Animation
一定時間内で少しずつ変化していくこと
画像の切り替えとは異なる
animate..AsState
値は一定間隔ではなく、気持ち良いアニメーションの値を算出してくれる
Compose Runtime が値を監視して Redraw
updateTransition
transitionSpec
launchedEffect でフラグを上げ下げするのはベストとは思えない
初期表示とそれ以外の状態が異なるなら、何か表現方法はないだろうか
Comonent animation feature
- AnimateVisibility
- Enter-ExitTransition
- Corssfade
- 天気予報の切り替えに良さそう
- droidtraining に取り入れても良さそう
- この辺り ios-training にも animation 追加した方が楽しくなるんじゃないかな
- AnimatedContent
- Develop Site に詳しく
Shimmer Effect
光の反射表現
Draw gradient
発光部分を drawWithContent
blendMode srcAtop
Modifier として定義しておくと、様々な Composable に適用可能
タイマー表現
animationTargets が複数あるので、 updateTransition
drawIntoCanvas
sweepGradient
AGSL
Android Graphics Shading Language
RenderEffect
サポートOSは絞られるが、より複雑な表現が可能
One button Signin @GitHub
保存したパスキーを使用しますか?
Client discoverization?
ユーザの特定をしている
誰でも良いけど、この環境で使えるパスキーを使って
GitHubユーザはパスキーを知っている前提がある
Autofill(Conditional UI) @MIXI M
利用可能なパスキーがある場合は、そのパスキーを使用するか選べる
Autofill(Condifional UI) @Moneyfoward
パスキーをこれまでのパスワードマネージャーを拡張するような形で利用できる
Hybrid transport @MIXI M
QR コードが表示されるので、パスキーを持っている端末で読み込んでログインする
現状はリカバリで使われているイメージ
Re-Authentication @MIXI M, GitHub
重要な操作に対して再認証を要求する
メルカリのビットコインはこの方式で保護している
パスキーの導入入口
- SignUp
- パスキーの登録
- SignIn
- パスキーでログイン
- Credential Management
- パスキーの影響範囲を明記
- Account Recovery
- パスキーの復旧(パスワード認証と同じフローが必要
UX上の課題
Google の場合 Android 端末にパスキーが登録された状態になる
パスワード管理のユーザに対してパスキーを展開するのが課題
エラーになるとユーザはその機能の利用に消極的になる
モバイル端末のパスキーをPCに向けに使えるがその逆ができない
どうしてもパスキーが使えない状況が出てくる
パスキーを前提とすると UX とそうでない UX がコンフリクトする
認証部分を切り離せないだろうか?
アプリ共通の認証機構とそこで権限をもらって、任意のアプリを開くようなイメージ
セッション管理を共通アプリに任せる
Apple / Google で共通の仕組み
- チームで工夫していること
- チームで改善したいこと
- レビュアーとしての工夫
- レビュイーとしての工夫
- Androidならではの観点
コードレビューの文化はいつからだろう?
2017年くらいのチーム開発からかな
- DMMポイントクラブ
- 5名
- チェックリストでセルフチェック
- スライドで例を公開
- 全員の Approve 4名分?
- 体感として全員がベストか?
- 実装前の設計レビュー
- PR? 口頭?
- レビュータイムを1日2回時間指定
- 午前中は同期レビュー
- コミュニケーション改善
- 午前中は同期レビュー
- レビューが溜まる
- レビュワーの偏り
- TV
- 8名
- KMP
- code owner の approve でマージ
- 修正行の制限
- 500行目安でも多い印象
- レビュワーの偏り
- 仕様の把握に差がある
- レビューされる PR にも偏りがある
- わかりにくいため敬遠される
- ブックス
- 設計を重視する
- 仮実装
- PRベース?
- コードスニペットを活用
- 設計プロセスとコミュニケーション不足の課題の顕在化
- 設計レビューで合意済みなので、本実装の PR レビューのコストが下がる
- 設計を重視する
アプリごとのチーム開発
レビュワーの偏りは知識の偏りと言って良いだろうか
知識が偏っているのは、平準化の機会点
平準化のためには、ペアワークかな
PR を小さくするには、対応する課題の分割が必要
その辺りのコミュニケーションは何か工夫があるだろうか?
レビュワーとしての工夫
認識合わせ
- ちょっとした疑問を聞く
- ちょっとはどれくらい?
- 念の為を聞く
- プルリクのやり取りが3往復以上になりそうな場合、対面レビューやモブレビューへ
- コメントした背景と理由を書く
記録やナレッジとしてプルリクを活用
- 口頭で確認したことをプルリクにもコメントに残す
- 非同期コミュニケーションの基本
- 返信・Resolve の確認
- レビューコメントを読んだ人が今後のレビューをする・される時に役立つように詳細を書く(コメントをナレッジにする)
- 良いコメントを Slack に流したり、 GitHub 上でうまく Notification できないかしら
スムーズなレビューを目指す
- レビューを優先
- レビューすることで自分のタスクにフィードバックが発生するのがメリット
- すぐ見る
- すぐ見てもらったほうがレビュイーの修正も容易。時間経過で忘れてしまう
- 優先度がわかるようにする
心地良いコミュニケーション
- ピンとこない
- 明快な表現で認知負荷を下げるのが重要だと思った
その他
- レビューしたら自分がメンテナンスできるかの責任を持つ
レビューイとしての工夫
差分のサイズを小さくする
- スコープを狭める
- 修正を混ぜない
- コミットの分割
- コメントで補足
- GitHub に依存するので避けれるなら避けたい気がする
- コードコメントの方が優れてそう
読みやすいプルリクにする
- 意味のあるまとまり
- 処理の意図をコードコメント+プルリクコメント <- 冗長では?
必要な情報をきちんと揃える
- 参考資料をつける
その他
- 指摘修正コミットのリンクを返信
- Why REST to GraphQL
GraphQL
- データの取得が効率的
- 単一のエンドポイントでシンプル
- 強い型付
スケーリングの問題がある
マイクロサービス化
モノリスのサービスからの移行
より効率的なマイクロサービスが必要だった
データのローディングが効率的
複数のリクエストを一つのリクエストでまとまる
リアルタイム通信 websocket
いちいちポーリングしなくて良い
個別に作って開発ができる
強い型付のおかげでサーバとのやり取りが明快になる
遅延が減る
全体的なパフォーマンスが改善される
AWS AppSync
Apollo Kotlin
Apollo Kotlin setup
Apollo 💚 Kotlin
Beware the timeout
REST と GraphQL で同じタイムアウトを使うべきではない
最適な時間をサーバチームと相談すること
OkHttp も分ける
Lazy loading
遅延初期化を活用する
Monitoring
queries と mutation の OkHttp Interceptor を活用する
レスポンスが遅い時どうする?
ネストされたクエリを解消する?
Subscriptions は便利だが難しい
WebSocket を維持する
addSocketReopenWhen 問題があった時に再接続を設定できる
エラーハンドリングでちゃんと閉じて開き直す
どうしても切れることがあるので
Client はリセットせずにラムダを使って状態を変えるのが有効だった
既知の課題としてあって、対応した
Error handling
エラーの parsing が複雑
Work in progress
Apollo 4.0 alpha で改善が見られる
Schema automation
有効
開発が活発で複数 flavors あるならやるべき
気軽に vote :-1: できると良いね
サイレントマジョリティをやめよう
Apollo Commmunity は素晴らしい
Apollo 4 は alpha で様々な改善を予定しています
If you come back at the start before introduce GraphQL, how you improve for migration REST to GraphQL?