+1

Idiomatic Kotlin (Phần 2)

Nối tiếp phần 1

Tiếp tục là một vài tips hữu ích khi sử dụng Kotlin

Nâng giá trị các object (Leverage Value Object)

Với data classes, ta có thể dễ dàng viết các immutable-value object. Kể cả object chỉ có duy nhất 1 propety.

//Don't
fun send(target: String){}

//Do
fun send(target: EmailAddress){}
// expressive, readable, type-safe

data class EmailAddress(val value: String)

Mapping ngắn gọn hơn với Single Expression Function

// Don't
fun mapToDTO(entity: SnippetEntity): SnippetDTO {
    val dto = SnippetDTO(
            code = entity.code,
            date = entity.date,
            author = "${entity.author.firstName} ${entity.author.lastName}"
    )
    return dto
}

Với single expression functions, ta có thể viết tên các argument dễ dàng, chính xác và tăng khả năng readable của mapping giữa các object.

// Do
fun mapToDTO(entity: SnippetEntity) = SnippetDTO(
        code = entity.code,
        date = entity.date,
        author = "${entity.author.firstName} ${entity.author.lastName}"
)
val dto = mapToDTO(entity)

Nếu bạn thích extension functions, ta cũng có thể sử dụng chúng như thế này

// Do
fun SnippetEntity.toDTO() = SnippetDTO(
        code = code,
        date = date,
        author = "${author.firstName} ${author.lastName}"
)
val dto = entity.toDTO()

Tham chiếu đối số constructor khi khởi tạo

Hãy nhìn ví dụ dưới đây, bạn phải khai báo các khởi tạo (trong block init) bên trong constructor để set up cho httpClient

// Don't
class UsersClient(baseUrl: String, appName: String) {
    private val usersUrl: String
    private val httpClient: HttpClient
    init {
        usersUrl = "$baseUrl/users"
        val builder = HttpClientBuilder.create()
        builder.setUserAgent(appName)
        builder.setConnectionTimeToLive(10, TimeUnit.SECONDS)
        httpClient = builder.build()
    }
    fun getUsers(){
        //call service using httpClient and usersUrl
    }
}

apply() giúp ta nhóm lại khởi tạo với 1 single expression

// Do
class UsersClient(baseUrl: String, appName: String) {
    private val usersUrl = "$baseUrl/users"
    private val httpClient = HttpClientBuilder.create().apply {
        setUserAgent(appName)
        setConnectionTimeToLive(10, TimeUnit.SECONDS)
    }.build()
    fun getUsers(){
        //call service using httpClient and usersUrl
    }
}

object cho Stateless Interface

object trong Kotlin giúp ta cài đặt framework interface mà không cần quan tâm đến state.

//Do
object StringToInstantConverter : Converter<String, Instant> {
    private val DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm:ss Z")
            .withLocale(Locale.UK)
            .withZone(ZoneOffset.UTC)

    override fun convertToModel(value: String?, context: ValueContext?) = try {
        Result.ok(Instant.from(DATE_FORMATTER.parse(value)))
    } catch (ex: DateTimeParseException) {
        Result.error<Instant>(ex.message)
    }

    override fun convertToPresentation(value: Instant?, context: ValueContext?) =
            DATE_FORMATTER.format(value)
}

Destructuring

Destructuring rất hữu ích sử dụng để trả về nhiều values từ một function. Ta có thể tự định nghĩa data class hoặc sử dụng Pair (performance tốt hơn)

//Do
data class ServiceConfig(val host: String, val port: Int)
fun createServiceConfig(): ServiceConfig {
    return ServiceConfig("api.domain.io", 9389)
}
//destructuring in action:
val (host, port) = createServiceConfig()

Ngoài ra, destructuring có thể dùng để iterate map

//Do
val map = mapOf("api.domain.io" to 9389, "localhost" to 8080)
for ((host, port) in map){
    //...
}

Khởi tạo Structs theo cách khác

listOf, mapOf và to có thể được dùng để khởi tạo structs (như JSON) khá chính xác. Mặc dù chúng ta nên dùng data classes và object mapping để tạo JSON, nhưng đây cũng là 1 phương pháp hay nên biết

//Do
val customer = mapOf(
        "name" to "Clair Grube",
        "age" to 30,
        "languages" to listOf("german", "english"),
        "address" to mapOf(
                "city" to "Leipzig",
                "street" to "Karl-Liebknecht-Straße 1",
                "zipCode" to "04107"
        )
)

SourceCode

Nguồn


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí