Kotlin tips – #day2

1. Top-Level (Extensions) Functions for Utility Functions

// Don't
object StringUtil {
    fun countAmountOfX(string: String): Int{
        return string.length - string.replace("x", "").length
    }
}
StringUtil.countAmountOfX("xSamplex")

// Do
fun String.countAmountOfX(): Int {
    return length - replace("x", "").length
}
"xSamplex".countAmountOfX()

This way, our code feels more like telling a story.

2. Avoid if-null check

//Don't
if (order == null || order.customer == null || order.customer.address == null){
    throw IllegalArgumentException("Invalid Order")
}
val city = order.customer.address.city

//Do
val city = order?.customer?.address?.city ?: throw IllegalArgumentException("Invalid Order")

Often you can use null-safe call ?. or the elvis operator ?: instead.

3. Avoid if-type check

//Don't
if (service !is CustomerService) {
    throw IllegalArgumentException("No CustomerService")
}
service.getCustomer()

//Do
service as? CustomerService ?: throw IllegalArgumentException("No CustomerService")
service.getCustomer()

4. Avoid not-null Assertions

//Don't
order!!.customer!!.address!!.city

5. Consider let

Sometimes using let can be a concise alternative for if

val order: Order? = findOrder()
if (order != null){
    dun(order.customer)
}

// Do
findOrder()?.let { dun(it.customer) }
//or
findOrder()?.customer?.let(::dun)

Kotlin tips – #day1

1. Use Expressions

// Don't
fun getDefaultLocale(deliveryArea: String): Locale {
    val deliverAreaLower = deliveryArea.toLowerCase()
    if (deliverAreaLower == "germany" || deliverAreaLower == "austria") {
        return Locale.GERMAN
    }
    if (deliverAreaLower == "usa" || deliverAreaLower == "great britain") {
        return Locale.ENGLISH
    }
    if (deliverAreaLower == "france") {
        return Locale.FRENCH
    }
    return Locale.ENGLISH
}

// Do
fun getDefaultLocale2(deliveryArea: String) = when (deliveryArea.toLowerCase()) {
    "germany", "austria" -> Locale.GERMAN
    "usa", "great britain" -> Locale.ENGLISH
    "france" -> Locale.FRENCH
    else -> Locale.ENGLISH
}

Basically an ifcan be replaced with more concise when expressions.

2.apply for Grouping Object Initialization

//Don't
val dataSource = BasicDataSource()
dataSource.driverClassName = "com.mysql.jdbc.Driver"
dataSource.url = "jdbc:mysql://domain:3309/db"
dataSource.username = "username"
dataSource.password = "password"
dataSource.maxTotal = 40
dataSource.maxIdle = 40
dataSource.minIdle = 4

//Do
val dataSource = BasicDataSource().apply {
    driverClassName = "com.mysql.jdbc.Driver"
    url = "jdbc:mysql://domain:3309/db"
    username = "username"
    password = "password"
    maxTotal = 40
    maxIdle = 40
    minIdle = 4
}