第55回Kotlin dojoを開催した

今週は第55回を開催しました!

引き続きKotlin Hands-onをすすめています。

 

前回の様子はコチラ↓

kdnakt.hatenablog.com

 

 

[第55回の様子]

2021/3/10に第55回を開催した。

 

参加メンバーは自分をいれて4名。メンバーは最近固定気味。

今回も自分はナビゲータ役を担当した。

 

勉強会本編の内容としては、ひき続きIntroduction to Coroutines and Channelsハンズオンを進めた。第5章 Concurrencyのタスク部分を実施して、あと少し残して終わり。

全体としては第9章まであるので、ようやく後半戦という感じ。

 

[学んだことや疑問点]

  • Introduction to Coroutines and Channels: 5. Concurrency
    • 今回のタスクはloadContributorsConcurrent()を実装せよというもの
suspend fun loadContributorsConcurrent(
    service: GitHubService, req: RequestData
): List<User> = coroutineScope {
     // この部分を実装するのが課題
}
    • coroutineScope()を使うと新しいスコープを定義できるらしい
    • スコープの使い道がいまいち理解できないまま問題を解いてみる
    • 方針としては以下のようにDeferredのリストを受け取って、awaitAll()すればよい
    • 前回も不思議だったのだけれど、Listに新しくawaitAll()関数が生えるのが面白い
val deferreds: List<Deferred<List<User>>> = repos.map { repo ->
    async {
        // load contributors for each repo
    }
}
deferreds.awaitAll() // List<List<User>>
    • 前々回のloadContributorsSuspend()の実装を参考にすべし、ということで最初に出た解答がこちら
val repos = service
    .getOrgRepos(req.org)
    .also { logRepos(req, it) }
    .body() ?: listOf()
// ここまではloadContributorsSuspendそのまま利用

val deferreds: List<Deferred<List<User>>> = repos.map { repo ->
    async {
        service
            .getRepoContributors(req.org, repo.name)
            .also { logUsers(repo, it) }
            .bodyList()
    }
}
deferreds.awaitAll().flatten() // List<List<User>>をList<User>に変換
    • ところが、GUIを起動して動作を確認してみると、意図した結果と異なっていた
    • 本来、ユーザーごとのコントリビューション数合計が表示されるべきところ、各ユーザーのコントリビューション数がリポジトリごとに表示されてしまっていた
    • 模範解答を見て、deferreds.awaitAll().flatten().aggregate()と最後に集計処理が足りていなかったので追加した
    • 動作確認結果も問題なし!
    • 次の話題は別スレッドを利用して、マルチスレッドでCoroutineを利用する方法。しかし時間がなかったので最初の触りだけ読んで、今回はおしまい。

 

[まとめ]

モブプログラミング・スタイルで、Introduction to Coroutines and Channelsハンズオンを進めた。

coroutineScope()という新しい概念が出てきたけどあまり説明がなかった。たぶんマルチスレッドでいうスレッドを分ける的な話だとは思うけど……。詳細は次回以降に期待。

 

今週のプルリクエストはこちら。

github.com