Kotlin in 2018

  • The fastest growing language in 2018

    • 2.6 times the number of github contributors
  • One of the most loved languages of 2018

  • 5-10 years ahead of Java

  • Kotlin 1.3 released

    • Coroutines are stable
    • Kotlin/Native is beta
    • Lots of other improvements

Why use Kotlin?

  • Kotlin is a better language for the JVM than Java

    • Really easy to get up and running

    • Simpler language than Java

    • Much safer than Java

      • No more NullPointerExceptions!

      • Streamlines the handling of null values

    • More readable than Java

    • Has an excellent standard library

    • 100% Interoperable with Java

Start using Coroutines now!

On every platform it's important that we provide an experience that is

  • Fluid from the user's perspective

  • Scalable when needed

"Asynchronous or non-blocking programming is the new reality"

Lots of ways to do async

  • AsyncTask

  • Executors

  • Loaders

  • Future

  • Libraries (like RxJava)

  • Coroutines

Why Coroutines?

  • A new way of managing background threads​

  • Makes writing async code much easier

  • Convert async callbacks for long-running tasks into sequential code

    • ​The structure of imperative synchronous code is the same as async code

What are Coroutines?

  • Essentially, light weight threads

    • A new Thread uses 1MB
    • A new coroutine uses in the 10s of kilobytes
    • Suspended coroutine calls are removed from the stack
  • Does not block thread, "suspends" thread

  • Uses callbacks under the hood, but looks like sequential code

Coroutines vs RxJava

Coroutines can replace:

  • Single / Maybe / Completable

  • Not everything

  • There are some Rx coroutine wrappers

"Coroutines are always related to some local scope in your application, which is an entity with a limited life-time, like a UI element"

Structured Concurrency

Coroutine Scope

  • For managing coroutine cancellation

  • Parent-child relationship between coroutines

    • Ensures that cancelling a parent will cancel all its children

private val parentJob = Job()
private val uiScope = CoroutineScope(Dispatchers.Main + parentJob)
fun requestSomeData() {
    uiScope.launch {
        updateUI(performRequest())
    }
}
override fun onDestroy() {
    parentJob.cancel()
}
fun requestSomeData() {
    launch {
        updateUI(performRequest())
    }
}

Using CorutineScope

Dispatchers

  • Controls where the coroutine is run

    • i.e. the threadpool

  • Dispatchers.Default

    • Num CPU cores threads
  • Dispatchers.IO

    • Min 64 threads
  • Dispatchers.Main

  • Dispatchers.Unconfined

    • Don't use this

Changing Dispatcher

val result = withContext(Dispatchers.IO) {
    queryDatabase()
}

withContext(Dispatchers.Main) {
    updateUI(result)
}
  • withContext will run block in specified dispatcher

  • When finished the coroutine will continue on the previous dispatcher

  • Good way to switch threads briefly to handle expensive operations

Use Sealed Classes

  • instanceof checks in Java are a code smell

  • I assumed the same in Kotlin

  • But not with sealed classes!

Use Sealed Classes

  • What are sealed classes?

    • Representing restricted class hierarchies
  • Allows your classes to behave like enums

Sealed Classes

sealed class Expr
data class Const(val number: Double) : Expr()
data class Sum(val e1: Expr, val e2: Expr) : Expr()
object NotANumber : Expr()
fun eval(expr: Expr): Double = when(expr) {
    is Const -> expr.number
    is Sum -> eval(expr.e1) + eval(expr.e2)
    NotANumber -> Double.NaN
    // the `else` clause is not required 
    // because we've covered all the cases
}

Good uses of Sealed Classes

  • Event Sourcing

    • Great use of sealed classes

    • Example was pizza ordering system

  • Improving booleans (booleans are bad)

    • val priceRollupFlag: Boolean

    • Convert to sealed classes/enums

      • Maintainable and Extensible

      • Expressive + has domain meaning

Kotlin is coming to the server

  • Lots of companies whole heartedly adopting kotlin on the backend
  • I can't wait for Kotlin to be everywhere!

Kotlin is coming to the server

  • Some really cool server libraries
    • http4k
      • Everything is a function
      • Extremely easy to test
      • Really lightweight and un-opinionated
      • Can run with any container/frameworks
    • Ktor
      • Async framework developed by Jetbrains
      • Uses coroutines a lot
      • Really easy to safely async everything
      • Great testing tools

Convert Gradle Scripts to Kotlin DSL

Gradle Kotlin DSL

  • From the creator of Gradle

    • "Kotlin is better than groovy"

    • "I wish Kotlin existed when I created Gradle"
    • "You lucky b*******s"

Gradle Kotlin DSL

  • Why switch to the Gradle Kotlin DSL
    • Type safe build logic
    • Great IDE Support
    • Way more compile time checks
    • Shorter feedback loop
    • Groovys dynamism has performance hit
    • Null Safety
    • Documentation + discovery

Gradle Kotlin DSL

  • Migration guide
    • Can be done automatically
    • Easier with some preparatory steps to make scripts more declarative
    • Kotlin + groovy can live side by side
      • Kotlin should drive groovy, not the opposite
      • Due to groovy dynamism

Gradle Kotlin DSL

  • Shipped as part of Gradle 5.0

Unit Testing Best Practices

  • Use JUnit5

    • Nested Test classes

    • @TestInstance(PER_CLASS)

Unit Testing Best Practices

  • Mocking can be expensive

    • Especially mocking final classes

  • Instead of recreating mocks for each test method, just clear the mocks

    • 75% performance improvement

Unit Testing Best Practices

@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class DesignControllerTest {

    private val dao: DesignDAO = mockk()
    private val mapper: DesignMapper = mockk()
    private val controller = DesignController(dao, mapper)

    @BeforeEach
    fun init() {
        clearMocks(dao, mapper)
    }

    // takes 250 ms
    @RepeatedTest(300)
    fun foo() {
        controller.doSomething()
    }
}

Unit Testing Best Practices

  • Default parameters are great for testing

  • Can be harmful if overused in production code

Dissecting the stdlib

  • Kotlin written by those who know it best

inline fun <reified T> fromHashTable(
        hashTable: Hashtable<String, out Any>): T {
    
    return objectMapper.readValue(
            objectMapper.writeValueAsString(hashTable), 
            T::class.java)
}

You don't need to go crazy with pure functional programming

  • I'm a huge fan and advocate of the functional programming style over the imperative style.

    • Making everything immutable
    • Thinking of your code in terms of data flow transformation, instead of mutable state that you update.
  • Arrow

    • Pure functional programming library
    • I'm happy with the amount of functional programming tools in the Kotlin stdlib

Make better use of Static Code Analysis

  • Lots of options
    • Detekt/Ktlint
    • Can enforce checks at build time
    • Can log a warning with a link to shared Intellij settings
    • ReviewBots to comment on PRs 
  • Can automate lots of code review work
  • Can get a lot of value from this

The Future

  • Big focus on improving build times
  • Immutability as a first class construct
    • Plans for doing concurrency very well

Resources

Thank you

  • Questions/feedback/comments

KotlinConf 2018

By Tom Hanley

KotlinConf 2018

  • 129