Slide 1

Slide 1 text

@ToddGinsberg Write Less Code with Kotlin and Spring Boot October 7, 2019 Austin Convention Center Todd Ginsberg Principal Software Developer, Netspend

Slide 2

Slide 2 text

@ToddGinsberg Kotlin and Spring Boot in 30 Minutes?!

Slide 3

Slide 3 text

@ToddGinsberg Kotlin and Spring Boot in 30 Minutes?! No, that’s crazy!

Slide 4

Slide 4 text

@ToddGinsberg Kotlin and Spring Boot in 30 Minutes?! No, that’s crazy! But stick around after!

Slide 5

Slide 5 text

@ToddGinsberg Agenda - What Is Kotlin?

Slide 6

Slide 6 text

@ToddGinsberg Agenda - What Is Kotlin? - Why Kotlin with Spring Boot?

Slide 7

Slide 7 text

@ToddGinsberg Agenda - What Is Kotlin? - Why Kotlin with Spring Boot? - Syntax & Features

Slide 8

Slide 8 text

@ToddGinsberg Agenda - What Is Kotlin? - Why Kotlin with Spring Boot? - Syntax & Features - Summary

Slide 9

Slide 9 text

@ToddGinsberg Agenda - What Is Kotlin? - Why Kotlin with Spring Boot? - Syntax & Features - Summary - Questions?

Slide 10

Slide 10 text

@ToddGinsberg Who is this Guy? Todd Ginsberg

Slide 11

Slide 11 text

@ToddGinsberg Who is this Guy? Todd Ginsberg Just moved to Dallas from Chicago

Slide 12

Slide 12 text

@ToddGinsberg Who is this Guy? Todd Ginsberg Just moved to Dallas from Chicago Principal Developer at Netspend - A payments company here in Austin! - We love Kotlin and Java!

Slide 13

Slide 13 text

@ToddGinsberg What Is Kotlin?

Slide 14

Slide 14 text

@ToddGinsberg What Is Kotlin? Statically typed language, developed by JetBrains

Slide 15

Slide 15 text

@ToddGinsberg What Is Kotlin? Statically typed language, developed by JetBrains Released under Apache 2.0 license

Slide 16

Slide 16 text

@ToddGinsberg What Is Kotlin? Statically typed language, developed by JetBrains Released under Apache 2.0 license Designed as a general purpose language

Slide 17

Slide 17 text

@ToddGinsberg What Is Kotlin? Statically typed language, developed by JetBrains Released under Apache 2.0 license Designed as a general purpose language ● Targets JVM 6 or 8 bytecode

Slide 18

Slide 18 text

@ToddGinsberg What Is Kotlin? Statically typed language, developed by JetBrains Released under Apache 2.0 license Designed as a general purpose language ● Targets JVM 6 or 8 bytecode ● Targets ECMAScript 5.1

Slide 19

Slide 19 text

@ToddGinsberg What Is Kotlin? Statically typed language, developed by JetBrains Released under Apache 2.0 license Designed as a general purpose language ● Targets JVM 6 or 8 bytecode ● Targets ECMAScript 5.1 ● Targets other native platforms thanks to LLVM

Slide 20

Slide 20 text

@ToddGinsberg Major Features 100% Interoperable with Java

Slide 21

Slide 21 text

@ToddGinsberg Major Features 100% Interoperable with Java Designed to avoid entire classes of defects

Slide 22

Slide 22 text

@ToddGinsberg Major Features 100% Interoperable with Java Designed to avoid entire classes of defects Lots of small improvements that add up

Slide 23

Slide 23 text

@ToddGinsberg Major Features 100% Interoperable with Java Designed to avoid entire classes of defects Lots of small improvements that add up Far less code to accomplish the same task in Java

Slide 24

Slide 24 text

@ToddGinsberg Major Features Null-safe

Slide 25

Slide 25 text

@ToddGinsberg Major Features Null-safe 189,000+ issues on GitHub!

Slide 26

Slide 26 text

@ToddGinsberg Major Features Null-safe 189,000+ issues on GitHub! 14,548 duplicates on Stack Overflow!

Slide 27

Slide 27 text

@ToddGinsberg Major Features Pragmatic Improvements No shame in copying language features that make developers more productive

Slide 28

Slide 28 text

@ToddGinsberg Major Features Positive Community

Slide 29

Slide 29 text

