[Kotlin] Function returning a Deferred

kotlin

(Jonathan Cornaz) #1

Description

Since Kotlin coroutines are stable, a lot of people start using it in production application.

But when new to Kotlin coroutines, there is a caveat very easy to fall into: Writing function returning a Deferred.

This is strongly discouraged and is against the coroutines concept. One should instead mark the function with the kotlin keyword suspend.

Snippet of non-compliant Code

fun foo(): Deferred<String> = GlobalScope.async {
  delay(1000)
  "result"
}

fun usage() {
  GlobalScope.launch {
    println(foo().await())
  }
}

Snippet of Compliant Code (fixing the above non-compliant code)

suspend fun foo(): String {
  delay(1000)
  return "result"
}

fun usage() {
  GlobalScope.launch {
    println(foo())
  }
}

External references

The official coroutines guide (https://github.com/Kotlin/kotlinx.coroutines/blob/master/docs/composing-suspending-functions.md#async-style-functions) states:

This programming style with async functions is provided here only for illustration, because it is a popular style in other programming languages. Using this style with Kotlin coroutines is strongly discouraged for the reasons that are explained below.

Jetbrains also plan to add inspection for that in their IDE: https://youtrack.jetbrains.net/issue/KT-25620

Type: Bug

Returning a deferred enlighten a misconception of the programmer of how coroutines work, and is likely to behave in unexpected manners especially when it comes to parent-child relation, cancellation and error handling.

I would personally set the default severity to “Critical”

Tags

performance, multi-threading, bad-practice, design, pitfall