Slide 1

Slide 1 text

コルーチンを使って 処理の見通しをよくする リアルタイム放送の品質を向上し、 保つために horitamon • 2022 年 10月 5 日 @DroidKaigi2022

Slide 2

Slide 2 text

自己紹介 堀 多聞 - horitamon Androidエンジニア5年目 2020/9〜 Voicy 品質改善チーム Twitter: @horitamon

Slide 3

Slide 3 text

音声プラットフォーム - Voicy さまざまなパーソナリティのトークを楽しめるサービスを提供

Slide 4

Slide 4 text

Voicyのアプリ 聴くアプリ「Voicy」と 収録するアプリ「Voicy Recorder」 ふたつをAndroid/iOSともに展開

Slide 5

Slide 5 text

こんなことで 困ったこと、 ありませんか?

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

ぱっと見 何してるのか わからん😇 (追えばわかるけども)

Slide 8

Slide 8 text

コールバック内コールバック

Slide 9

Slide 9 text

帰らぬ人となったメソッド分割 呼び元のメソッドの役割が不明瞭 (行数増えると分けがちだけど)

Slide 10

Slide 10 text

LiveDataでUIへ処理完了を通知 これすなわち呼び元のメソッドが 分断されているということ

Slide 11

Slide 11 text

ぱっと見startLiveの結果が isSucceededStartから来るとは わからない🤔

Slide 12

Slide 12 text

コードの 見通しが悪くて 不具合の原因が わからない…! ● エラーログが無いので読むしかない … ● コールバックやメソッド分割でどの 処理がどの順番で進むのか わかりづらい… ● 原因が見つからないし、 直すにしてもどこを直せば… →不具合の解決に時間がかかる

Slide 13

Slide 13 text

そんなときに、 コルーチン

Slide 14

Slide 14 text

コルーチン =スレッド操作 だけじゃない! ● コルーチンってスレッド操作をやり やすくするんじゃないの? →それだけじゃない! ● コールバックを減らせるという 可読性の面での利点がある

Slide 15

Slide 15 text

今日伝えること 1. コルーチンの「中断」 2. コルーチンで コードの見通しを良くする 3. リアルタイム放送の品質を向上し 保つためにしたこと

Slide 16

Slide 16 text

コルーチンとは

Slide 17

Slide 17 text

コルーチンとは ざっくり言うと 並行実行のデザインパターン スレッド切り替え、バックグラウンド処理といった 非同期実行するコードを簡略化できる 全体をつかむには 過去のDroidKaigiでとてもわかりやすい発表があります 
 Understanding Kotlin Coroutines: コルーチンで進化するアプリケーション開発 @mhidaka

Slide 18

Slide 18 text

https://developer.android.com/kotlin/coroutines/ coroutines-adv?hl=ja loginをメインスレッドから呼ぶと makeLoginRequestが完了するまで スレッドをブロックしてしまう🤔

Slide 19

Slide 19 text

https://developer.android.com/kotlin/coroutines/ coroutines-adv?hl=ja 💡処理を簡単にI/Oスレッドへ移せる

Slide 20

Slide 20 text

コルーチンの 中断

Slide 21

Slide 21 text

https://developer.android.com/kotlin/coroutines/ coroutines-adv?hl=ja そもそもスレッドをブロックしないでほしい😠

Slide 22

Slide 22 text

https://developer.android.com/kotlin/coroutines/ coroutines-adv?hl=ja 💡makeLoginRequestを  suspend関数にする  呼び元のコルーチンを中断し  結果が出たら再開する

Slide 23

Slide 23 text

💡止めるのではなく中断する →結果が返ってくるまではメインスレッドが使える Main I/O System Coroutine launch Coroutine withContext Coroutine return suspend

Slide 24

Slide 24 text

https://developer.android.com/kotlin/coroutines/ coroutines-adv?hl=ja 💡makeLoginRequestはsuspend関数  コルーチンを中断し  結果が出たら再開する

Slide 25

Slide 25 text

https://developer.android.com/kotlin/coroutines/ coroutines-adv?hl=ja 💡実行スレッドをブロックせず  中断するだけ  メインセーフティ✨ 今回このコルーチンの 「中断」が活躍します

Slide 26

Slide 26 text

コルーチンで コードの見通しを良くする

Slide 27

Slide 27 text

例:生放送 Voicyが提供する リアルタイム放送機能 リスナーからのお便りに答えたり リスナーにゲストとして トークに参加してもらったり リアルタイムな交流が可能

Slide 28

Slide 28 text

問題のコードを コルーチンで書き換える ※もちろん擬似

Slide 29

Slide 29 text

No content

Slide 30

Slide 30 text

コールバックで結果を受け取っている LiveRepository#getByLiveIdを コルーチンを使って表してみる

Slide 31

Slide 31 text

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.c oroutines/suspend-coroutine.html 💡コルーチンを「中断」しつつ  「継続」するためのオブジェクトを提供する

Slide 32

Slide 32 text

suspendCoroutineも suspend関数 →呼び元のコルーチンを中断

Slide 33

