Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Practical Advanced Kotlin in Practice

Practical Advanced Kotlin in Practice

Getting started with Kotlin is as easy as saying “I want null safety” or "I hate boilerplate", sure — but that’s only scratching the surface of the brave new world that adopting Kotlin opened up for Java and Android developers.

In this workshop we’ll look at a number of less known language features and tips to make the most of the Kotlin Programming Language™ in our day-to-day work. We’ll touch on several topics, including property delegates, coroutines and flows, callbacks vs function references, sealed classes, member and extension functions, default parameters, typealiases, data classes and destructuring declarations.

For each of them, we’ll go over a series of dos and don’ts and best practices making sure you get the most out of Kotlin, without falling in the "shiny new thing" pitfalls.

---

The workshop code can be found at: https://github.com/rock3r/advanced-kotlin-workshop

Sebastiano Poggi

April 25, 2022
Tweet

More Decks by Sebastiano Poggi

Other Decks in Programming

Transcript

  1. Practical
    Advanced Kotlin
    in Practice
    Sebastiano Poggi
    @seebrock3r

    View full-size slide

  2. Before we begin!
    ● Make sure you have a computer
    ● Make sure you have an IDE: Intell! IDEA, Android Studio
    ● Make sure it’s up to date
    ● Make sure the Kotlin plugin is enabled and up to date, too
    ● Clone the repo: http:!"bit.ly/advanced-kotlin-workshop
    You have
    75 minutes …more or less

    View full-size slide

  3. Topics of the workshop
    ● Properties: lateinit, delegates
    ● Type system: type erasure and reified types
    ● Enum vs sealed classes
    ● Functions: top level functions, mixing in some functional code
    ● DSLs
    ● Destructuring and numbered components
    ● Opinions™

    View full-size slide

  4. Properties
    ● val vs var
    ○ val is like final in Java
    ○ Immutable reference
    ○ No guarantees on the value immutability
    ○ var are mutable variables
    ○ Mutable reference and value

    View full-size slide

  5. Properties
    ● What if you don’t have a value right away?
    ○ lateinit var myVar
    ○ E.g., Dagger, Context-dependent values, etc
    ○ Zero overhead, can change afterwards
    ○ Check if initialised with !#myVar.isInitialized
    ○ For primitive types use by notNull() instead

    View full-size slide

  6. Properties
    ● What if a value is expensive to produce and only used in some cases?
    ○ val myVal by lazy { … }
    ● Caches value once calculated, then can’t change anymore
    ● Synchronised (thread-safe) by default ⚠
    ○ Can be made faster with LazyThreadSafetyMode.NONE
    ○ Check your threading model!

    View full-size slide

  7. Type system
    ● Inherits JVM limitations
    ○ Type erasure loses type parameters’ information at runtime
    ● Is stricter in some regards
    ○ Has explicit covariance/contravariance keywords: in and out
    ○ No need to care much about them... except when you do
    ○ Seb’s top tip: try until the compiler is happy

    View full-size slide

  8. Type system
    ● Reified types
    ○ Only available for inline functions
    ○ Allows compiler to resolve type parameters
    ○ No need to pass in classes explicitly as arguments
    ○ No need to specify type parameters explicitly (in most cases)

    View full-size slide

  9. Enum and sealed classes
    ● Enumerations are enum classes
    ○ They work the same as in Java
    ● Sealed classes
    ○ Best of both worlds
    ○ Known set of values at compile time
    ○ Can be objects or (data) classes or a mix of them
    ● Use sealed classes for “enums with data”
    ○ E.g., kotlin.Result

    View full-size slide

  10. Functions
    ● Member functions are declared on a class you own
    ● Extension functions can be declared on any class
    ○ Even final/closed classes
    ○ Statically dispatched
    ○ fun AnyClass.myFun() → static void myFun(AnyClass receiver)

    View full-size slide

  11. Functions
    ● Functions don’t need to be in a class
    ○ Called top-level functions
    ○ Translate to static methods on JVM
    ○ In a synthetic class called like the file
    ○ E.g., a function in Functs.kt goes into FunctsKt
    ● Functions can take functions as parameters
    ○ Higher-order functions

    View full-size slide

  12. DSLs
    ● Create domain-specific languages
    ○ Extension functions for scoping
    ○ Higher-order functions to compose behaviour
    ○ E.g.:
    fun user(block: User.() !$ Unit): User { … }
    val user = user { name = "Roborbio" }

    View full-size slide

  13. Functional code
    ● Kotlin is OO but has FP facilities
    ○ Top-level functions
    ○ Function types & lambdas
    ○ Higher-order functions
    ○ Rich collection processing APIs
    ● Sequences
    ○ Lazy streams
    ○ Can only be “played” once

    View full-size slide

  14. Functional code
    ● Pure functions
    ○ Regular functions
    ○ No “outside” dependencies
    ○ No side effects
    ■ If you need them, isolate and make them explicit
    ● Great for some use cases
    ○ Data processing
    ○ Pipelines

    View full-size slide

  15. Collection/sequence APIs
    ● Same idioms as general FP
    ○ Mapping, filtering, grouping, aggregating, reducing
    ● Collection type-specific APIs
    ○ Lists: get by position, sublist, binary search, …
    ○ Maps: key/value aware functionality
    ○ Sets: intersect, union, subtract

    View full-size slide

  16. Destructuring declarations
    ● Special functions: componentN()
    ○ Access constructor properties in order
    ○ Data classes have them by default
    ● Destructuring declarations
    ○ Unpack classes’ components
    ○ data class User(val name: String, val surname: String, val
    email: String)
    val (name, surname) = myUser

    View full-size slide

  17. and now…
    segment I like to call
    opinions!

    View full-size slide

  18. and now…
    opinions!
    In a segment I like to call
    EVERYBODY
    HAS OPINIONSTM
    BUT I AM THE SPEAKER SO YOU ALL
    HAVE TO LISTEN TO MY RANTS NOW

    View full-size slide

  19. and now…
    opinions!
    In a segment I like to call
    EVERYBODY
    HAS OPINIONSTM
    BUT I AM THE SPEAKER SO YOU ALL
    HAVE TO LISTEN TO MY RANTS NOW

    View full-size slide

  20. Everybody has Opinions!
    ● Extension functions
    ○ They’re awesome! But…
    ○ Hard to discover, “break” encapsulation
    ○ Avoid abusing them, same as util classes
    ○ Prefer smaller scopes
    ○ …unless used as entry point to 3rd party API
    ○ Consider top-level functions instead
    ○ Factor in Java interop

    View full-size slide

  21. Everybody has Opinions!
    ● Delegate properties
    ○ They’re cool but don’t abuse them
    ○ Can obscure meaning and behaviour
    ● Lazy
    ○ Don’t make inexpensive stuff lazy
    ○ Prefer lateinit for “initialised later” idiom

    View full-size slide

  22. Everybody has Opinions!
    ● DSLs
    ○ You don’t always need a DSL for that
    ○ Avoid being too “smart” and side effects
    ● Operator overloading
    ○ Don’t unless it’s extremely obvious what you’re doing
    ○ Avoid at all costs if any risk of surprising users
    ○ Must be obvious that it’s an overload

    View full-size slide

  23. Ready
    Player one
    Sebastiano Poggi
    @seebrock3r
    go.sebastiano.dev/kotlin-workshop-2022

    View full-size slide