Slide 1

Slide 1 text

Sansan株式会社 部署 名前 Kotlin Coroutinesを通して理解する Structured Concurrency Sansan技術本部 技術本部 Mobile Applicationグループ 北村 研⼆

Slide 2

Slide 2 text

北村 研⼆ Sansan株式会社 技術本部 Mobile Applicationグループ 2019年中途⼊社 Sansan Androidチームのリーダーを担当した後、 Sansanのプロダクトマネージャーを担当し、 2024年現在ではMobile Applicationグループのプロダクト横断チ ームのリーダーを担当しています。 複数のモバイルプロダクトに関わる技術的な課題の解決に取り組 んでいます。

Slide 3

Slide 3 text

Kotlin Coroutinesの特徴は? と聞かれたら

Slide 4

Slide 4 text

- 軽量スレッド? - ⾮同期処理を同期的に記述することでコールバック地獄の解消? Kotlin Coroutinesの特徴

Slide 5

Slide 5 text

Structured Concurrency!

Slide 6

Slide 6 text

- ⽇本語では構造化された並⾏性を意味する - 実⾏した⾮同期処理が完了するまで、呼び出し元の特定のブロックが完 了しないことを保証する並⾏処理の概念 - Kotlin CoroutinesではCoroutineScopeで実現できる Structured Concurrencyとは? coroutineScope { delay(1000) println("Hello") } coroutineScope { println("World") launch { delay(1000) println("!!!") } } println("終わり")

Slide 7

Slide 7 text

- アプリケーションの任意のスコープと、並⾏処理のスコープを ⼀致させることは難しい - 例えば次のコードはボタンの連打対策がされているが、 ボタンを押してrequestDataの処理に時間がかかる場合があり、 ⼀つ前の画⾯に戻って再度画⾯を開き、ボタンを押したら期待通りに動作しない 並⾏処理はスコープの管理が困難 fun onClick() { GlobalScope.launch { disableButton() val data = requestData() updateUI(data) enableButton() } }

Slide 8

Slide 8 text

- アプリケーションの任意のスコープと、並⾏処理のスコープを同期でき、 必要に応じて適切にキャンセルができる - 例えば次のコードはUIのスコープを⽰すViewModelScopeで実⾏するので、そのス コープが終了すればCoroutineの処理もキャンセルされる Structured Concurrencyによりスコープ問題を解決 fun onClick() { viewModelScope.launch { disableButton() val data = requestData() updateUI(data) enableButton() } }

Slide 9

Slide 9 text

- 構造化された並⾏処理がない場合、 複数の並⾏処理を⾏うときのエラー処理が難しくなる - ある並⾏処理でエラーが発⽣したときに、別の並⾏処理を停⽌するのが複雑になる 複数の並⾏処理を同時実⾏した場合のエラー処理が困難 suspend fun loadAndCombine(name1: String, name2: String): Image { val deferred1 = GlobalScope.async { loadImage (name1) } val deferred2 = GlobalScope.async { loadImage (name2) } return combineImages (deferred1.await(), deferred2.await()) }

Slide 10

Slide 10 text

- Structured Concurrencyにより、ある並⾏処理でエラーが発⽣した場合に、 別の並⾏処理をキャンセルする事ができる エラー処理も楽になる suspend fun loadAndCombine(name1: String, name2: String): Image = coroutineScope { val deferred1 = async { loadImage(name1) } val deferred2 = async { loadImage(name2) } combineImages(deferred1.await(), deferred2.await()) }

Slide 11

Slide 11 text

構造化プログラミングとの類似性

Slide 12

Slide 12 text

- 構造化プログラミングが出現する前、⾃作関数は無くGOTO⽂のみがあった - 抽象化されておらず、スパゲッティになり、保守性が無い - 構造化プログラミングでは関数としてブラックボックス化できた 構造化プログラミングは秩序と平和をもたらした

Slide 13

Slide 13 text

- 「実⾏した⾮同期処理が完了するまで、呼び出し元の特定のブロックが 完了しないことを保証」することで並⾏処理をブラックボックス化できる - Structured Concurrencyのパラダイムは並⾏処理プログラミングに 秩序と平和をもたらす 並⾏処理プログラミングにも秩序と平和をもたらす

Slide 14

Slide 14 text

⼩ネタ

Slide 15

Slide 15 text

- Kotlin 1.1の頃、Kotlin CoroutinesはStructured Concurrencyの概念がなかった - その時点でのCoroutinesの魅⼒は、軽量スレッドで処理を中断できる点だった - Kotlin 1.1では、Coroutinesを開始するのにCoroutineScopeは必須ではなく、ど こからでもlaunchを使って処理を開始できた - Kotlin 1.3でCoroutinesが正式版になり、Structured Concurrencyの概念が導⼊さ れ、launchを使⽤する際にCoroutineScopeが必須となった Kotlin Coroutinesは最初Structured Concurrencyでは無かった

Slide 16

Slide 16 text

まとめ

Slide 17

Slide 17 text

- 従来の並⾏処理ライブラリとの⼤きな違いはStructured Concurrency - Structured Concurrencyのメリット - 並⾏処理のスコープを管理しやすくなる - 並⾏処理の例外処理が容易になる - 構造化プログラミングの登場と同じくらい⼤きなパラダイムシフトをもたらす まとめ

Slide 18

Slide 18 text

No content