Slide 33 text

結果を返してコルーチンを再開

Slide 34

Slide 34 text

💡同期処理っぽい書き方に →コールバックが減らせる

Slide 35

Slide 35 text

💡やってることが一目でわかる ● 生放送情報の取得 ● 生放送データを開始状態にする ● 画像URL取得

Slide 36

Slide 36 text

開始処理の結果が まだちょっと追いづらい…

Slide 37

Slide 37 text

ぱっと見startLiveの結果が isSucceededStartから来るとは わからない🤔

Slide 38

Slide 38 text

成功/失敗をBooleanで返すメソッドに

Slide 39

Slide 39 text

💡生放送の開始処理の成功/失敗を  返すメソッドになった

Slide 40

Slide 40 text

💡見通しUP! ・生放送の開始処理の成功/失敗を  返すメソッドであることがわかる ・処理の順番がすぐわかる

Slide 41

Slide 41 text

💡見通しUP!  startLiveの結果を受け取る箇所が  すぐわかる

Slide 42

Slide 42 text

生放送が開始しない不具合が発生! ↓ エラーハンドリング追加まで やってみる 見やすくなった コードから 問題点を 解決していく

Slide 43

Slide 43 text

・setLiveStartedが完了しないと次へは進まない ・liveがnullの場合もsetLiveStartedへ進んでしまう →止まるポイントがすぐわかる

Slide 44

Slide 44 text

liveがnullのときは失敗を返す

Slide 45

Slide 45 text

見通しが良くなると 品質を落としているポイントが コードからわかるようになる さらに 問題点を探してみる

Slide 46

Slide 46 text

この処理をしなくても setLiveStartedへ 進むことは可能 →余計な待ち時間がある

Slide 47

Slide 47 text

💡並列実行で  処理スピードUp

Slide 48

Slide 48 text

リアルタイム放送の 品質を向上し 保つためにしたこと

Slide 49

Slide 49 text

Voicyの Qualityチーム 既存機能の品質向上を担う ● 2022年から開発チーム編成を変更 ● 変更前のチームでリリースした 機能の保守責任が曖昧に ● 2021年リリースの生放送で 障害発生 ● 対応の流れでQualityチームが発足 ● リリース済み機能の不具合対応や ユーザーからの問い合わせに対応

Slide 50

Slide 50 text

Voicy server 音声通信 ・放送データ ・お便り イベント 通信 ・放送開始 ・データ更新 3つの通信経路を 同時性を保って管理 生放送の構成

Slide 51

Slide 51 text

見通しが悪くて どこが問題なのか なかなかわからない…!

Slide 52

Slide 52 text

生放送を開始する流れ 1. 放送データを「予約中」から「放送中」に更新 2. 生放送開始イベントを通知 3. 音声を接続する 4. 放送データの取得、更新 ○ 放送データを作成 ○ 自身のユーザーデータ取得 ○ アイコン画像取得 ○ お便りブロックユーザー一覧取得 etc… 順番は…? 失敗した ときは…? よ〜〜〜く読まないと把握できない😇

Slide 53

Slide 53 text

そもそもやってることが複雑 ● 3つの双方向通信 ● 通信の同時性を保つ ● たくさんのセットアップ処理 開発していくうちにさらにどんどん複雑に ● 技術調査、実装、仕様調整を繰り返す ● 複数人で同時並行で開発する なぜ見通しが悪いコードに…?

Slide 54

Slide 54 text

すぐ直すのではなく 一度立ち止まってでも コードの見通しを 良くする ● このままだと 調査も修正も時間がかかる ● よくわからないまま修正して さらに不具合を生むリスク →問題を解決し  問題を生まないために  まず見通しを良くする

Slide 55

Slide 55 text

リファクタで 価値をストレートに 届ける リファクタは 直接的な解決策ではない しかし不具合が減らしやすく 増えにくくなる ユーザーが感じる品質課題が減る →価値ある機能が  ストレートに届くようになる

Slide 56

Slide 56 text

コルーチンで非同期処理を同期的に書き直すと コードの見通しが良くなる ● 処理の順番が追いやすくなり、全体の見通しが良くなる ● 不具合原因を見つけやすくなり コードからさらなる課題を見つけやすくなる リファクタはユーザーにとっても価値がある ● 不具合解決のスピードが上がり、リスクも減る ● 価値ある機能がストレートに届く まとめ

Slide 57

Slide 57 text

参考 ● Understanding Kotlin Coroutines: コルーチンで進化するアプリケーション開発 @mhidaka
 ● Using Kotlin Coroutines in your Android App 
 
 ● Android での Kotlin コルーチン | Android Developers 
 ● Coroutines guide | Kotlin


Slide 58

Slide 58 text

Voicy のエンジニアが テックや開発組織について いろいろ語っています DroidKaigi登壇メンバーの アフタートークも予定! voi-chord配信中!

Slide 59

Slide 59 text

Voicyで音声の未来を切り開く仲間を募集中! 対面でも、Twitter DMでも詳しくお話しします @horitamon

Slide 60

Slide 60 text

Thank you!