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. 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
  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™
  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
  4. 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
  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!
  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
  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)
  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
  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 AnyClass.myFun() → static void myFun(AnyClass receiver)
  10. 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
  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" }
  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
  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
  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
  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
  16. 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
  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
  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
  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
  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