@ToddGinsberg Major Features Positive Community Even on Stack Overflow!

Slide 30

Slide 30 text

@ToddGinsberg Major Features Positive Community Even on Stack Overflow! RTFM

Slide 31

Slide 31 text

@ToddGinsberg Why Kotlin with Spring Boot?

Slide 32

Slide 32 text

@ToddGinsberg The Hard Work is Already Done! - Kotlin Support since Spring Framework 5.0

Slide 33

Slide 33 text

@ToddGinsberg The Hard Work is Already Done! - Kotlin Support since Spring Framework 5.0 - Nullability support between Java and Kotlin

Slide 34

Slide 34 text

@ToddGinsberg The Hard Work is Already Done! - Kotlin Support since Spring Framework 5.0 - Nullability support between Java and Kotlin - Excellent documentation

Slide 35

Slide 35 text

@ToddGinsberg The Hard Work is Already Done! - Kotlin Support since Spring Framework 5.0 - Nullability support between Java and Kotlin - Excellent documentation - Thorough examples

Slide 36

Slide 36 text

@ToddGinsberg The Hard Work is Already Done! - Kotlin Support since Spring Framework 5.0 - Nullability support between Java and Kotlin - Excellent documentation - Thorough examples - Even better support being added for Spring Boot 2.2

Slide 37

Slide 37 text

@ToddGinsberg Similar Philosophies “The goal of library design is to give application developers ready-to-use tools that cover their most frequent use-cases and solve the most popular problems. If something is needed all the time by any kind of application, it should be simple and straightforward to code. The correct code shall be the easiest one to write, while advanced, rarely needed corner-cases can and should take longer.”

Slide 38

Slide 38 text

@ToddGinsberg Similar Philosophies “The goal of library design is to give application developers ready-to-use tools that cover their most frequent use-cases and solve the most popular problems. If something is needed all the time by any kind of application, it should be simple and straightforward to code. The correct code shall be the easiest one to write, while advanced, rarely needed corner-cases can and should take longer.” -- Roman Elizarov (JetBrains)

Slide 39

Slide 39 text

@ToddGinsberg Less Code == More Room For Business Value - Less code means less cognitive load

Slide 40

Slide 40 text

@ToddGinsberg Less Code == More Room For Business Value - Less code means less cognitive load - The most common case is the default

Slide 41

Slide 41 text

@ToddGinsberg Less Code == More Room For Business Value - Less code means less cognitive load - The most common case is the default - Fewer places for bugs to hide

Slide 42

Slide 42 text

@ToddGinsberg Less Code == More Room For Business Value - Less code means less cognitive load - The most common case is the default - Fewer places for bugs to hide - Work that you once had to do is a top level concern of the language / framework

Slide 43

Slide 43 text

@ToddGinsberg Less Code == More Room For Business Value - Less code means less cognitive load - The most common case is the default - Fewer places for bugs to hide - Work that you once had to do is a top level concern of the language / framework - These effects stack

Slide 44

Slide 44 text

@ToddGinsberg Syntax

Slide 45

Slide 45 text

@ToddGinsberg Variables and Values var place: String = "Austin"

Slide 46

Slide 46 text

@ToddGinsberg Variables and Values var place: String = "Austin" place = "Texas" // OK!

Slide 47

Slide 47 text

@ToddGinsberg Variables and Values var place: String = "Austin" place = "Texas" // OK! val name: String = "Todd"

Slide 48

Slide 48 text

@ToddGinsberg Variables and Values var place: String = "Austin" place = "Texas" // OK! val name: String = "Todd" name = "Emma" // Compile Error!

Slide 49

Slide 49 text

@ToddGinsberg Type Inference val d: Int = 2 val text: String = "Todd has $d doughnuts"

Slide 50

Slide 50 text

@ToddGinsberg Type Inference val d: Int = 2 val text: String = "Todd has $d doughnuts"

Slide 51

Slide 51 text

@ToddGinsberg Type Inference val d = 2 val text = "Todd has $d doughnuts"

Slide 52

Slide 52 text

@ToddGinsberg Equality val name1 = "EXAMPLE" val name2 = "example"

Slide 53

Slide 53 text

@ToddGinsberg Equality val name1 = "EXAMPLE" val name2 = "example" // Structural Equality name1 == name2.toUpperCase() // True!

Slide 54

Slide 54 text

