Kotlin in Practice Philipp Hauer, Fabian Sudau Spreadshirt JUG - - PowerPoint PPT Presentation

kotlin in practice
SMART_READER_LITE
LIVE PREVIEW

Kotlin in Practice Philipp Hauer, Fabian Sudau Spreadshirt JUG - - PowerPoint PPT Presentation

Kotlin in Practice Philipp Hauer, Fabian Sudau Spreadshirt JUG Saxony Camp 2017 Spreadshirt Spreadshirt Spreadshirt 2 Hands Up! Spreadshirt Introduction Spreadshirt Introduction: Java Ecosystem and Language Powerful Ecosystem Poor


slide-1
SLIDE 1

Spreadshirt

Kotlin in Practice

Philipp Hauer, Fabian Sudau Spreadshirt

JUG Saxony Camp 2017

slide-2
SLIDE 2

Spreadshirt 2

Spreadshirt

slide-3
SLIDE 3

Spreadshirt

Hands Up!

slide-4
SLIDE 4

Spreadshirt

Introduction

slide-5
SLIDE 5

Spreadshirt

Introduction: Java Ecosystem and Language

Powerful Ecosystem Poor Language

5

Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY

slide-6
SLIDE 6

Spreadshirt

Introduction: Java Ecosystem and Language

Powerful Ecosystem Powerful Language

6

Icons made by Freepik from www.flaticon.com is licensed by CC 3.0 BY

slide-7
SLIDE 7

Spreadshirt

Ecosystem vs. Language

7

slide-8
SLIDE 8

Spreadshirt

Introduction: Kotlin

  • By JetBrains
  • 2011
  • Open-Source
  • Characteristics:

Statically Typed

Object-Oriented

Many Functional Concepts

8

  • Compiled to Java Bytecode
  • Runs on the Java Virtual Machine (JVM)
  • “Pragmatic”
slide-9
SLIDE 9

Spreadshirt

Language Features

slide-10
SLIDE 10

Spreadshirt

Language Features: Immutability

Support for immutability built-in

// mutable state - use rarely var mutableList = mutableListOf(1, 2, 3) mutableList.add(4)

10

// ‘immutable’ state - generally recommended val readonlyList = listOf(1, 2, 3) readonlyList.add(4) readonlyList = listOf(1, 2, 3, 4) → Immutability feels defaultish, encourages better design → Still 100% Java compatible due to interface-based approach

slide-11
SLIDE 11

Spreadshirt

Language Features: Data Classes

Concise Data Containers

// implies sensible defaults for equals(...), hashCode(), toString() data class Person(val firstName: String, var age: Int, val title: Title = Title.UNKNOWN)

11

val jon = Person(firstName = "Jon", age = 18, title = Title.MR) val defaultJon = Person(firstName = "Jon", age = 18) val jack = jon.copy(firstName = "Jack") println(jack.firstName) // prints ‘Jack’ jack.age = 19 // assignment of var jack.firstName = "Joseph" // illegal, field is immutable

→ Plain Java equivalent requires 91 LOC!

slide-12
SLIDE 12

Spreadshirt

Language Features: Null Safety

“Billion dollar mistake” in Java: Kotlin proposes an alternative

var name: String = "Jon" println(name.length) name = null // does not compile

12

var nullableName: String ? = "Jon" println(nullableName.length) // does not compile println(nullableName?.length) // 3 or null println(nullableName?.length ?: 0) // 3 or 0 if (nullableName != null) { println(nullableName.length) // compiler infers safety } nullableName = null // compiles

slide-13
SLIDE 13

Spreadshirt

Language Features: Type Inference

13

Local type inference (compromise)

