Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Kotlin: maybe it's the right time

493 views

Published on

After 20 years, Java seems to feel the weight of the years and his syntax it isn't evolved as we live. But the JVM it is always a stable environment and it is often in production everywhere. In the past years, there were many languages based on the JVM, but they don't have a lot of success. Kotlin conquered Android and, now, thanks to an easy syntax many and big companies behind it, may be used also in web development, also as full stack language. During this talk, we will give a look the language and how to use it to develop a production ready web application.
All code showed during presentation is here: https://github.com/jesty/kotlin-fossavotabona

Published in: Software
  • My son was struggling with GCSE revision and being a typical boy his desire to stay inside and study was not too high on the agenda! His maths has always been pretty average, and he has always had very little confidence in his mathematical abilities. Jeevan's programme is excellent. The break down of all mathematical problems has completely changed the way my son approaches his work and he is no longer doubting his ability. I have no doubt that this programme is the best there is and would have complete confidence in recommending it to anyone studying GCSE maths. On a side note, Jeevan is a perfect gentleman. He is very approachable, kind and generous with his advice. An efficient young man who truly cares about what he is offering. If you purchase this programme, you will certainly not be disappointed. ▲▲▲ http://t.cn/AirrSv7D
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • I have found your program really helpful. It is so easy to understand. It makes far more sense than school teachers ever did. I desperately need a 'C' grade and with your package, I am bang on this pass rate. With a bit more revision, it will be a comfortable pass. Thanks Jeevan! ♥♥♥ http://t.cn/AirraVnG
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

