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

Kotlin: from No to Yes

Kotlin: from No to Yes

cmonfortep

March 24, 2017
Tweet

Other Decks in Technology

Transcript

  1. • This is not Kotlin vs Java vs Scala •

    This is not a ‘how to use kotlin' talk
  2. Our first steps… we started with unit tests Some of

    us fell in love with Kotlin Kaizen Circle
  3. Our first steps… we started with unit tests Some of

    us fell in love with Kotlin Kaizen Circle I voted NO
  4. Our first steps… we started with unit tests Some of

    us fell in love with Kotlin Kaizen Circle I voted NO …but the team voted Yes
  5. • Scala was my personal bet • Nulls… • Learning

    while writing code in production • JetBrains support • how does kotlin coexist with android? • I don’t need kotlin…it’s only syntactic sugar • why only Android?
  6. • Hiring • Clients • Complex apps • Not an

    official language • Size of teams Concerns
  7. • Shared knowledge • Solving problems together • More resources

    for mentoring • PR reviewed by more people Good for big teams
  8. After 2 days…we received an email… …Asking us to STOP

    producing code in Kotlin The company has to decide too
  9. • 15% crashes are NPE • Be faster, Be concise,

    Be clean • Kotlin-Swift • New possibilities • Kotlin documentation and trainings • Remove third-party libs Pros
  10. • Tests / project libraries / module • Define conventions

    and tools • Refactor classes backed by tests • Everything new in kotlin Roll-out plan
  11. Nullability as a Type var nullableString: String? = "hello world"


    var length: Int = nullableString.length //compile error
 length = nullableString?.length //compile error
 length = nullableString?.length ?: 0
  12. Nullability as a Type var nullableString: String? = "hello world"


    var length: Int = nullableString.length //compile error
 length = nullableString?.length //compile error
 length = nullableString?.length ?: 0 if (nullableString != null) {
 length = nullableString.length
 length = nullableString?.length
 } length = nullableString!!.length
 length = nullableString.length
  13. Nullability as a Type var nullableString: String? = "hello world"


    var length: Int = nullableString.length //compile error
 length = nullableString?.length //compile error
 length = nullableString?.length ?: 0 if (nullableString != null) {
 length = nullableString.length
 length = nullableString?.length
 } length = nullableString!!.length
 length = nullableString.length var notNullString: String
 notNullString = null //compile error
 notNullString = StringGenerator.itsATrap() //boom!
  14. • concise, less verbose, string interpolation, smart cast, sealed classes,

    streams, lambdas, immutability first, kotlin size, static nullability checks, reduce common errors…
  15. let, apply, with, run fun printUserLet(user: User?): String {
 return

    user?.let { //(T) -> R
 it.formattedName()
 } ?: ""
 }
  16. let, apply, with, run fun printUserLet(user: User?): String {
 return

    user?.let { //(T) -> R
 it.formattedName()
 } ?: ""
 } fun printUserApply(user: User?): String {
 return user?.apply {//T.() -> Unit
 formattedName()
 }?.formattedName() ?: ""
 }
  17. let, apply, with, run fun printUserLet(user: User?): String {
 return

    user?.let { //(T) -> R
 it.formattedName()
 } ?: ""
 } fun printUserApply(user: User?): String {
 return user?.apply {//T.() -> Unit
 formattedName()
 }?.formattedName() ?: ""
 } fun printUserWith(user: User?): String {
 return with(user) {//T.() -> R
 this?.formattedName()
 } ?: ""
 }
  18. let, apply, with, run fun printUserLet(user: User?): String {
 return

    user?.let { //(T) -> R
 it.formattedName()
 } ?: ""
 } fun printUserApply(user: User?): String {
 return user?.apply {//T.() -> Unit
 formattedName()
 }?.formattedName() ?: ""
 } fun printUserWith(user: User?): String {
 return with(user) {//T.() -> R
 this?.formattedName()
 } ?: ""
 } fun printUserRun(user: User?): String {
 return user?.run {//T.() -> R
 formattedName()
 } ?: ""
 }
  19. JvmOverloads, named and default params @JvmOverloads fun dummyMethod(dummyString: String? =

    "", dummyBoolean: Boolean = true) {
 }
 
 fun dummyMethod(dummyLong: Long?, dummyBoolean: Boolean) {
 }
  20. JvmOverloads, named and default params @JvmOverloads fun dummyMethod(dummyString: String? =

    "", dummyBoolean: Boolean = true) {
 }
 
 fun dummyMethod(dummyLong: Long?, dummyBoolean: Boolean) {
 } public static void dummyCall() {
 DefaultParams.dummyMethod(null, true); //Ambiguous method call
 } fun sample() {
 dummyMethod(null, true) //Overload resolution ambiguity
 }
  21. JvmOverloads, named and default params @JvmOverloads fun dummyMethod(dummyString: String? =

    "", dummyBoolean: Boolean = true) {
 }
 
 fun dummyMethod(dummyLong: Long?, dummyBoolean: Boolean) {
 } fun sample() {
 dummyMethod(dummyString = null, dummyBoolean = true)
 } public static void dummyCall() {
 DefaultParams.dummyMethod(null, true); //Ambiguous method call
 } fun sample() {
 dummyMethod(null, true) //Overload resolution ambiguity
 }
  22. Extensions const val NO_FLAGS: Int = 0
 
 fun Activity.showKeyboard(flags:

    Int = NO_FLAGS) =
 (getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.apply {
 toggleSoftInput(InputMethodManager.SHOW_FORCED, flags)
 }
  23. Extensions const val NO_FLAGS: Int = 0
 
 fun Activity.showKeyboard(flags:

    Int = NO_FLAGS) =
 (getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.apply {
 toggleSoftInput(InputMethodManager.SHOW_FORCED, flags)
 } class keyboardActivity : AppCompatActivity() {
 override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 showKeyboard()
 }
 }
  24. High order methods fun Activity.getSharedPref(name: String = "DefaultSP",
 mode: Int

    = Context.MODE_PRIVATE): SharedPreferences {
 return getSharedPreferences(name, mode)
 } fun SharedPreferences.edit(func: SharedPreferences.Editor.() -> Unit) {
 val editor = edit()
 editor.func()
 editor.apply()
 }

  25. High order methods fun Activity.getSharedPref(name: String = "DefaultSP",
 mode: Int

    = Context.MODE_PRIVATE): SharedPreferences {
 return getSharedPreferences(name, mode)
 } fun SharedPreferences.edit(func: SharedPreferences.Editor.() -> Unit) {
 val editor = edit()
 editor.func()
 editor.apply()
 }
 class SharedPrefActivity : AppCompatActivity() {
 override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 
 getSharedPref().edit {
 putString("Location", "Madrid")
 putInt("Year", 2017)
 putBoolean("Visited", true)
 }
 }
 }
  26. Sealed class sealed class CustomException {
 object UnkownException : CustomException()


    class ParseException(val description: String) : CustomException()
 class NetworkException(val code: Int, val description: String) : CustomException()
 }
 
 fun manageExceptions(exception: CustomException) = when (exception) {
 CustomException.UnkownException -> println("no idea")
 is CustomException.ParseException -> println(exception.description)
 is CustomException.NetworkException -> println("${exception.code}: ${exception.description}")
 }
  27. Delegation interface InterfaceA {
 fun methodA()
 }
 
 interface InterfaceB

    {
 fun methodB()
 }
 
 class ImplA(val x: Int) : InterfaceA {
 override fun methodA() {
 print(x)
 }
 }
 
 class ImplB(val x: Int) : InterfaceB {
 override fun methodB() {
 print(x)
 }
 }
  28. Delegation interface InterfaceA {
 fun methodA()
 }
 
 interface InterfaceB

    {
 fun methodB()
 }
 
 class ImplA(val x: Int) : InterfaceA {
 override fun methodA() {
 print(x)
 }
 }
 
 class ImplB(val x: Int) : InterfaceB {
 override fun methodB() {
 print(x)
 }
 } class AandB(a: InterfaceA, b: InterfaceB) : InterfaceA by a, InterfaceB by b
  29. Software Patterns object SingleInstance {
 var dummyBool: Boolean = true

    } https://github.com/dbacinski/Design-Patterns-In-Kotlin
  30. Software Patterns object SingleInstance {
 var dummyBool: Boolean = true

    } public class XingUser {
 private final int id;
 private final String name;
 private final String email;
 
 public static class Builder {
 private final int id;
 private final String name;
 private String email = "";
 
 public Builder(int id, String name) {
 this.id = id;
 this.name = name;
 }
 
 public Builder email(String email) {
 this.email = email;
 return this;
 }
 
 public XingUser build() {
 return new XingUser(this);
 }
 }
 
 private XingUser(Builder builder) {
 id = builder.id;
 name = builder.name;
 email = builder.email;
 }
 } https://github.com/dbacinski/Design-Patterns-In-Kotlin
  31. Software Patterns object SingleInstance {
 var dummyBool: Boolean = true

    } public class XingUser {
 private final int id;
 private final String name;
 private final String email;
 
 public static class Builder {
 private final int id;
 private final String name;
 private String email = "";
 
 public Builder(int id, String name) {
 this.id = id;
 this.name = name;
 }
 
 public Builder email(String email) {
 this.email = email;
 return this;
 }
 
 public XingUser build() {
 return new XingUser(this);
 }
 }
 
 private XingUser(Builder builder) {
 id = builder.id;
 name = builder.name;
 email = builder.email;
 }
 } class XingUser(val id: Int,
 val name: String,
 val email: String = "",
 val premium: Boolean = false) https://github.com/dbacinski/Design-Patterns-In-Kotlin
  32. Software Patterns object SingleInstance {
 var dummyBool: Boolean = true

    } public class XingUser {
 private final int id;
 private final String name;
 private final String email;
 
 public static class Builder {
 private final int id;
 private final String name;
 private String email = "";
 
 public Builder(int id, String name) {
 this.id = id;
 this.name = name;
 }
 
 public Builder email(String email) {
 this.email = email;
 return this;
 }
 
 public XingUser build() {
 return new XingUser(this);
 }
 }
 
 private XingUser(Builder builder) {
 id = builder.id;
 name = builder.name;
 email = builder.email;
 }
 } class XingUser(val id: Int,
 val name: String,
 val email: String = "",
 val premium: Boolean = false) XingUser(id = 1,
 name = "Cristian")
 
 XingUser(id = 1,
 name = "Cristian",
 email = "[email protected]")
 
 XingUser(id = 1,
 name = "Cristian",
 premium = true) https://github.com/dbacinski/Design-Patterns-In-Kotlin
  33. Software Patterns https://github.com/dbacinski/Design-Patterns-In-Kotlin class Printer(val stringStrategy: (String) -> String) {


    fun printString(string: String) = println(stringStrategy.invoke(string))
 } val lowerCasePrinter = Printer({ it.toLowerCase() })
 val prefixPrinter = Printer({ "Prefix: " + it })
 
 prefixPrinter.printString("Hello world") //Prefix: Hello world
 lowerCasePrinter.printString("HELLO WORLD") //hello world
  34. Destructuring declarations data class User(val name: String, val age: Int,


    val city: String, val country: String) val user = User("Cristian", 31, "bcn", "Spain")
 val user2 = user.copy(city = "Madrid")
 
 val listFUsers = listOf(user, user2)
 
 for ((name, age, city, country) in listFUsers) {
 println("Hi! $name from $city, $country")
 }
 
 val (age) = user
 println("Hi $age") //Hi Cristian
  35. Destructuring declarations data class User(val name: String, val age: Int,


    val city: String, val country: String) val salute = Pair("Hola", "Hi")
 println(salute.first)// Hola
 
 val (spanish, english) = salute
 println(spanish)// Hola val user = User("Cristian", 31, "bcn", "Spain")
 val user2 = user.copy(city = "Madrid")
 
 val listFUsers = listOf(user, user2)
 
 for ((name, age, city, country) in listFUsers) {
 println("Hi! $name from $city, $country")
 }
 
 val (age) = user
 println("Hi $age") //Hi Cristian
  36. DSL fun main(args: Array<String>) = {
 val time = measureTimeMillis

    {
 doSomethingUsefulOne()
 }
 println("Completed in $time ms")
 }
  37. DSL fun main(args: Array<String>) = {
 val time = measureTimeMillis

    {
 doSomethingUsefulOne()
 }
 println("Completed in $time ms")
 } inline fun measureTimeMillis(block: () -> Unit) : Long {
 val start = System.currentTimeMillis()
 block()
 return System.currentTimeMillis() - start
 }
  38. DSL’s fun setListener(view: View) {
 view.setOnClickListener(View.OnClickListener {
 doSomething()
 })
 }

    fun setListener(view: View) {
 view.setOnClickListener({ v -> doSomething() })
 }
  39. DSL’s fun setListener(view: View) {
 view.setOnClickListener(View.OnClickListener {
 doSomething()
 })
 }

    fun setListener(view: View) {
 view.setOnClickListener({ v -> doSomething() })
 } fun setListener(view: View) {
 view.setOnClickListener({ doSomething() })
 }
  40. DSL’s fun setListener(view: View) {
 view.setOnClickListener(View.OnClickListener {
 doSomething()
 })
 }

    fun setListener(view: View) {
 view.setOnClickListener({ v -> doSomething() })
 } fun setListener(view: View) {
 view.setOnClickListener({ doSomething() })
 } fun setListener(view: View) {
 view.setOnClickListener { doSomething() }
 }
  41. DSL’s fun setListener(view: View) {
 view.setOnClickListener(View.OnClickListener {
 doSomething()
 })
 }

    fun setListener(view: View) {
 view.setOnClickListener({ v -> doSomething() })
 } fun setListener(view: View) {
 view.setOnClickListener({ doSomething() })
 } fun setListener(view: View) = view.setOnClickListener { doSomething() } fun setListener(view: View) {
 view.setOnClickListener { doSomething() }
 }