@ToddGinsberg Equality val name1 = "EXAMPLE" val name2 = "example" // Structural Equality name1 == name2.toUpperCase() // True! // Referential Equality name1 === name2 // False!

Slide 55

Slide 55 text

@ToddGinsberg Raw Strings val json = "{\n\"name\": \"Todd\"\n}"

Slide 56

Slide 56 text

@ToddGinsberg Raw Strings val json = "{\n\"name\": \"Todd\"\n}" val json = """{ "name": "Todd" }"""

Slide 57

Slide 57 text

@ToddGinsberg Raw Strings val json = "{\n\"name\": \"Todd\"\n}" val json = """ { "name": "Todd" } """

Slide 58

Slide 58 text

@ToddGinsberg Null Safety // Guaranteed to never be null var name: String = "Todd"

Slide 59

Slide 59 text

@ToddGinsberg Null Safety // Guaranteed to never be null var name: String = "Todd" // May be null var salary: Int? = null

Slide 60

Slide 60 text

@ToddGinsberg Null-Safe Traversal var city: String? = "Austin"

Slide 61

Slide 61 text

@ToddGinsberg Null-Safe Traversal var city: String? = "Austin" // Not allowed, might be null! city.toUpperCase()

Slide 62

Slide 62 text

@ToddGinsberg Null-Safe Traversal var city: String? = "Austin" // Not allowed, might be null! city.toUpperCase() // Safe traversal city?.toUpperCase()

Slide 63

Slide 63 text

@ToddGinsberg Elvis val lowest : Int? = listOf(1, 2, 3).min()

Slide 64

Slide 64 text

@ToddGinsberg Elvis val lowest : Int? = listOf(1, 2, 3).min() val lowest : Int = listOf(1, 2, 3).min() ?: 0

Slide 65

Slide 65 text

@ToddGinsberg Combine Safe-Traversal and Elvis println( city?.toUpperCase() ?: ”UNKNOWN” )

Slide 66

Slide 66 text

@ToddGinsberg Manual Override val lowest: Int? = listOf(1, 2, 3).min()

Slide 67

Slide 67 text

@ToddGinsberg Hey Kotlin, Hold My Beer! val lowest: Int? = listOf(1, 2, 3).min() val lowest: Int = listOf(1, 2, 3).min()!!

Slide 68

Slide 68 text

@ToddGinsberg Hey Kotlin, Hold My Beer! val lowest: Int? = listOf(1, 2, 3).min() val lowest: Int = listOf(1, 2, 3).min()!! val lowest: Int = emptyList().min()!!

Slide 69

Slide 69 text

@ToddGinsberg Hey Kotlin, Hold My Beer! val lowest: Int? = listOf(1, 2, 3).min() val lowest: Int = listOf(1, 2, 3).min()!! val lowest: Int = emptyList().min()!! // NullPointerException!

Slide 70

Slide 70 text

@ToddGinsberg Expressions - if val status = if (code == 42) { "Success" } else { "Fail" }

Slide 71

Slide 71 text

@ToddGinsberg Expressions - try/catch val number = try { code.toInt() } catch (e: NumberFormatException) { 0 }

Slide 72

Slide 72 text

