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

Practical Advanced Kotlin in Practice

Practical Advanced Kotlin in Practice

Note: this is the accompanying slide deck for the workshop repository that you can find at http://bit.ly/advanced-kotlin-workshop

Getting started with Kotlin is as easy as saying “I want lambdas”, sure — but that’s only scratching the surface of the brave new world that adopting Kotlin will open up for Java and Android developers. In this workshop we’ll look at a number of 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, threading and coroutines, callbacks vs function references, sealed classes, member and extension functions, default parameters, typealiases, data classes and destructuring. 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.

Sebastiano Poggi

August 29, 2019
Tweet

More Decks by Sebastiano Poggi

Other Decks in Programming

Transcript

  1. Practical

    Advanced Kotlin

    in Practice
    Sebastiano Poggi

    @seebrock3r

    View Slide

  2. 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 Slide

  3. 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 Slide

  4. Properties
    ● What 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 Slide

  5. 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 Slide

  6. 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 Slide

  7. 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 Slide

  8. 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 Slide

  9. 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 MyClass.myFun() → static void myFun(MyClass receiver)

    View Slide

  10. Functions
    ● Functions don’t need to be in a class
    ○ Called top-level functions
    ○ Translate to static methods on JVM
    ○ In a virtual class called like the package
    ○ Functions can take functions as parameters
    ○ Higher-order functions

    View Slide

  11. 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 Slide

  12. 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 Slide

  13. 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 Slide

  14. 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 Slide

  15. 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 Slide

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

    View Slide

  17. 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 Slide

  18. 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 Slide

  19. 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 Slide

  20. 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 Slide

  21. Ready
    Player one
    Sebastiano Poggi

    @seebrock3r
    http://bit.ly/advanced-kotlin-workshop

    View Slide