Reviewing Kotlin (Conference for Kotliners 2019)

Reviewing Kotlin (Conference for Kotliners 2019)

I have been teaching our rapidly growing team of Android developers Kotlin for about a year, and for the last few months, I’ve been reviewing tens of thousands of lines of code written by almost a dozen people at times. Here’s what we’ve found out together about learning, teaching, and reviewing Kotlin. I’ll tell you what worked for us and what didn’t, so that you may be more prepared for this path than we were. I’ll also point out some of the issues that most often arose in the code while our developers were getting familiar with the language.

Talk recording: https://www.youtube.com/watch?v=sXwiiTFjczw

4047c64e3a1e2f81addd4ba675ddc451?s=128

Marton Braun

June 07, 2019
Tweet

Transcript

  1. 4.

    and how to get your management onboard with the idea

    Why you should use Kotlin for Android development… How great code reviews are, and what’s the best way to do them This is not…
  2. 5.

    and how to get your management onboard with the idea

    Why you should use Kotlin for Android development… All the awesome things that are in the Kotlin standard library How great code reviews are, and what’s the best way to do them This is not…
  3. 6.

    Life is Great and Everything Will Be Ok, Kotlin is

    Here Christina Lee, Jake Wharton Google I/O '17 Dissecting the stdlib Huyen Tue Dao KotlinConf 2018 Code Review Best Practices Trisha Gee SCLConf 2018 This is not…
  4. 7.
  5. 8.
  6. 9.
  7. 10.
  8. 11.
  9. 12.
  10. 14.
  11. 15.
  12. 16.
  13. 17.
  14. 18.
  15. 19.
  16. 20.
  17. 21.
  18. 29.

    entries: ArrayList<Entry>) { fun updateColors(chart: , val colors = ArrayList<Int>()

    entries.forEach { entry -> colors.add(entry.data as Int) } } PieChart
  19. 30.

    entries: ArrayList<Entry>) { fun updateColors(chart: , val colors = ArrayList<Int>()

    entries.forEach { entry -> colors.add(entry.data as Int) } chart.colors = colors } PieChart
  20. 31.

    entries: ArrayList<Entry>) { fun updateColors(chart: , val colors = ArrayList<Int>()

    entries.forEach { entry -> colors.add(entry.data as Int) } chart.colors = colors } PieChart
  21. 32.

    fun PieChart.updateColors(entries: val colors = ArrayList<Int>() entries.forEach { entry ->

    colors.add(entry.data as Int) } this.colors = colors } List<Entry>) { Array
  22. 33.

    fun PieChart.updateColors(entries: val colors = ArrayList<Int>() entries.forEach { entry ->

    colors.add(entry.data as Int) } this.colors = colors } List<Entry>) {
  23. 34.

    fun PieChart.updateColors(entries: val colors = ArrayList<Int>() entries.forEach { entry ->

    colors.add(entry.data as Int) } this.colors = colors } List<Entry>) {
  24. 35.
  25. 36.
  26. 37.

    fun PieChart.updateColors(entries: List<Entry>) { val colors = mutableListOf<Int>() entries.map {

    entry -> colors.add( ) } this.colors = colors } entry.data as Int
  27. 42.
  28. 43.
  29. 47.
  30. 48.
  31. 49.
  32. 53.

    val events: List<Event> = getAllEvents() val upcoming = events.filter {

    it.date > } OffsetDateTime.now() val now = now
  33. 59.

    if (scanner != null) { } else { /* ¯\_(ツ)_/¯

    */ } } fun startBluetoothLeScan() { val scanner = BluetoothAdapter.getDefaultAdapter() .bluetoothLeScanner /* ... */ scanner.startScan(/* ... */)
  34. 60.
  35. 61.
  36. 65.

    data class DailyFluidConsumption( val quantity: Double, val recommended: Double =

    4.0, val percentage: Int = ((quantity / recommended) * 100) .roundToInt() .coerceIn(0..100) )
  37. 66.

    data class DailyFluidConsumption( val quantity: Double, val recommended: Double =

    4.0 ) val percentage: Int = ((quantity / recommended) * 100) .roundToInt() .coerceIn(0..100)
  38. 67.

    data class DailyFluidConsumption( val quantity: Double, val recommended: Double =

    4.0 ) val DailyFluidConsumption.percentage: Int ((quantity / recommended) * 100) .roundToInt() .coerceIn(0..100)
  39. 68.

    data class DailyFluidConsumption( val quantity: Double, val recommended: Double =

    4.0 ) val DailyFluidConsumption.percentage: Int get() = ((quantity / recommended) * 100) .roundToInt() .coerceIn(0..100)
  40. 70.

    class Ingredient( val id: UUID = UUID.randomUUID(), val name: String

    = "", val quantity: Double? = null, val unit: String? = null, val imageId: UUID? = null )
  41. 71.

    class Ingredient( val id: UUID = UUID.randomUUID(), val name: String

    = "", val quantity: Double? = null, val unit: String? = null, val imageId: UUID? = null )
  42. 72.

    class Ingredient( val id: UUID = UUID.randomUUID(), val name: String

    = "", val quantity: Double? = null, val unit: String? = null, val imageId: UUID? = null )
  43. 73.

    class Ingredient( val id: UUID = UUID.randomUUID(), val name: String

    = "", val quantity: Double? = null, val unit: String? = null, val imageId: UUID? = null ) Ingredient(id, "Pixie dust", 6.28, "teaspoon")
  44. 74.

    class Ingredient( val id: UUID = UUID.randomUUID(), val name: String

    = "", val quantity: Double? = null, val unit: String? = null, val imageId: UUID? = null ) Ingredient(id, "Pixie dust", 6.28, "teaspoon")
  45. 75.

    class Ingredient( val id: UUID = UUID.randomUUID(), val name: String

    = "", val quantity: Double? = null, val unit: String? = null, val imageId: UUID? = null ) Ingredient(id, "Pixie dust", 6.28, "teaspoon")
  46. 76.

    class Ingredient( val id: UUID, val name: String, val quantity:

    Double?, val unit: String?, val imageId: UUID? ) Ingredient(id, "Pixie dust", 6.28, "teaspoon")
  47. 77.

    class Ingredient( val id: UUID, val name: String, val quantity:

    Double?, val unit: String?, val imageId: UUID? ) Ingredient(id, "Pixie dust", 6.28, "teaspoon", null)
  48. 78.

    id = name = quantity = unit = imageId =

    id, 6.28, ) "teaspoon", null Ingredient( "Pixie dust", class Ingredient( val id: UUID, val name: String, val quantity: Double?, val unit: String?, val imageId: UUID? )
  49. 83.

    suspend fun getValidMeasurements( measurements: List<Measurement> ): List<Measurement> { return measurements.filter

    { val validator = getValidatorForType(it.type) it.value in (validator.minValue..validator.maxValue) } }
  50. 84.

    suspend fun getValidMeasurements( measurements: List<Measurement> ): List<Measurement> { return measurements.filter

    { measurement -> val validator = getValidatorForType(measurement.type) measurement.value in (validator.minValue..validator.maxValue) } }
  51. 85.

    return measurements.filter { measurement -> val validator = getValidatorForType(measurement.type) measurement.value

    in (validator.minValue..validator.maxValue) } } suspend fun getValidMeasurements( measurements: List<Measurement> ): List<Measurement> {
  52. 86.

    return measurements.filter { measurement -> val validator = getValidatorForType(measurement.type) measurement.value

    in (validator.minValue..validator.maxValue) } } suspend fun getValidMeasurements( measurements: List<Measurement> ): List<Measurement> {
  53. 87.

    return measurements.filter { measurement -> val validator = getValidatorForType(measurement.type) measurement.value

    in (validator.minValue..validator.maxValue) } } suspend fun getValidMeasurements( measurements: List<Measurement> ): List<Measurement> {
  54. 88.

    val validatorsByType = getAllValidators() suspend fun getValidMeasurements( measurements: List<Measurement> ):

    List<Measurement> { } return measurements.filter { measurement -> val validator = getValidatorForType(measurement.type) measurement.value in (validator.minValue..validator.maxValue) }
  55. 89.

    val validatorsByType = getAllValidators().associateBy { it.type } suspend fun getValidMeasurements(

    measurements: List<Measurement> ): List<Measurement> { } return measurements.filter { measurement -> val validator = getValidatorForType(measurement.type) measurement.value in (validator.minValue..validator.maxValue) }
  56. 90.

    val validatorsByType = getAllValidators() suspend fun getValidMeasurements( measurements: List<Measurement> ):

    List<Measurement> { } return measurements.filter { measurement -> val validator = validatorsByType.getValue(measurement.type) measurement.value in (validator.minValue..validator.maxValue) } .associateBy { it.type }
  57. 91.
  58. 92.
  59. 93.
  60. 94.
  61. 95.
  62. 96.
  63. 97.
  64. 98.
  65. 99.
  66. 100.
  67. 101.
  68. 102.
  69. 103.
  70. 104.
  71. 105.
  72. 106.
  73. 107.

    fun add (x:Int,y: Int) :Int{ return x +y } fun

    main() { println( add(2,3) ) }
  74. 108.

    fun add(x: Int, y: Int): Int { return x +

    y } fun main() { println(add(2, 3)) }
  75. 110.

    Related talks • Code Review Best Practices  Trisha Gee,

    SCLConf 2018  https://www.youtube.com/watch?v=jXi8h44cbQA • Life is Great and Everything Will Be Ok, Kotlin is Here  Christina Lee & Jake Wharton, Google I/O ‘17  https://www.youtube.com/watch?v=fPzxfeDJDzY • Dissecting the stdlib  Huyen Tue Dao, KotlinConf 2018  https://www.youtube.com/watch?v=Fzt_9I733Yg
  76. 111.

    Learning resources • Kotlin in Action, Dmitry Jemerov and Svetlana

    Isakova  https://www.manning.com/books/kotlin-in-action • Coursera course, Andrey Breslav and Svetlana Isakova  https://www.coursera.org/learn/kotlin-for-java-developers • O’Reilly courses, Hadi Hariri  https://hadihariri.com/2016/11/01/oreilly-kotlin-course/
  77. 112.

    Learning resources • Kotlin Bootcamp for Programmers  https://eu.udacity.com/course/kotlin-bootcamp-for- programmers--ud9011

    • Developing Android Apps with Kotlin  https://eu.udacity.com/course/developing-android-apps-with- kotlin--ud9012