Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

Tips and tricks for adopting Kotlin Uriel Salischiker - @urielsalis N26, Barcelona - May 2019

Slide 3

Slide 3 text

Uriel Salischiker Backend Engineer @ N26 @urielsalis - [email protected]

Slide 4

Slide 4 text

Uriel Salischiker Backend Engineer @ N26 @urielsalis - [email protected]

Slide 5

Slide 5 text

The first bank you will love

Slide 6

Slide 6 text

The first bank you will love We are hiring! https://n26.com/en/careers

Slide 7

Slide 7 text

z Introduction

Slide 8

Slide 8 text

Tips and tricks for adopting Kotlin Share your own at [email protected] This is my own experience

Slide 9

Slide 9 text

Our journey adopting Kotlin In our production environments

Slide 10

Slide 10 text

What we like about Kotlin

Slide 11

Slide 11 text

Why Kotlin? Null safety Tips and tricks for adopting Kotlin

Slide 12

Slide 12 text

Why Kotlin? Null safety 一 Aimed at removing null references Tips and tricks for adopting Kotlin

Slide 13

Slide 13 text

Why Kotlin? Null safety 一 Aimed at removing null references 一 Avoiding The Billion Dollar Mistake Tips and tricks for adopting Kotlin

Slide 14

Slide 14 text

Why Kotlin? Null safety 一 Aimed at removing null references 一 Avoiding The Billion Dollar Mistake 一 Clearer APIs Tips and tricks for adopting Kotlin

Slide 15

Slide 15 text

Why Kotlin? Null safety var str: String = "I’m a string!" str = null // Fails to compile var str2: String? = "I’m a nullable string!" str2 = null // Works! Tips and tricks for adopting Kotlin

Slide 16

Slide 16 text

Why Kotlin? Null safety var str: String = "I’m a string!" str = null // Fails to compile var str2: String? = "I’m a nullable string!" str2 = null // Works! Tips and tricks for adopting Kotlin Optional strOptional = Optional.of("I’m a string!"); Optional strOptional = Optional.ofNullable("I’m a string!"); String contents = strOptional.orElse("I was null :c"); String contents2 = strOptional2.orElse("I was null :c");

Slide 17

Slide 17 text

Why Kotlin? Immutability Tips and tricks for adopting Kotlin

Slide 18

Slide 18 text

Why Kotlin? Immutability 一 Immutability by default Tips and tricks for adopting Kotlin

Slide 19

Slide 19 text

Why Kotlin? Immutability 一 Immutability by default Tips and tricks for adopting Kotlin 一 Clear mutability on properties

Slide 20

Slide 20 text

Why Kotlin? Immutability Tips and tricks for adopting Kotlin val immutableList = List() val mutableList = MutableList() Collections

Slide 21

Slide 21 text

Why Kotlin? Immutability Tips and tricks for adopting Kotlin val immutableList = List() val mutableList = MutableList() immutableList.add("string") //Fails mutableList.add("string") //Works Collections

Slide 22

Slide 22 text

Why Kotlin? Immutability Tips and tricks for adopting Kotlin val finalStr = "string" var mutableStr = "string" Properties

Slide 23

Slide 23 text

Why Kotlin? Immutability Tips and tricks for adopting Kotlin val finalStr = "string" var mutableStr = "string" finalStr = "something else" //Fails mutableStr = "something else" // Works Properties

Slide 24

Slide 24 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin 一 Reducing boilerplate 一 Human comprehension is the key

Slide 25

Slide 25 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin

Slide 26

Slide 26 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters

Slide 27

Slide 27 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters ● Setters

Slide 28

Slide 28 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters ● Setters ● Constructor

Slide 29

Slide 29 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters ● Setters ● Constructor ● Equals

Slide 30

Slide 30 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters ● Setters ● Constructor ● Equals ● Hashcode

Slide 31

Slide 31 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters ● Setters ● Constructor ● Equals ● Hashcode ● ToString

Slide 32

Slide 32 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters ● Setters ● Constructor ● Equals ● Hashcode ● ToString ● Builder