fun doubleLength(str: String): Int { val stringLength = str.length // == val stringLength: Int = str.length return stringLength * 2 }

Single Expression Functions

fun doubleLength(str: String) = str.length * 2 // return type inferred

Inference on immediate assignment

class Foo{ val bar = "baz" // == val bar: String = "baz" }

slide-14
SLIDE 14

Spreadshirt

Language Features: Devs just wanna have fun

14

Top-Level Functions

// Hello World.kt fun main(args: Array<String>) { println("Hello World") }

Extension functions

// definition fun String.wrap(wrapWith: String) = wrapWith + this + wrapWith // usage val wrapped = "hello".wrap("*") // as opposed to: val wrapped = StringUtils.wrap( "hello", "*")

// HelloWorld.java public class HelloWorld { public static void main(String[] args) { System.out.println( "Hello World"); } }

slide-15
SLIDE 15

Spreadshirt

Language Features: Devs just wanna have fun

15

Proper function types

fun foo(provideString: () -> String, consumeString: (String) -> Int): Int { return consumeString(provideString()) }

Concise Lambdas

fun safe(code: () -> Unit) { try { code() } catch(e: Exception) { log.ERROR( "Exception t_t", e) } } // usage safe { println("Hello World") }

slide-16
SLIDE 16

Spreadshirt

Language Features: Smart Pattern Matching

16

When - A better Switch Case

// myInt: Int val x = when (myInt) { 0 -> "zero" 1, 2 -> "one or two" in 3..10 -> "small number" in 11..Int.MAX_VALUE -> "large number" else -> "negative number" } enum class Mode { ON, OFF, IDLE } fun messageForMode(mode: Mode) = when (mode) { Mode.ON -> "Turning on" Mode.OFF -> "Turning off" } // error: 'when' expression is not exhaustive

slide-17
SLIDE 17

Spreadshirt

Kotlin at Spreadshirt: Evaluation

slide-18
SLIDE 18

Spreadshirt

Welcome to the Enterprise: No Changes without Careful Consideration

18

Pros Cons Reuse Java ecosystem (big deal!) Niche Reuse beloved Java frameworks & libs Know-how required Easy to learn: Conservative language concepts Risk: Unexpected complications? Less error prone: NPEs and mutable state easier to avoid Future of language highly depends on JetBrains Conciseness: Improved maintainability, less developer frustration .. but we already have Scala

Management Matrix ™

slide-19
SLIDE 19

Spreadshirt

Giving it a Try

19

Start small:

  • Migrate a system test suite from Java to Kotlin
  • Carve out “misplaced” functionality from a Java monolith to

a Kotlin based microservice

  • Re-evaluate based on this experience

Advantages significant enough to use Kotlin for the next project?

slide-20
SLIDE 20

Spreadshirt

Kotlin at Spreadshirt: Usage

slide-21
SLIDE 21

Spreadshirt

Kotlin Usage at Spreadshirt

5 new services purely written in Kotlin 1 Java service enriched with Kotlin

21

slide-22
SLIDE 22

Spreadshirt

Kotlin Usage at Spreadshirt

Kotlin in conjunction with popular Java frameworks and tools Jackson

22

slide-23
SLIDE 23

Spreadshirt

Taking Advantage

  • f Kotlin in Practice
slide-24
SLIDE 24

Spreadshirt

Putting Classes Together

Java Kotlin

24

slide-25
SLIDE 25

Spreadshirt

Concise Mapping between Model Classes

data class SnippetEntity( val code: String, val author: AuthorEntity, val date: Instant ) data class AuthorEntity( val firstName: String, val lastName: String ) data class SnippetDTO( val code: String, val author: String, val date: Instant )

25

Icon made by Freepik from www.flaticon.com is licensed by CC 3.0 BY

slide-26
SLIDE 26

Spreadshirt

Concise Mapping between Model Classes

fun mapToDTO(entity: SnippetEntity) = SnippetDTO( code = entity.code, date = entity.date, author = "${entity.author.firstName} ${entity.author.lastName}" )

26

Icon made by Freepik from www.flaticon.com is licensed by CC 3.0 BY

slide-27
SLIDE 27

Spreadshirt

Value Objects

//without value object: fun send(target: String){}

27

//expressive, readable, safe fun send(target: EmailAddress){} //with value object: data class EmailAddress(val value: String)

slide-28
SLIDE 28

Spreadshirt

//Java: Table myTable = new Table("MyTable", container); myTable.setSizeFull(); myTable.setColumnHeader("code", "Code"); myTable.setColumnHeader("date", "Date"); myTable.addGeneratedColumn("code", ShortValueColumnGenerator); myTable.setConverter("date", StringToInstantConverter);

Vaadin: Structuring UI Definition with apply()

28

slide-29
SLIDE 29

Spreadshirt

Vaadin: Structuring UI Definition with apply()

//Kotlin: val myTable = Table("MyTable", container).apply { setSizeFull() setColumnHeader("code", "Code") setColumnHeader("date", "Date") addGeneratedColumn("code", ShortenedValueColumnGenerator) setConverter("date", StringToInstantConverter) }

29

slide-30
SLIDE 30

Spreadshirt

val layout = FormLayout().apply { setMargin(true) isSpacing = true val codeLabel = Label().apply { caption = "Code" value = "Select * From dual;" } val stateLabel = Label().apply { caption = "State" value = "${icon} Successfully executed" } val closeButton = Button( "Close").apply { addClickListener { close() } } addComponents(codeLabel, stateLabel, closeButton) }

30

Vaadin: Structuring UI Definition with apply()

slide-31
SLIDE 31

Spreadshirt

Vaadin: Extension Functions to Add UI Logic

fun SnippetState.toIcon() = when (this){ SnippetState.EXECUTED -> FontAwesome.THUMBS_O_UP SnippetState.NOT_EXECUTED -> FontAwesome.THUMBS_O_DOWN } //usage: val icon = state.toIcon()

31

enum class SnippetState {EXECUTED, NOT_EXECUTED}

slide-32
SLIDE 32

Spreadshirt

Popular Java Idioms and Patterns are Built-in

32

Java Idiom or Pattern Idiomatic Solution in Kotlin Getter, Setter, Backing Field Properties Static Utility Class Top-Level (extension) functions Immutability, Value Objects data class with Immutable Properties, copy() Fluent Setter (Wither) Named and Default Arguments, apply() Method Chaining Default Arguments Singleton

  • bject

Delegation Delegated Properties by Lazy Initialization Delegated Properties by: lazy() Observer Delegated Properties by: observable()

slide-33
SLIDE 33

Spreadshirt

Drawbacks and Pitfalls

slide-34
SLIDE 34

Spreadshirt

Trouble with Object Mapping and XML

34

  • JAXB (XML) requires parameterless constructor ↯ Kotlin
  • Jackson (JSON) supports parameterless constructors.

But poor and buggy XML support

data class SnippetDTO(val code: String, val author: String) val snippet = Snippet()

  • Can’t find data class working for all use cases:

Jackson

XML and JSON

Serialization and Deserialization

Nasty XML structure

  • Solution: Different data classes for Serialization and

Deserialization

slide-35
SLIDE 35

Spreadshirt

Final by Default

35

  • Some frameworks rely on extension of classes

Spring

Mockito

  • Solutions:

Open classes and methods explicitly

Open-all-plugin for Kotlin compiler

class CustomerService { fun findCustomer(id: Int){ //... } }

  • pen class CustomerService {
  • pen fun findCustomer(id: Int){

//... } }

Can’t be extended by subclasses! Works!

slide-36
SLIDE 36

Spreadshirt

Pitfalls with Auto-Discovery via Reflection

36

  • Java: file path = package

package net.sprd.ServiceA;

  • Kotlin: no such requirement
  • Copy and Paste class EventController to serviceB

package net.sprd.ServiceA

EventController not found!

slide-37
SLIDE 37

Spreadshirt

Conclusion

slide-38
SLIDE 38

Spreadshirt

Conclusion

38

  • Programming for the JVM never felt so satisfying
  • We saved ~75% of the code
  • Several best practices were more prevalent in Kotlin
  • Spring ecosystem worked well
  • XML data binding was a major pain point and cost us days

→ Use of Kotlin will continue at Spreadshirt

slide-39
SLIDE 39

Spreadshirt

Questions?