@ToddGinsberg Expressions - when val result = when (x) { 0 -> "x is 0” in 1..10 -> "x is between 1 and 10" in someSet -> "x is in someSet" is SomeType -> "x is an instance of SomeType" parseString(s) -> "the same as parseString" else -> "x doesn't match anything" }

Slide 73

Slide 73 text

@ToddGinsberg Smart Casting when (x) { is Int -> print(x % 2 == 0) is String -> print(x.length + 1) is IntArray -> print(x.sum()) }

Slide 74

Slide 74 text

@ToddGinsberg Smart Casting when (x) { is Int -> print(x % 2 == 0) is String -> print(x.length + 1) is IntArray -> print(x.sum()) }

Slide 75

Slide 75 text

@ToddGinsberg Smart Casting if(x != null) { println(x.toString()) }

Slide 76

Slide 76 text

@ToddGinsberg Classes class Entity : SomeInterface { // ... }

Slide 77

Slide 77 text

@ToddGinsberg Classes - Inheritance open class Entity : SomeInterface { // ... } class Customer : Entity() { // ... }

Slide 78

Slide 78 text

@ToddGinsberg Properties public class Customer { private String name; public String getName() { return name; } public void setName(final String name) { this.name = name; } }

Slide 79

Slide 79 text

@ToddGinsberg Properties class Customer { var name: String? = null }

Slide 80

Slide 80 text

@ToddGinsberg Properties class Customer { var name: String? = null } val c = Customer()

Slide 81

Slide 81 text

@ToddGinsberg Properties class Customer { var name: String? = null } val c = Customer() c.name = "Todd"

Slide 82

Slide 82 text

@ToddGinsberg Properties class Customer { var name: String? = null } val c = Customer() c.name = "Todd" println("My name is ${c.name}")

Slide 83

Slide 83 text

@ToddGinsberg Properties class Customer { var name: String? = null }

Slide 84

Slide 84 text

@ToddGinsberg Properties class Customer { var name: String? = null set(value) { field = value?.toUpperCase() } }

Slide 85

Slide 85 text

@ToddGinsberg Properties class Customer { var name: String? = null private set(value) { field = value?.toUpperCase() } }

Slide 86

Slide 86 text

@ToddGinsberg Properties class Customer { var name: String? = null get() { return field?.toUpperCase() } }

Slide 87

Slide 87 text

@ToddGinsberg Let’s Write a POJO! public class Person { public String firstName; public String lastName; }

Slide 88

Slide 88 text

@ToddGinsberg Let’s Write a POJO! public class Person { private String firstName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(final String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(final String lastName) { this.lastName = lastName; } }

Slide 89

Slide 89 text

@ToddGinsberg Let’s Write a POJO! public class Person { private String firstName; private String lastName; public Person() { } public Person(final String firstName, final String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(final String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(final String lastName) { this.lastName = lastName; } }

Slide 90

Slide 90 text

@ToddGinsberg Let’s Write a POJO! import java.util.Objects; public class Person { private String firstName; private String lastName; public Person() { } public Person(final String firstName, final String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(final String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(final String lastName) { this.lastName = lastName; } @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final Person person = (Person) o; return Objects.equals(firstName, person.firstName) && Objects.equals(lastName, person.lastName); } @Override public int hashCode() { return Objects.hash(firstName, lastName); } }

Slide 91

Slide 91 text

@ToddGinsberg Let’s Write a POJO! import java.util.Objects; public class Person { private String firstName; private String lastName; public Person() { } public Person(final String firstName, final String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public void setFirstName(final String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(final String lastName) { this.lastName = lastName; } @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final Person person = (Person) o; return Objects.equals(firstName, person.firstName) && Objects.equals(lastName, person.lastName); } @Override public int hashCode() { return Objects.hash(firstName, lastName); } @Override public String toString() { return "Person{" + "firstName='" + firstName + '\'' + ", lastName='" + lastName + '\'' + '}'; } }

Slide 92

Slide 92 text

@ToddGinsberg Data Classes to the Rescue! data class Person(val firstName: String, val lastName: String)

Slide 93

Slide 93 text

@ToddGinsberg Data Classes to the Rescue! data class Person(val firstName: String, val lastName: String) ● Getters (and Setters for vars) as Properties

Slide 94

Slide 94 text

@ToddGinsberg Data Classes to the Rescue! data class Person(val firstName: String, val lastName: String) ● Getters (and Setters for vars) as Properties ● toString()

Slide 95

Slide 95 text

@ToddGinsberg Data Classes to the Rescue! data class Person(val firstName: String, val lastName: String) ● Getters (and Setters for vars) as Properties ● toString() ● hashCode() and equals()

Slide 96

Slide 96 text

@ToddGinsberg Data Classes to the Rescue! data class Person(val firstName: String, val lastName: String) ● Getters (and Setters for vars) as Properties ● toString() ● hashCode() and equals() ● And…

Slide 97

Slide 97 text

@ToddGinsberg Copying Data Classes val me = Person("Todd", "Ginsberg")

Slide 98

Slide 98 text

@ToddGinsberg Copying Data Classes val me = Person("Todd", "Ginsberg") val emma = me.copy(firstName = "Emma") // Person(”Emma", "Ginsberg")

Slide 99

Slide 99 text

@ToddGinsberg Data Classes as @ConfigurationProperties @ConfigurationProperties("example.kotlin") data class KotlinExampleProperties( val name: String, val description: String = "Defaults Supported!", val myService: MyService ) data class MyService( val apiToken: String, val uri: URI )

Slide 100

Slide 100 text

@ToddGinsberg Data Classes as @ConfigurationProperties @ConfigurationProperties("example.kotlin") data class KotlinExampleProperties( val name: String, val description: String = "Defaults Supported!", val myService: MyService ) data class MyService( val apiToken: String, val uri: URI ) Boot 2.2!

Slide 101

Slide 101 text

@ToddGinsberg FUNctions! fun generateRandomNumber(): Int { return 4 }

Slide 102

Slide 102 text

@ToddGinsberg FUNctions! fun generateRandomNumber(): Int { return 4 } fun generateRandomNumber(): Int = 4

Slide 103

Slide 103 text

@ToddGinsberg FUNctions! fun generateRandomNumber(): Int { return 4 } fun generateRandomNumber(): Int = 4 fun generateRandomNumber() = 4

Slide 104

Slide 104 text

@ToddGinsberg FUNctions - Default Values fun random(offset: Int = 0): Int = offset + 4

Slide 105

Slide 105 text

@ToddGinsberg FUNctions - Default Values fun random(offset: Int = 0): Int = offset + 4 random() // 4

Slide 106

Slide 106 text

@ToddGinsberg FUNctions - Default Values fun random(offset: Int = 0): Int = offset + 4 random() // 4 random(1) // 5

Slide 107

Slide 107 text

@ToddGinsberg FUNctions - Adding Parameters fun combine(first: Int, second: Int): Int = first + second

Slide 108

Slide 108 text

@ToddGinsberg FUNctions - Adding Parameters fun combine(first: Int, second: Int, third: Int = 0): Int = first + second + third

Slide 109

Slide 109 text

@ToddGinsberg FUNctions - Adding Parameters fun combine(first: Int, second: Int, third: Int = 0): Int = first + second + third combine(1, 2) combine(1, 2, 3)

Slide 110

Slide 110 text

@ToddGinsberg FUNctions - Named Parameters fun combine(first: Int, second: Int): Int = first + second

Slide 111

Slide 111 text

@ToddGinsberg FUNctions - Named Parameters fun combine(first: Int, second: Int): Int = first + second combine(1, 2) // 3

Slide 112

Slide 112 text

@ToddGinsberg FUNctions - Named Parameters fun combine(first: Int, second: Int): Int = first + second combine(first = 1, second = 2) // 3

Slide 113

Slide 113 text

@ToddGinsberg FUNctions - Named Parameters fun combine(first: Int, second: Int): Int = first + second combine(second = 2, first = 1) // 3

Slide 114

Slide 114 text

@ToddGinsberg Extension FUNctions // Java public static boolean isEven(int i) { return i % 2 == 0; }

Slide 115

Slide 115 text

@ToddGinsberg Extension FUNctions // Kotlin fun Int.isEven(): Boolean = this % 2 == 0

Slide 116

Slide 116 text

@ToddGinsberg Extension FUNctions // Kotlin fun Int.isEven(): Boolean = this % 2 == 0 2.isEven() // True!

Slide 117

Slide 117 text

@ToddGinsberg The use Extension // Java try (Connection conn = getConnection()) { // ... }

Slide 118

Slide 118 text

@ToddGinsberg The use Extension // Kotlin getConnection().use { conn -> // ... }

Slide 119

Slide 119 text

@ToddGinsberg The apply Extension // Expression and Statements val p = Person() p.name = "Todd" p.age = 21

Slide 120

Slide 120 text

@ToddGinsberg The apply Extension // Single Expression val p = Person().apply { name = "Todd" age = 21 }

Slide 121

Slide 121 text

@ToddGinsberg The apply Extension // Single Expression val p = Person().apply { name = "Todd" age = 21 address = Address().apply { line1 = "5 Tall Cedar Rd." … } }

Slide 122

Slide 122 text

@ToddGinsberg One More Thing on FUNctions ● Functions are final by default.

Slide 123

Slide 123 text

@ToddGinsberg One More Thing on FUNctions ● Functions are final by default. ● Arguments are always final.

Slide 124

Slide 124 text

@ToddGinsberg One More Thing on FUNctions ● Functions are final by default. ● Arguments are always final. ● Functions can be defined in a file, outside of a class.

Slide 125

Slide 125 text

@ToddGinsberg One More Thing on FUNctions ● Functions are final by default. ● Arguments are always final. ● Functions can be defined in a file, outside of a class. ● Functions can be defined within another function.

Slide 126

Slide 126 text

@ToddGinsberg One More Thing on FUNctions ● Functions are final by default. ● Arguments are always final. ● Functions can be defined in a file, outside of a class. ● Functions can be defined within another function. ● Kotlin supports tail recursive functions.

Slide 127

Slide 127 text

@ToddGinsberg What About Checked Exceptions? ?

Slide 128

Slide 128 text

@ToddGinsberg What About Checked Exceptions? NO

Slide 129

Slide 129 text

@ToddGinsberg Lambdas listOf(1, 2, 3, 4) .filter { x -> x % 2 == 0 } .map { y -> y * 2 } // List[4, 8]

Slide 130

Slide 130 text

@ToddGinsberg Lambdas listOf(1, 2, 3, 4) .filter { x -> x % 2 == 0 } .map { y -> y * 2 } // List[4, 8]

Slide 131

Slide 131 text

@ToddGinsberg Lambdas listOf(1, 2, 3, 4) .filter { it % 2 == 0 } .map { it * 2 } // List[4, 8]

Slide 132

Slide 132 text

@ToddGinsberg So Many Things Left Out! :( - Property delegation - Class delegation - Operator overloading - Destructuring - Higher-order functions - Companion objects - Import aliases - Type aliases - Unsigned integer types - Coroutines - Massive STDLIB replaces your util classes - Reified generics - Inline classes - Infix functions - Sealed classes - Scoping functions - DSL support

Slide 133

Slide 133 text

@ToddGinsberg Summary

Slide 134

Slide 134 text

@ToddGinsberg Why Do I Use Kotlin? ● I write far less code.

Slide 135

Slide 135 text

@ToddGinsberg Why Do I Use Kotlin? ● I write far less code. ● The code I write is more expressive and clear.

Slide 136

Slide 136 text

@ToddGinsberg Why Do I Use Kotlin? ● I write far less code. ● The code I write is more expressive and clear. ● I avoid whole classes of defects.

Slide 137

Slide 137 text

@ToddGinsberg Why Do I Use Kotlin? ● I write far less code. ● The code I write is more expressive and clear. ● I avoid whole classes of defects. ● Plays well with the tools I use (Spring, IDEA, Gradle)

Slide 138

Slide 138 text

@ToddGinsberg Why Do I Use Kotlin? ● I write far less code. ● The code I write is more expressive and clear. ● I avoid whole classes of defects. ● Plays well with the tools I use (Spring, IDEA, Gradle) ● Writing Kotlin, for me, is more fun.

Slide 139

Slide 139 text

@ToddGinsberg Fun == Fun % of developers who are developing with the language or technology but have not expressed interest in continuing to do so (Stack Overflow Developer Survey 2019)

Slide 140

Slide 140 text

@ToddGinsberg Fun == Fun % of developers who are developing with the language or technology but have not expressed interest in continuing to do so (Stack Overflow Developer Survey 2019) Kotlin

Slide 141

Slide 141 text

@ToddGinsberg Make “Bad” Choices Explicit or Impossible Fixed in Kotlin: -Singleton support built in -Override keyword mandatory -Properties over fields with getter/setter -Mutability is minimized (val + collections) -Inheritance prohibited by default -Builders are easy with default values -No checked exceptions -Structural equality is the same everywhere -Delegation support makes composition easier

Slide 142

Slide 142 text

@ToddGinsberg Want to Learn More? https://play.kotlinlang.org

Slide 143

Slide 143 text

@ToddGinsberg Want to Learn More? The State of Kotlin Support in Spring Go back in time for this (or check it out on YouTube next week!)

Slide 144

Slide 144 text

@ToddGinsberg Want to Learn More? Fully Reactive: Spring, Kotlin, and JavaFX Playing Together Today from 4:20pm–5:30pm In this room!

Slide 145

Slide 145 text

@ToddGinsberg Want to Learn More? Klingon Kotlin (in Anger, er, Passion) with Project Reactor and Spring Boot: Ha' HIja'! Tomorrow from 11:30am–12:40pm In this room!

Slide 146

Slide 146 text

#springone @s1p @ToddGinsberg [email protected] https://todd.ginsberg.com http://bit.ly/S1P2019-Kotlin Thank You!