Slide 33

Slide 33 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters ● Setters ● Constructor ● Equals ● Hashcode ● ToString ● Builder ● Copy

Slide 34

Slide 34 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin public class VideoGame { private String name; private String publisher; private int reviewScore; public VideoGame(String name, String publisher, int reviewScore) { this.name = name; this.publisher = publisher; this.reviewScore = reviewScore; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPublisher() { return publisher; } public void setPublisher(String publisher) { this.publisher = publisher; } public int getReviewScore() { return reviewScore; } public void setReviewScore(int reviewScore) { this.reviewScore = reviewScore; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; VideoGame that = (VideoGame) o; if (reviewScore != that.reviewScore) return false; if (name != null ? !name.equals(that.name) : that.name != null) { return false; } return publisher != null ? publisher.equals(that.publisher) : that.publisher == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (publisher != null ? publisher.hashCode() : 0); result = 31 * result + reviewScore; return result; } @Override public String toString() { return "VideoGame{" + "name='" + name + '\'' + ", publisher='" + publisher + '\'' + ", reviewScore=" + reviewScore + '}'; } Java data class VideoGame( val name: String, val publisher: String, var reviewScore: Int ) Kotlin ● Getters ● Setters ● Constructor ● Equals ● Hashcode ● ToString ● Builder ● Copy ● ComponentN

Slide 35

Slide 35 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin

Slide 36

Slide 36 text

Why Kotlin? Data classes data class Pet( val name: String, var office: String? = “Berlin” ) Tips and tricks for adopting Kotlin

Slide 37

Slide 37 text

Why Kotlin? Data classes data class Pet( val name: String, var office: String? = “Berlin” ) Tips and tricks for adopting Kotlin @Data @AllArgsConstructor public class Pet { @NonNull private final String name; private boolean office = "Berlin"; @Builder @SuppressWarnings("unused") private Pet(String name) { this.name = name; } }

Slide 38

Slide 38 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin

Slide 39

Slide 39 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String)

Slide 40

Slide 40 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String)

Slide 41

Slide 41 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR")

Slide 42

Slide 42 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA")

Slide 43

Slide 43 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee)

Slide 44

Slide 44 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee)

Slide 45

