Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tips and tricks for adopting Kotlin

Tips and tricks for adopting Kotlin

Kotlin is the new cool kid in town, but there is not a lot of information out there on the process of adopting it as a company.
In this talk we are going to show why and how we started using Kotlin in N26, focusing on a service written from scratch by the Barcelona team, and discussing some of the lessons learned in the process.
At the end we are going to close with a quick 5 step guide on how your Kotlin migration can be successful and a Q&A.

Uriel Salischiker

May 02, 2019
Tweet

More Decks by Uriel Salischiker

Other Decks in Programming

Transcript

  1. Why Kotlin? Null safety 一 Aimed at removing null references

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

    一 Avoiding The Billion Dollar Mistake 一 Clearer APIs Tips and tricks for adopting Kotlin
  3. 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
  4. 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<String> strOptional = Optional.of("I’m a string!"); Optional<String> strOptional = Optional.ofNullable("I’m a string!"); String contents = strOptional.orElse("I was null :c"); String contents2 = strOptional2.orElse("I was null :c");
  5. Why Kotlin? Immutability 一 Immutability by default Tips and tricks

    for adopting Kotlin 一 Clear mutability on properties
  6. Why Kotlin? Immutability Tips and tricks for adopting Kotlin val

    immutableList = List<String>() val mutableList = MutableList<String>() Collections
  7. Why Kotlin? Immutability Tips and tricks for adopting Kotlin val

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

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

    finalStr = "string" var mutableStr = "string" finalStr = "something else" //Fails mutableStr = "something else" // Works Properties
  10. Why Kotlin? Data classes Tips and tricks for adopting Kotlin

    一 Reducing boilerplate 一 Human comprehension is the key
  11. 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
  12. 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
  13. 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
  14. 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
  15. 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
  16. 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
  17. 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
  18. 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
  19. 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
  20. 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
  21. Why Kotlin? Data classes data class Pet( val name: String,

    var office: String? = “Berlin” ) Tips and tricks for adopting Kotlin
  22. 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; } }
  23. Why Kotlin? Data classes Tips and tricks for adopting Kotlin

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

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

    data class Fee(val amount: Int, val country: String) val ukFee = Fee(10, "GBR")
  26. 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")
  27. 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)
  28. 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)
  29. 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) {
  30. 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
  31. 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
  32. 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<Key, Value> entry: map.entries()
  33. 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<Key, Value> entry: map.entries() }
  34. 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<Key, Value> entry: map.entries() }
  35. 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<Key, Value> entry: map.entries() }
  36. 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<Key, Value> entry: map.entries() } data class Result(val result: Int, val status: Status)
  37. 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<Key, Value> entry: map.entries() } data class Result(val result: Int, val status: Status) val (result, status) = ...
  38. Why Kotlin? One language Multiple platforms 一 Compiles to native

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

    code, javascript, JVM 一 Client and Server can share code Tips and tricks for adopting Kotlin
  40. 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
  41. 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
  42. Why Kotlin? Open source 一 Fully open source 一 Backed

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

    by Jetbrains 一 Language proposals KEEP Tips and tricks for adopting Kotlin
  44. “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
  45. Why Kotlin? Interoperability with Java 一 100% compatible with Java

    一 Easier to migrate in steps Tips and tricks for adopting Kotlin
  46. 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
  47. Why Kotlin? Cleaner functional programming 一 Extensive base library 一

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

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

    Collection processing 一 Sequences: Better streams 一 Ranges Tips and tricks for adopting Kotlin
  50. 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
  51. 一 Lombok 一 KAPT 一 Change of mentality and way

    of coding Tips and tricks for adopting Kotlin Why NOT Kotlin?
  52. 一 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?
  53. “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
  54. Why Not Kotlin? Tips and tricks for adopting Kotlin -

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

    Developers are not as experienced - Bad Kotlin code is uglier than Java
  56. Talks 一 Lighting talks 一 Get Stuff Done Days projects

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

    一 Initial gotchas Tips and tricks for adopting Kotlin
  58. Tests 一 Migrating tests to kotlin 一 Kotlin Junit &

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

    mockito-kotlin Tips and tricks for adopting Kotlin Tip Check KotlinTest and MockK!
  60. Migrating services 一 Small services: Transaction Notifications 一 Automatic conversion

    using Intellij IDEA 一 Manual changes to make it more idiomatic Tips and tricks for adopting Kotlin
  61. New services 一 New architecture 一 Shared libraries 一 New

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

    plugin Tips and tricks for adopting Kotlin
  63. Codestyle 一 No set code style 一 Java Static analysis

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

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

    tools 一 Kotlin Static analysis tools 一 Team conventions Tips and tricks for adopting Kotlin
  66. Jooq 一 Custom converters 一 Runs after kotlin 一 Requires

    code to compile Tips and tricks for adopting Kotlin
  67. 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
  68. 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
  69. Sealed classes sealed class Fee( val id: FeeId ) data

    class ActiveFee(val id: FeeId): Fee(id) Tips and tricks for adopting Kotlin
  70. 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
  71. 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
  72. 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
  73. 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
  74. Generics inline val <reified T> T.log: Logger get() = LoggerFactory.getLogger(T::class.java)

    class Foo { fun bar() { log.info("No need to create instances, only import") } }
  75. Generics interface Source<out T> { //Covariant fun nextT(): T }

    fun demo(strs: Source<String>) { val objects: Source<Any> = strs // This is OK, since T is an out-parameter // ... }
  76. Generics interface Comparable<in T> { //Contravariant operator fun compareTo(other: T):

    Int } fun demo(x: Comparable<Number>) { 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<Double> val y: Comparable<Double> = x // OK! }
  77. 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’
  78. Delegated properties val lazyValue: String by lazy { println("computed!") "Hello"

    } fun main() { println(lazyValue) println(lazyValue) } //computed //Hello //Hello
  79. Delegated properties class User { var name: String by Delegates.observable("<no

    name>") { prop, old, new -> println("$old -> $new") } } fun main() { val user = User() user.name = "first" user.name = "second" }
  80. Delegated properties class User(val map: Map<String, Any?>) { 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
  81. 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() } }
  82. Constants 一 Java -> static final 一 Kotlin -> ?

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

    const val FOO = "foo" Tips and tricks for adopting Kotlin
  84. Companion objects 一 Extra boilerplate 一 Performance penalty 一 Uglier

    code on Java Tips and tricks for adopting Kotlin
  85. 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
  86. DSL and Extension functions abuse 一 Leads to god objects

    一 DSL for everything might not be as readable Tips and tricks for adopting Kotlin
  87. 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
  88. 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
  89. DSL and Extension functions abuse class HouseBuilder { internal val

    people = mutableListOf<Person>() internal val items = mutableListOf<Item>() 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<House>() 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)
  90. Generics 一 Difficult to change mindset 一 * everywhere 一

    out vs in confusion Tips and tricks for adopting Kotlin
  91. Testing libraries 一 All classes are final by default 一

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

    Used mockito Tips and tricks for adopting Kotlin Tip Check MockK and KotlinTest!
  93. 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
  94. Reflection abuse val numberRegex = "\\d+".toRegex() println(numberRegex.matches("29")) val isNumber =

    numberRegex::matches println(isNumber("29")) Tips and tricks for adopting Kotlin
  95. Immutability 一 We shouldn’t just use Mutable everywhere 一 Change

    of mindset Tips and tricks for adopting Kotlin
  96. 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
  97. Code style - No set code style - Intellij doesn’t

    follow Kotlin guidelines completely by default(!) Tips and tricks for adopting Kotlin
  98. Learn the basics 一 Base concepts 一 Common patterns 一

    Open source code Tips and tricks for adopting Kotlin
  99. Tests 一 Start writing tests in Kotlin 一 Migrate small

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

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

    一 Increases app quality 一 Team happiness! Tips and tricks for adopting Kotlin
  102. 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
  103. 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
  104. 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