Kotlin: maybe it's the right time

  1. 1. Kotlin: maybe it’s the right time Davide Cerbo - Entaksi CODEMOTION MILAN - SPECIAL EDITION 10 – 11 NOVEMBER 2017
  2. 2. Chi sono Hi, my name is Davide and I’m writing bad code since I was 7. Since 2003 I’m paid for that.
  3. 3. Disclaimer Here we have a lot of println, and some jokes. My wife said that they aren’t funny.
  4. 4. C’era una volta OAK It was 1992 and in Italy there was a big scandal: Tangentopoli.
  5. 5. C’era una volta OAK Java Borns in 1995 and now can drink beers.
  6. 6. Il grande problema Backward compatibility (The art of killing your app because the environment evolve while you can’t) JDK 1.0 (21 january 1996) JDK 1.1 (19 february 1997) J2SE 1.2 (8 december 1998) J2SE 1.3 (8 my 2000) J2SE 1.4 (6 february 2002) J2SE 5.0 (30 september 2004) Java SE 6 (11 december 2006) Java SE 7 (28 july 2011) Java SE 8 (18 march 2014) Java SE 9 (26 september 2017) Tutte compatibili!
  7. 7. JVM != Java JAVA JVM
  8. 8. JVM != Java class Hello { fun sayHello(): String { return "hello!" } } public final class Hello { // access flags 0x11 public final sayHello()Ljava/lang/String; @Lorg/jetbrains/annotations/NotNull;() // invisible L0 LINENUMBER 8 L0 LDC "hello!" ARETURN L1 LOCALVARIABLE this Ltotest/Hello; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x1 public <init>()V L0 LINENUMBER 6 L0 ALOAD 0 INVOKESPECIAL java/lang/Object.<init> ()V RETURN L1 LOCALVARIABLE this L/Hello; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 @Lkotlin/Metadata;(mv={1, 1, 1}, bv={1, 0, 2}, k=1, d1={"u0000u0012nu0002u0018u0002nu0002u0010u0000nu0002 u0008u0002nu0002u0010u000enu0000u0018u00002u00020u00 01Bu0005u00a2u0006u0002u0010u0002Ju0006u0010u0003u001 au00020u0004u00a8u0006u0005", d2={"L/Hello;", "", "()V", "sayHello", "", "production sources for module coroutine_main"}) // compiled from: Hello.kt } @Metadata( mv = {1, 1, 7}, bv = {1, 0, 2}, k = 1, d1 = {"u0000u0012nu0002u0018u0002nu0002 u0005¢u0006u0002u0010u0002Ju0006u00 d2 = {"Ltotest/Hello;", "", "()V", "sayHello", "", " ) public final class Hello { @NotNull public final String sayHello() { return "hello!"; } } Compile Decompile
  9. 9. Machine code is not enought? Assembly languages Machine code Logic languages (Prolog) Functional languages (Haskell) Procedural languages (C) Object-oriented languages (Java) The Case for Kotlin and Ceylon by Russel Winder https://www.youtube.com/watch?v=cFL_DDXBkJQ
  10. 10. Why Kotlin? Hey! People said the same about Scala in the past. So why not Scala?
  11. 11. So, why not Scala? Kotlin is a better Java while Scala is more powerful than Java, and probably than Kotlin. But, Kotlin borns in the industry for the industry and it evolves with the industry in mind, while Scala borns at the university and it is adapted to the industry. Unfortunately, we work for the industry. https://agilewombat.com/2016/02/01/scala-vs-kotlin/ https://superkotlin.com/kotlin-vs-scala/
  12. 12. Kotlin is a statically-typed programming language that runs on the Java Virtual Machine and also can be compiled to JavaScript source code or uses the LLVM compiler infrastructure.
  13. 13. https://dzone.com/articles/why-learn-kotlin-infographic Since 2010(2012): KOTLIN!
  14. 14. 04 Gennaio 2017 Introducing Kotlin support in Spring Framework 5.0 https://spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0 https://github.com/sdeleuze/spring-kotlin-deepdive
  15. 15. 17 Maggio 2017 Kotlin on Android. Now official https://blog.jetbrains.com/kotlin/2017/05/kotlin-on-android-now-official/ http://nilhcem.com/swift-is-like-kotlin/
  16. 16. 5 Giugno 2017 kotlin-react borns! https://github.com/JetBrains/kotlin-wrappers/commits/master/kotlin-react https://github.com/JetBrains/create-react-kotlin-app
  17. 17. 1.0 Release 1.1 Release Kotlin is born Gradle Android Official Spring Statische download
  18. 18. Please shutdown the lights
  19. 19. Var o Val var serie = "B" var a = "Salernitana will win Serie $serie" val b = "Salernitana will win Serie $serie"
  20. 20. Fun fun main(args: Array<String>){ hello("Davide", "Salerno") } fun hello(name: String, city: String){ println("Hello $name from $city") }
  21. 21. Fun fun functions fun hello(name: String, city: String = "Salerno") = println("Hello $name from $city") hello("Davide", "Salerno") hello(name = "Davide") hello(city = "Salerno", name = "Valentina") fun Int.multilpy(x: Int): Int = this * x // 5.multilpy(10) infix fun Int.multilpy(x: Int): Int = this * x // 5 multilpy 10 Aiuta anche nel refactoring!
  22. 22. E gli operatori? data class Point(val x: Int, val y: Int) { operator fun plus(a: Point) = Point(x + a.x, y + a.y) } operator fun Point.unaryMinus() = Point(-x, -y) val point = Point(10, 20) println(point + point + point) //Point(x=30, y=60) println(-point) // Point(x=-10, y=-20)
  23. 23. Tailrec ● Rercursion, in some language, can cause: StackOverflow! ● Reduce stack execution. ● Tailrec will resolve this issue only if the recursive call is the last one. ● How? Transform your code in imperative code. Less readable, but more fast. ● Performance improvement fun factorial(n: Long): Long = if (n <= 1L) n else n * factorial(n - 1) tailrec fun factorial(n: Long, accumulator: Long = 1): Long = if (n <= 1L) accumulator else factorial(n - 1, accumulator * n) Tailrec cannot applicable “If” will return the verified condition value
  24. 24. Tailrec decompiled public static final long factorial(long n, long accumulator) { while(n > 1L) { long var10000 = n - 1L; accumulator *= n; n = var10000; } return accumulator; } public static long factorial$default(long var0, long var2, int var4, Object var5) { if((var4 & 2) != 0) { var2 = 1L; } return factorial(var0, var2); } } public static final long factorial(long n, long accumulator) { return n <= 1L?accumulator:factorial(n - 1L, accumulator * n); } public static long factorial$default(long var0, long var2, int var4, Object var5) { if((var4 & 2) != 0) { var2 = 1L; } return factorial(var0, var2); } With Tailrec Without Tailrec StackOverflow Tools > Kotlin > Show Kotlin Bytecode > Decompile
  25. 25. Class open class Person(val name: String) { init { println("init…") } open fun speak() { println("Hi $name!") } infix fun and(o: Person) = "Hi ${o.name} & ${this.name}" } fun main(args: Array<String>) { Person("Davide") and Person("Valentina") val p = Person("Jack") p.speak() }
  26. 26. Class class Customer(name: String) : Person(name) { override fun speak() { println("Welcome $name!") } } class CustomerDavide : Person("Davide") { override fun speak() { println("Welcome $name!") } }
  27. 27. Equals, hashCode, toString e copy, nevermore! data class User(val name: String, val age: Int) val davide = User("Davide", 35) val davideJunior = davide.copy(age=0) fun main(args: Array<String>) { val (name, age) = davide println("$name $age years old") } deconstructing
  28. 28. Nothing is equal as appear data class Point(val x: Int, val y: Int) val a = Point(1, 2) val b = Point(1, 2) val c = a println(a === b) // false println(a == b) // true println(a === c) // true println(a == c) // true Controlla il riferimento .equals(...)
  29. 29. Lambda fun main(args: Array<String>) { arrayOf("Valentina", "Davide").forEach { println("Hello $it!") } val ints = arrayOf(1, 2, 3) val logger = { msg: Any -> println("log $msg") } ints.map { value -> value * 2 }.map { v -> logger(v) } ints.map { it * 2 }.map { logger(it) } }
  30. 30. Lambda class Customer(val name: String) { fun forEach(action: (char: Char) -> Unit) = name.forEach(action) fun hello(callback: (name: String) -> Unit) = callback(name) fun upperCaseAndConcat(callback: () -> String) = "${callback()} $name".toUpperCase() } fun main(args: Array<String>) { val customer = Customer("Davide") customer.hello { println("Ciao $it") } println(customer.upperCaseAndConcat { "Cerbo" }) customer.forEach { println(it) } } È il tipo con un solo valore vuoto. Corrisponde a void in Java.
  31. 31. Lambda & Function Label fun forEachTest() { val numbers = 1..100 numbers.forEach { if (it == 25) { return } println("index $it") } println("Hello") } fun forEachTest() { val numbers = 1..100 numbers.forEach { if (it == 25) { return@forEach } println("index $it") } println("Hello") } Vs.
  32. 32. Tell me when, when? fun describe(obj: Any): String = when (obj) { 1 -> "One" "Hello" -> "Greeting" is Long -> "Long" !is String -> "Not a string" else -> "Unknown" } describe(Person("davide"))
  33. 33. Null is safe! var testA:String = "ciao" var testB:String? = "ciao" testB = null val nullableList: List<Int?> = listOf(1, 2, null, 4) val intList: List<Int> = nullableList.filterNotNull() println("a0 ${testA.length}") println("a1 ${testA?.length}") println("a2 ${testA!!.length}") println("b0 ${testB.length}") // ^ Not safe! Compile time error! ^ println("b1 ${testB?.length}") println("b2 ${testB!!.length}") // ^ KotlinNullPointerException ^ // NPE Lovers
  34. 34. Null is safe! val nullableList: List<Int?> = listOf(1, 2, null, 4) val intList: List<Int> = nullableList.filterNotNull() // [1, 2, 4] val aInt: Int? = b as? Int // If b is null, normally we will will have a NullPointerException, while if the type is differente we will have a ClassCastExeption. Usin “as?” we haven’t exception, we will have a null value assigned to the aInt value.
  35. 35. Null è sicuro data class Person(val name: String, val age: Int?) val person:Person? = Person("Jack", 1) if (person?.age != null) { println("The person is aged ${person?.age}") } //oppure person?.age?.let { println("The person is aged $it") }
  36. 36. ?: Elvis operator val davide = Person(testA) val elvis = Person(testB ?: "Elvis") println(jack.name)
  37. 37. Get & Set class Strange(var value: Long) { var strangeValue: Long get() = value * 2 set(value){ if(value > 5) this.value = value } } fun main(args: Array<String>) { val customer = Strange(10) println(customer.strangeValue) //20 customer.strangeValue = 3 println(customer.strangeValue) //20 customer.strangeValue = 6 println(customer.strangeValue) //12 }
  38. 38. Delegated properties: non può farlo qualcun altro? class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, thank you for delegating '${property.name}' to me!" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value has been assigned to '${property.name} in $thisRef.'") } } class Example { var p: String by Delegate() }
  39. 39. Delegated properties: il pigro e l’osservabile val lazyValue: String by lazy { println("computed!") "Hello" } fun main(args: Array<String>) { println(lazyValue) println(lazyValue) } class User { var n: String by Delegates.observable("empty") { prop, old, new -> println("$old -> $new") } } fun main(args: Array<String>) { val user = User() user.n = "first" user.n = "second" }
  40. 40. Coroutine Coroutine ⋍ light-weight thread ● Are like threads, they run in parallel, wait for each other and they communicate. ● Area cheap, we can create many of those without having performance issues. ● Are executed in a thread pool. ● A thread can handle more than one coroutine. ● The thread became free while a coroutine is in waiting when the coroutine will return active, it will use a free thread in the pool. https://github.com/Kotlin/kotlinx.coroutines/blob/master/coroutines-guide.md https://proandroiddev.com/approaching-kotlin-coroutines-an-extensive-feature-concurrent-programming-in-kotlin-eaaa19b003d2
  41. 41. Coroutine sono oneste fun main(args: Array<String>) = runBlocking { val jobs = List(100_000) { launch { delay(1000L) print(".") } } jobs.forEach { it.join() } } fun main(args: Array<String>) { val jobs = List(100_000) { thread(start = true) { Thread.sleep(1000L) print(".") } } jobs.forEach { it.join() } } OUT OF MEMORY!!!
  42. 42. Coroutine: suspend, async / await fun main(args: Array<String>) = runBlocking<Unit> { val time = measureTimeMillis { val one = doSomethingUsefulOne() val two = doSomethingUsefulTwo() println("The answer is ${one + two}") } println("Completed in $time ms") } suspend fun doSomethingUsefulOne(): Int { delay(1000L) return 13 } suspend fun doSomethingUsefulTwo(): Int { delay(1000L) return 29 } fun main(args: Array<String>) = runBlocking<Unit> { val time = measureTimeMillis { val one = async { doSomethingUsefulOne() } val two = async { doSomethingUsefulTwo() } println("The answer is ${one.await() + two.await()}") } println("Completed in $time ms") } suspend fun doSomethingUsefulOne(): Int { delay(1000L) return 13 } suspend fun doSomethingUsefulTwo(): Int { delay(1000L) return 29 } ~2 sec. ~1 sec.
  43. 43. Coroutine is the basement Coroutine Actors Communication Sequence Process ?
  44. 44. Testing class GreeterTest { @Mock lateinit var user: User lateinit var tested: Greeter @Before fun setUp() { MockitoAnnotations.initMocks(this) tested = Greeter(user) } @Test fun englishGreetIsCorrect() { whenever(user.fullName()).thenReturn("Codemotion") assertEquals("Hello Codemotion!", tested.getGreeting()) } } all values are final by default. With lateinit the compiler knows that someone will intialize it later. Mockito.`when` is not the best choice with Kotlin. The cause is that Kotlin avoid null, and can cause issues with .any() mehtod. The “whenever” method is part of mockito-kotlin libary. backticks are used when the method name is a reserved word.
  45. 45. Testing: Mockito-Kotlin class GreeterTest { val user: User = mock { on { fullName() }.then { "Codemotion" } } val tested: Greeter = Greeter(user) @Test fun `english greeting is correct`() { assertEquals("Hello, Codemotion!", tested.getGreeting()) } }
  46. 46. Testing: Kluent class GreeterTest3 { val user: User = mock { on { fullName() }.then { "Codemotion" } } val tested: Greeter = Greeter(user) @Test fun `english greeting is correct`() { tested.getGreeting() `should equal` "Hello, Codemotion!" } @Test fun `cannot smoke`() { val davide = User("Davide", "Cerbo") val davideSmoke = { davide.smoke() } davideSmoke `should throw` RuntimeException::class `with message` "Cannot smoke!" } }
  47. 47. Testing dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:$kotlin_version" testCompile "org.mockito:mockito-core:2.8.9" testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version" testCompile 'de.jodamob.kotlin:kotlin-runner-junit4:0.3.1' testCompile "com.nhaarman:mockito-kotlin-kt1.1:1.5.0" testCompile 'org.amshove.kluent:kluent:1.30' } https://proandroiddev.com/improve-your-tests-with-kotlin-in-android-pt-1-6d0b04017e80 https://proandroiddev.com/improve-your-tests-with-kotlin-in-android-pt-2-f3594e5e7bfd https://proandroiddev.com/improve-your-tests-with-kotlin-in-android-pt-3-104e1c9f77cc
  48. 48. Now is the time to remember that Kotlin is good because the trade-off between synthesis and readable code is really good.
  49. 49. Automatic restart
  50. 50. Webapp: Gradle buildscript { ... dependencies { ... classpath "org.jetbrains.kotlin:kotlin-noarg:$kotlinVersion" } } ... apply plugin: "kotlin-jpa" group = 'it.devday' version = '0.0.1-SNAPSHOT' ... } JPA need an empty constructor in some entities, and Kotlin objects don’t have. To solve this issue we can use this plugin that will create an empty constructor in any object, without any change to our codebase.
  51. 51. Webapp: Domain & Repository import it.devday.kotlincodemotion.domain.Contact import org.springframework.data....JpaRepository interface ContactRepository: JpaRepository<Contact, Long> import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.Id @Entity data class Contact( @Id @GeneratedValue val id: Long, val name: String, val surname: String)
  52. 52. Webapp: Resource 1/2 @RestController @RequestMapping("/contacts") class ContactResource(val contactRepository: ContactRepository) { @GetMapping //curl -XGET http://localhost:8080/contacts fun getAll() = contactRepository.findAll() @GetMapping("/{id}") //curl -XGET http://localhost:8080/contacts/1 fun getAll(@PathVariable id: Long) = contactRepository.findById(id)
  53. 53. Webapp: Resource 2/2 @PostMapping //curl -XPOST http://localhost:8080/contacts -H 'Content-Type: application/json' -d '{"name":"Davide", "surname":"Cerbo"}' fun insert(@RequestBody contact: Contact) = contactRepository.save(contact) @DeleteMapping("/{id}") //curl -XDELETE http://localhost:8080/contacts/1 fun delete(@PathVariable id: Long) { val contact = contactRepository.findById(id).unwrap() contact?.let { contactRepository.delete(contact) } } } aspetta...unwrap() non esiste su Optional
  54. 54. Webapp: Application @SpringBootApplication class KotlinCodemotionApplication fun <T> Optional<T>.unwrap(): T? = orElse(null) fun main(args: Array<String>) { runApplication<KotlinCodemotionApplication>(*args) } ecco unwrap()! array is passed element by element, it is used with vararg arguments public inline fun <reified T : kotlin.Any> runApplication(vararg args: kotlin.String) The generic type will be avaible in the method. Wow!
  55. 55. Hey, I’m a frontend developer, where is my code?
  56. 56. $ create-react-kotlin-app kotlin-codemotion-front $ cd kotlin-codemotion-from $ yarn start https://github.com/jetbrains/create-react-kotlin-app https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-react/README.md https://github.com/JetBrains/kotlin-wrappers/blob/master/kotlin-react-dom/README.md https://github.com/Kotlin/kotlin-fullstack-sample https://github.com/JetBrains/kotlinconf-app https://blog.frankel.ch/kotlin-front-end-developers/#gsc.tab=0 https://github.com/sdeleuze/spring-kotlin-deepdive Kotlin React: Application
  57. 57. React is a framework made by Facebook to build UI. Is the View in the MVC pattern. It simple associate a state to a specific UI. Your UI will change regarding your state. Kotlin React: Stop! What is React? {name: “Davide”, color: “red”} Hi Davide! {name: “Jack”, color: “green”} Hi Jack!
  58. 58. Kotlin React: Application: Component definition interface ContactListProps : RProps { var owner: String } interface ContactListState : RState { var list: Array<Contact> } class ContactList(props: ContactListProps) : RComponent<ContactListProps, ContactListState>(props) { override fun ContactListState.init(props: ContactListProps) { list = emptyArray() } ...
  59. 59. Kotlin React: Application: Data loading override fun componentDidMount() { async { val listData = httpGet("/contacts") setState { list = JSON.parse<Array<Contact>>(listData) } } } remember to define the proxy in package.json: "proxy": "http://localhost:8080"
  60. 60. Kotlin React: Application: UI rendering override fun RBuilder.render() { div("ContactList-header") { key = "contactListHeader" h2 { +"${props.owner}'s contact list" } ul { for (c in state.list) { li { +"${c.id}: ${c.name} ${c.surname}" } } } } } } fun RBuilder.contactList(owner: String = "No-name") = child(ContactList::class) { attrs.owner = owner }
  61. 61. STOP!
  62. 62. What we miss? ● Spring WebFlux ● Reactor ● Android + Kotlin ● Native + Kotlin #byebyejava
  63. 63. Everything is here: https://github.com/jesty/kotlin-fossavotabona
  64. 64. Questions @davide_cerbo @devdayit http://slack.devday.it
  65. 65. Useful resources https://kotlinlang.org/docs/reference/ https://spring.io/blog/2017/01/04/introducing-kotlin-support-in-spring-framework-5-0 https://blog.jetbrains.com/kotlin/2017/05/kotlin-on-android-now-official/ https://dev.to/lovis/gang-of-four-patterns-in-kotlin https://github.com/volodymyrprokopyuk/kotlin-sdp https://github.com/gradle/gradle-script-kotlin https://speakerdeck.com/sdeleuze/functional-web-applications-with-spring-and-kotlin https://kotlinlang.org/docs/tutorials/httpservlets.html http://thetechnocafe.com/more-about-functions-in-kotlin/ https://nklmish.wordpress.com/2017/10/22/deprecated-in-kotlin/ https://kotlinlang.org/docs/tutorials/command-line.html https://agilewombat.com/2016/02/01/scala-vs-kotlin/ https://superkotlin.com/kotlin-vs-scala/ https://kotlinlang.org/docs/reference/type-safe-builders.html
  66. 66. Useful resources

×