Slide 45 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) {

Slide 46

Slide 46 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) { // This is also done automatically for maps

Slide 47

Slide 47 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) { // This is also done automatically for maps // No need to do something like

Slide 48

Slide 48 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) { // This is also done automatically for maps // No need to do something like // Map.Entry entry: map.entries()

Slide 49

Slide 49 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) { // This is also done automatically for maps // No need to do something like // Map.Entry entry: map.entries() }

Slide 50

Slide 50 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) { // This is also done automatically for maps // No need to do something like // Map.Entry entry: map.entries() }

Slide 51

Slide 51 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) { // This is also done automatically for maps // No need to do something like // Map.Entry entry: map.entries() }

Slide 52

Slide 52 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) { // This is also done automatically for maps // No need to do something like // Map.Entry entry: map.entries() } data class Result(val result: Int, val status: Status)

Slide 53

Slide 53 text

Why Kotlin? Data classes Tips and tricks for adopting Kotlin data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR") val usaFee = ukFee.copy(country = "USA") val fees = listOf(ukFee, usaFee) for ((amount, country) in fees) { // This is also done automatically for maps // No need to do something like // Map.Entry entry: map.entries() } data class Result(val result: Int, val status: Status) val (result, status) = ...

Slide 54

Slide 54 text

Why Kotlin? One language Multiple platforms Tips and tricks for adopting Kotlin

Slide 55

Slide 55 text

Why Kotlin? One language Multiple platforms 一 Compiles to native code, javascript, JVM Tips and tricks for adopting Kotlin

Slide 56

Slide 56 text

Why Kotlin? One language Multiple platforms 一 Compiles to native code, javascript, JVM 一 Client and Server can share code Tips and tricks for adopting Kotlin

Slide 57

Slide 57 text

Why Kotlin? One language Multiple platforms 一 Compiles to native code, javascript, JVM 一 Client and Server can share code 一 Official Android language Tips and tricks for adopting Kotlin

Slide 58

Slide 58 text

Why Kotlin? One language Multiple platforms 一 Compiles to native code, javascript, JVM 一 Client and Server can share code 一 Official Android language 一 Supports iOS (more targets in the future) Tips and tricks for adopting Kotlin

Slide 59

Slide 59 text

Why Kotlin? Open source Tips and tricks for adopting Kotlin

Slide 60

Slide 60 text

Why Kotlin? Open source 一 Fully open source Tips and tricks for adopting Kotlin

Slide 61

Slide 61 text

Why Kotlin? Open source 一 Fully open source 一 Backed by Jetbrains Tips and tricks for adopting Kotlin

Slide 62

Slide 62 text

Why Kotlin? Open source 一 Fully open source 一 Backed by Jetbrains 一 Language proposals KEEP Tips and tricks for adopting Kotlin

Slide 63

Slide 63 text

“Adoption of a language depends more of its ecosystem than its features” Empirical analysis of programming languages adoption Meyerovich LA, Rabkin AS November 2013 Tips and tricks for adopting Kotlin

Slide 64

Slide 64 text

Tips and tricks for adopting Kotlin

Slide 65

Slide 65 text

Why Kotlin? Interoperability with Java Tips and tricks for adopting Kotlin

Slide 66

Slide 66 text

Why Kotlin? Interoperability with Java Tips and tricks for adopting Kotlin

Slide 67

Slide 67 text

Why Kotlin? Interoperability with Java 一 100% compatible with Java Tips and tricks for adopting Kotlin

Slide 68

Slide 68 text

Why Kotlin? Interoperability with Java 一 100% compatible with Java 一 Easier to migrate in steps Tips and tricks for adopting Kotlin

Slide 69

Slide 69 text

Why Kotlin? Interoperability with Java 一 100% compatible with Java 一 Easier to migrate in steps Tips and tricks for adopting Kotlin Note This doesn’t work as well with code generators like Lombok

Slide 70

Slide 70 text

Why Kotlin? Cleaner functional programming Tips and tricks for adopting Kotlin

Slide 71

Slide 71 text

Why Kotlin? Cleaner functional programming 一 Extensive base library Tips and tricks for adopting Kotlin

Slide 72

Slide 72 text

Why Kotlin? Cleaner functional programming 一 Extensive base library 一 Collection processing Tips and tricks for adopting Kotlin

Slide 73

Slide 73 text

Why Kotlin? Cleaner functional programming 一 Extensive base library 一 Collection processing 一 Sequences: Better streams Tips and tricks for adopting Kotlin

Slide 74

Slide 74 text

Why Kotlin? Cleaner functional programming 一 Extensive base library 一 Collection processing 一 Sequences: Better streams 一 Ranges Tips and tricks for adopting Kotlin

Slide 75

Slide 75 text

Why Kotlin? Cleaner functional programming 一 Extensive base library 一 Collection processing 一 Sequences: Better streams 一 Ranges Tips and tricks for adopting Kotlin Tip Libraries like Arrow make this even better

Slide 76

Slide 76 text

Why Kotlin? Tips and tricks for adopting Kotlin

Slide 77

Slide 77 text

Tips and tricks for adopting Kotlin Why NOT Kotlin?

Slide 78

Slide 78 text

一 Lombok Tips and tricks for adopting Kotlin Why NOT Kotlin?

Slide 79

Slide 79 text

一 Lombok 一 KAPT Tips and tricks for adopting Kotlin Why NOT Kotlin?

Slide 80

Slide 80 text

一 Lombok 一 KAPT 一 Change of mentality and way of coding Tips and tricks for adopting Kotlin Why NOT Kotlin?

Slide 81

Slide 81 text

一 Lombok 一 KAPT 一 Change of mentality and way of coding 一 Patterns and Anti-Patterns are not set Tips and tricks for adopting Kotlin Why NOT Kotlin?

Slide 82

Slide 82 text

“I’m just playing with Kotlin as a kid with a new game, so I find a lot of possibilities of writing the same code in different ways, but no opinions yet” - Pull request comment Yesterday Tips and tricks for adopting Kotlin

Slide 83

Slide 83 text

Why Not Kotlin? Tips and tricks for adopting Kotlin

Slide 84

Slide 84 text

Why Not Kotlin? Tips and tricks for adopting Kotlin - Developers are not as experienced

Slide 85

Slide 85 text

Why Not Kotlin? Tips and tricks for adopting Kotlin - Developers are not as experienced - Bad Kotlin code is uglier than Java

Slide 86

Slide 86 text

History of Kotlin @ N26 Tips and tricks for adopting Kotlin

Slide 87

Slide 87 text

Talks Tips and tricks for adopting Kotlin

Slide 88

Slide 88 text

Talks 一 Lighting talks Tips and tricks for adopting Kotlin

Slide 89

Slide 89 text

Talks 一 Lighting talks 一 Get Stuff Done Days projects Tips and tricks for adopting Kotlin

Slide 90

Slide 90 text

Talks 一 Lighting talks 一 Get Stuff Done Days projects 一 Initial gotchas Tips and tricks for adopting Kotlin

Slide 91

Slide 91 text

Tech radar Tips and tricks for adopting Kotlin (not our real one)

Slide 92

Slide 92 text

Tests Tips and tricks for adopting Kotlin

Slide 93

Slide 93 text

Tests 一 Migrating tests to kotlin 一 Kotlin Junit & mockito-kotlin Tips and tricks for adopting Kotlin

Slide 94

Slide 94 text

Tests 一 Migrating tests to kotlin 一 Kotlin Junit & mockito-kotlin Tips and tricks for adopting Kotlin Tip Check KotlinTest and MockK!

Slide 95

Slide 95 text

Converting code Tips and tricks for adopting Kotlin

Slide 96

Slide 96 text

Migrating services Tips and tricks for adopting Kotlin

Slide 97

Slide 97 text

Migrating services 一 Small services: Transaction Notifications Tips and tricks for adopting Kotlin

Slide 98

Slide 98 text

Migrating services 一 Small services: Transaction Notifications 一 Automatic conversion using Intellij IDEA Tips and tricks for adopting Kotlin

Slide 99

Slide 99 text

Migrating services 一 Small services: Transaction Notifications 一 Automatic conversion using Intellij IDEA 一 Manual changes to make it more idiomatic Tips and tricks for adopting Kotlin

Slide 100

Slide 100 text

New services Tips and tricks for adopting Kotlin

Slide 101

Slide 101 text

New services 一 New architecture Tips and tricks for adopting Kotlin

Slide 102

Slide 102 text

New services 一 New architecture 一 Shared libraries Tips and tricks for adopting Kotlin

Slide 103

Slide 103 text

New services 一 New architecture 一 Shared libraries 一 New problems Tips and tricks for adopting Kotlin

Slide 104

Slide 104 text

Fee Service

Slide 105

Slide 105 text

Design challenges

Slide 106

Slide 106 text

Final by default Tips and tricks for adopting Kotlin

Slide 107

Slide 107 text

Final by default 一 Lots of open everywhere Tips and tricks for adopting Kotlin

Slide 108

Slide 108 text

Final by default 一 Lots of open everywhere 一 “all-open” plugin Tips and tricks for adopting Kotlin

Slide 109

Slide 109 text

Codestyle Tips and tricks for adopting Kotlin

Slide 110

Slide 110 text

Codestyle 一 No set code style Tips and tricks for adopting Kotlin

Slide 111

Slide 111 text

Codestyle 一 No set code style 一 Java Static analysis tools Tips and tricks for adopting Kotlin

Slide 112

Slide 112 text

Codestyle 一 No set code style 一 Java Static analysis tools 一 Kotlin Static analysis tools Tips and tricks for adopting Kotlin

Slide 113

Slide 113 text

Codestyle 一 No set code style 一 Java Static analysis tools 一 Kotlin Static analysis tools 一 Team conventions Tips and tricks for adopting Kotlin

Slide 114

Slide 114 text

Jooq Tips and tricks for adopting Kotlin

Slide 115

Slide 115 text

Jooq 一 Custom converters Tips and tricks for adopting Kotlin

Slide 116

Slide 116 text

Jooq 一 Custom converters 一 Runs after kotlin Tips and tricks for adopting Kotlin

Slide 117

Slide 117 text

Jooq 一 Custom converters 一 Runs after kotlin 一 Requires code to compile Tips and tricks for adopting Kotlin

Slide 118

Slide 118 text

Jooq Tips and tricks for adopting Kotlin

Slide 119

Slide 119 text

Jooq table("pet") { "pet_id" withTinyType CatId::class "owner_id" withTinyType OwnerId::class "price" withCustomConverter CurrencyConverter::class "purchase_date" withInstantTinyType PurchaseDate::class "branch" withEnum Branch::class } Tips and tricks for adopting Kotlin

Slide 120

Slide 120 text

New patterns

Slide 121

Slide 121 text

Sealed classes Tips and tricks for adopting Kotlin

Slide 122

Slide 122 text

Sealed classes 一 State machines defined on the domain Tips and tricks for adopting Kotlin

Slide 123

Slide 123 text

Sealed classes Tips and tricks for adopting Kotlin

Slide 124

Slide 124 text

Sealed classes sealed class RegisterResponse() Tips and tricks for adopting Kotlin

Slide 125

Slide 125 text

Sealed classes sealed class RegisterResponse() object SuccessfulResponse: RegisterResponse() class FailedResponse(val e: Exception): RegisterResponse() return when(response) { is SuccessfulResponse -> "All good!" is FailedResponse-> "All bad :C. $e" } Tips and tricks for adopting Kotlin

Slide 126

Slide 126 text

Sealed classes Tips and tricks for adopting Kotlin

Slide 127

Slide 127 text

Sealed classes sealed class Fee( Tips and tricks for adopting Kotlin

Slide 128

Slide 128 text

Sealed classes sealed class Fee( val id: FeeId Tips and tricks for adopting Kotlin

Slide 129

Slide 129 text

Sealed classes sealed class Fee( val id: FeeId ) Tips and tricks for adopting Kotlin

Slide 130

Slide 130 text

Sealed classes sealed class Fee( val id: FeeId ) Tips and tricks for adopting Kotlin

Slide 131

Slide 131 text

Sealed classes sealed class Fee( val id: FeeId ) data class ActiveFee(val id: FeeId): Fee(id) Tips and tricks for adopting Kotlin

Slide 132

Slide 132 text

Sealed classes sealed class Fee( val id: FeeId ) data class ActiveFee(val id: FeeId): Fee(id) data class DeactivatedFee(val id: FeeId): Fee(id) Tips and tricks for adopting Kotlin

Slide 133

Slide 133 text

Sealed classes sealed class Fee( val id: FeeId ) data class ActiveFee(val id: FeeId): Fee(id) data class DeactivatedFee(val id: FeeId): Fee(id) data class ProcessingFee(val id: FeeId): Fee(id) Tips and tricks for adopting Kotlin

Slide 134

Slide 134 text

Sealed classes sealed class Fee( val id: FeeId ) data class ActiveFee(val id: FeeId): Fee(id) data class DeactivatedFee(val id: FeeId): Fee(id) data class ProcessingFee(val id: FeeId): Fee(id) data class CompletedFee( val id: FeeId, val completed: Instant ): Fee(id) Tips and tricks for adopting Kotlin

Slide 135

Slide 135 text

Builders Tips and tricks for adopting Kotlin

Slide 136

Slide 136 text

Builders 一 Named builders Tips and tricks for adopting Kotlin

Slide 137

Slide 137 text

Builders 一 Named builders 一 Tests Tips and tricks for adopting Kotlin

Slide 138

Slide 138 text

Builders Tips and tricks for adopting Kotlin Ramon Nala and Benno

Slide 139

Slide 139 text

Builders Tips and tricks for adopting Kotlin

Slide 140

Slide 140 text

Builders data class Pet( val name: String, val office: String? = null ) val ramon = Pet("Ramon", "BCN") val benno = Pet("Benno") val nala = Pet(name = "Nala", office = "BLN") Tips and tricks for adopting Kotlin

Slide 141

Slide 141 text

Generics

Slide 142

Slide 142 text

Generics - Generic properties

Slide 143

Slide 143 text

Generics - Generic properties - Variance

Slide 144

Slide 144 text

Generics

Slide 145

Slide 145 text

Generics inline val T.log: Logger get() = LoggerFactory.getLogger(T::class.java) class Foo { fun bar() { log.info("No need to create instances, only import") } }

Slide 146

Slide 146 text

Generics

Slide 147

Slide 147 text

Generics

Slide 148

Slide 148 text

Generics //Java Collection //Invariant Collection extends Object> // Covariant ??? //Contravariant

Slide 149

Slide 149 text

Generics

Slide 150

Slide 150 text

Generics

Slide 151

Slide 151 text

Generics interface Source { //Covariant fun nextT(): T } fun demo(strs: Source) { val objects: Source = strs // This is OK, since T is an out-parameter // ... }

Slide 152

Slide 152 text

Generics

Slide 153

Slide 153 text

Generics

Slide 154

Slide 154 text

Generics interface Comparable { //Contravariant operator fun compareTo(other: T): Int } fun demo(x: Comparable) { x.compareTo(1.0) // 1.0 has type Double, which is a subtype of Number // Thus, we can assign x to a variable of type Comparable val y: Comparable = x // OK! }

Slide 155

Slide 155 text

Delegated properties 一 Lazy 一 Observable 一 Vetoable

Slide 156

Slide 156 text

Delegated properties

Slide 157

Slide 157 text

Delegated properties class Example(var p: String by Delegate()) class Delegate { operator fun getValue(thisRef: Any?, property: KProperty<*>): String { return "$thisRef, delegating '${property.name}'" } operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) { println("$value, '${property.name}' in $thisRef.") } } val e = Example() println(e.p) //Example@33a17727, delegating ‘p’

Slide 158

Slide 158 text

Delegated properties

Slide 159

Slide 159 text

Delegated properties val lazyValue: String by lazy { println("computed!") "Hello" } fun main() { println(lazyValue) println(lazyValue) } //computed //Hello //Hello

Slide 160

Slide 160 text

Delegated properties

Slide 161

Slide 161 text

Delegated properties class User { var name: String by Delegates.observable("") { prop, old, new -> println("$old -> $new") } } fun main() { val user = User() user.name = "first" user.name = "second" }

Slide 162

Slide 162 text

Delegated properties

Slide 163

Slide 163 text

Delegated properties class User(val map: Map) { val name: String by map val age: Int by map } val user = User(mapOf( "name" to "John Doe", "age" to 25 )) println(user.name) // Prints "John Doe" println(user.age) // Prints 25

Slide 164

Slide 164 text

Delegated properties

Slide 165

Slide 165 text

Delegated properties //Since Kotlin 1.1 fun example(computeFoo: () -> Foo) { val memoizedFoo by lazy(computeFoo) if (someCondition && memoizedFoo.isValid()) { //if someCondition is false, // memoizedFoo is never computed memoizedFoo.doSomething() } }

Slide 166

Slide 166 text

Delegated properties

Slide 167

Slide 167 text

Gotchas

Slide 168

Slide 168 text

Constants 一 Java -> static final 一 Kotlin -> ? Tips and tricks for adopting Kotlin

Slide 169

Slide 169 text

Constants 一 Java -> static final 一 Kotlin -> ? const val FOO = "foo" Tips and tricks for adopting Kotlin

Slide 170

Slide 170 text

Companion objects 一 Extra boilerplate 一 Performance penalty 一 Uglier code on Java Tips and tricks for adopting Kotlin

Slide 171

Slide 171 text

Companion objects Tips and tricks for adopting Kotlin class C { companion object { @JvmStatic fun foo() {} fun bar() {} } } C.foo(); // works fine C.bar(); // error: not a static method C.Companion.foo(); // instance method remains C.Companion.bar(); // the only way it works

Slide 172

Slide 172 text

DSL and Extension functions abuse 一 Leads to god objects 一 DSL for everything might not be as readable Tips and tricks for adopting Kotlin

Slide 173

Slide 173 text

DSL and Extension functions abuse val helloWorldInBrainf_ck = s[s { 7 }.r.a.l].r.s.o //-[------->+<]>-. .s[s.r.a { 5 }.l].r.a.a.o //-[->+++++<]>++. .a { 7 }.o.o //+++++++.. .a { 3 }.o[s.r.a { 5 }.l].r.a.o //+++.[->+++++<]>+. .s { 12 }.o //------------. .s { 3 }[s.r.a { 3 }.l].r.o //---[->+++<]>. .s[s { 3 }.r.a.l].r.s { 3 }.o //-[--->+<]>---. .a { 3 }.o //+++. .s { 6 }.o //------. .s { 8 }.o //--------. .s[s { 3 }.r.a.l].r.o //-[--->+<]>. Tips and tricks for adopting Kotlin

Slide 174

Slide 174 text

DSL and Extension functions abuse val v = village { house { "Alice" age 31 "Bob" age 45 500.gold } house { sword with strength value 24.2 sword with strength level 16.7 shield with defense value 15.3 } house() house { "Charles" age 52 2500.gold sword shield } } Tips and tricks for adopting Kotlin

Slide 175

Slide 175 text

DSL and Extension functions abuse class HouseBuilder { internal val people = mutableListOf() internal val items = mutableListOf() fun build(): House { return House(people, items) } infix fun String.age(age: Int) { people.add(Person(this, age)) } val Int.gold: Unit get() { items += Gold(this) return Unit } } class VillageBuilder { private val houses = mutableListOf() operator fun House.unaryPlus() { houses += this } fun house(setup: HouseBuilder.() -> Unit = {}) { val houseBuilder = HouseBuilder() houseBuilder.setup() houses += houseBuilder.build() } fun build(): Village { return Village(houses) } } fun village(setup: VillageBuilder.() -> Unit): Village { val villageBuilder = VillageBuilder() villageBuilder.setup() return villageBuilder.build() } Tips and tricks for adopting Kotlin class ShieldContinuation(val house: HouseBuilder) object defense val HouseBuilder.shield: ShieldContinuation get() { this.items += Shield(0.0) return ShieldContinuation(this) } infix fun ShieldContinuation.with(d: defense): ShieldBuilder { house.items.removeAt(house.items.lastIndex) return ShieldBuilder(house) } class ShieldBuilder(val house: HouseBuilder) infix fun ShieldBuilder.value(defense: Double) { house.items += Shield(defense) } class SwordContinuation(val house: HouseBuilder) object strength val HouseBuilder.sword: SwordContinuation get() { this.items += Sword(0.0) return SwordContinuation(this) } infix fun SwordContinuation.with(d: strength): SwordBuilder { house.items.removeAt(house.items.lastIndex) return SwordBuilder(house) } class SwordBuilder(val house: HouseBuilder) infix fun SwordBuilder.value(strength: Double) { house.items += Sword(strength) } infix fun SwordBuilder.level(strength: Double) = value(strength)

Slide 176

Slide 176 text

Generics 一 Difficult to change mindset 一 * everywhere 一 out vs in confusion Tips and tricks for adopting Kotlin

Slide 177

Slide 177 text

Testing libraries Tips and tricks for adopting Kotlin

Slide 178

Slide 178 text

Testing libraries 一 All classes are final by default Tips and tricks for adopting Kotlin

Slide 179

Slide 179 text

Testing libraries 一 All classes are final by default 一 Used mockito Tips and tricks for adopting Kotlin

Slide 180

Slide 180 text

Testing libraries 一 All classes are final by default 一 Used mockito Tips and tricks for adopting Kotlin Tip Check MockK and KotlinTest!

Slide 181

Slide 181 text

Jackson - Can’t serialize without a default constructor - Jackson-module-kotlin Tips and tricks for adopting Kotlin

Slide 182

Slide 182 text

Getters as properties 一 Might hide performance bugs Tips and tricks for adopting Kotlin

Slide 183

Slide 183 text

Reflection abuse 一 Easy reflection hides the performance penalty Tips and tricks for adopting Kotlin

Slide 184

Slide 184 text

Reflection abuse class A(val p: Int) fun main() { // prints "public final int A.getP()" println(A::p.javaGetter) // prints "private final int A.p" println(A::p.javaField) } Tips and tricks for adopting Kotlin

Slide 185

Slide 185 text

Reflection abuse val numberRegex = "\\d+".toRegex() println(numberRegex.matches("29")) val isNumber = numberRegex::matches println(isNumber("29")) Tips and tricks for adopting Kotlin

Slide 186

Slide 186 text

Immutability 一 We shouldn’t just use Mutable everywhere 一 Change of mindset Tips and tricks for adopting Kotlin

Slide 187

Slide 187 text

Performance cost 一 Hidden cost of lambdas • Inline to the rescue! 一 Local functions 一 Nullable primitives 一 Ranges(when there is indirection) Tips and tricks for adopting Kotlin

Slide 188

Slide 188 text

Code style - No set code style - Intellij doesn’t follow Kotlin guidelines completely by default(!) Tips and tricks for adopting Kotlin

Slide 189

Slide 189 text

Lessons learned

Slide 190

Slide 190 text

Kotlin champion Tips and tricks for adopting Kotlin

Slide 191

Slide 191 text

Kotlin champion 一 Designate a Kotlin champion Tips and tricks for adopting Kotlin

Slide 192

Slide 192 text

Kotlin champion 一 Designate a Kotlin champion 一 Kotlin Koans Tips and tricks for adopting Kotlin

Slide 193

Slide 193 text

Learn the basics Tips and tricks for adopting Kotlin

Slide 194

Slide 194 text

Learn the basics 一 Base concepts Tips and tricks for adopting Kotlin

Slide 195

Slide 195 text

Learn the basics 一 Base concepts 一 Common patterns Tips and tricks for adopting Kotlin

Slide 196

Slide 196 text

Learn the basics 一 Base concepts 一 Common patterns 一 Open source code Tips and tricks for adopting Kotlin

Slide 197

Slide 197 text

Tests Tips and tricks for adopting Kotlin

Slide 198

Slide 198 text

Tests 一 Start writing tests in Kotlin Tips and tricks for adopting Kotlin

Slide 199

Slide 199 text

Tests 一 Start writing tests in Kotlin 一 Migrate small services Tips and tricks for adopting Kotlin

Slide 200

Slide 200 text

Convincing Management Tips and tricks for adopting Kotlin

Slide 201

Slide 201 text

Convincing Management 一 The team is more productive with Kotlin Tips and tricks for adopting Kotlin

Slide 202

Slide 202 text

Convincing Management 一 The team is more productive with Kotlin 一 Increases app quality Tips and tricks for adopting Kotlin

Slide 203

Slide 203 text

Convincing Management 一 The team is more productive with Kotlin 一 Increases app quality 一 Team happiness! Tips and tricks for adopting Kotlin

Slide 204

Slide 204 text

Convincing Management 一 The team is more productive with Kotlin 一 Increases app quality 一 Team happiness! 一 The industry is moving to it Tips and tricks for adopting Kotlin

Slide 205

Slide 205 text

Convincing Management 一 The team is more productive with Kotlin 一 Increases app quality 一 Team happiness! 一 The industry is moving to it 一 Official Spring, Android & Gradle support Tips and tricks for adopting Kotlin

Slide 206

Slide 206 text

Effective Kotlin 一 Team needs to agree on patterns 一 With great flexibility comes great responsibility https://medium.com/@appmattus/effective-kotlin- 31215a6cf847 Tips and tricks for adopting Kotlin

Slide 207

Slide 207 text

Questions?

Slide 208

Slide 208 text

Questions?