Các mẹo nhỏ bạn nên biết khi dùng Kotlin (P1)

Bạn sử dụng Kotlin để lập trình ứng dụng Android? Bạn nghe nói dùng Kotlin code rất nhanh, có thật sự vậy không? Bạn muốn sử dụng tối đa sự hữu dụng của ngôn ngữ lập trình này? Vậy sau đây là các mẹo nhỏ, khi bạn dùng nó chắc chắn bạn sẽ thấy sức mạnh của Kotlin mang tới cho bạn các dòng code thực sự rất ngắn!!!

#1 Explosive Placeholders Rất nhiều lần khi bạn implement một class mới, bạn sẽ được hỗ trợ các method TODO, ví dụ như:

class Test : Runnable {
    override fun run() {
        // TODO doSomethingElse()?
    }
}

Nó rất hữu dụng khi bạn làm theo flow, IDE sẽ cảnh báo bạn khi có case nào đó bạn quên chưa làm. Nhưng nếu như bạn chỉ muốn đánh dấu là phần đó mình sẽ làm trong tương lai, bạn sẽ phải code rất nhiều thứ, đại loại như là:

class Test : Callable<String> {
    override fun call(): String {
        if (something()) {
            return doSomething()
        } else {
            throw UnsupportedOperationException("TODO return doSomethingElse()?")
        }
    }
}

Nhưng Kotlin sẽ giúp bạn làm điều đó rất đơn giản, bạn chỉ cần:

class Test : Callable<String> {
    override fun call(): String {
        if (something()) {
            return doSomething()
        } else {
            TODO("doSomethingElse()?")
        }
    }
}

#2 Semantic Validation Khi bạn muốn validate tham số truyền vào, ở đây mình ví dụ String sep, và show ra các throw thông báo tương ứng. Với Java bạn sẽ phải làm đại loại như sau:

public String join(String sep, List<String> strings) {
        if (sep == null) throw new NullPointerException("sep == null");
        if (sep.length() < 2) {
            throw new IllegalArgumentException("sep.leng() < 2: "+sep);
        }
        if (strings == null) throw new NullPointerException("string == null");
        //....
    }

Hoặc bạn có thể dùng Guava với Preconditions để validate điều kiện nhập vào, ví dụ như:

public String join(String sep, List<String> strings) {
        Preconditions.checkNotNull(sep, "sep == null");
        Preconditions.checkArgument(sep.length() < 2, "sep.leng() < 2: "+sep);
        Preconditions.checkNotNull(strings, "string == null");
        //....
    }

Nhưng với Kotlin bạn không phải check nhiều như vậy, hệ thống sẽ tự check cho bạn phần null

fun join(sep: String, strings: List<String>): String {
        Preconditions.checkArgument(sep.length < 2, "sep.leng < 2: " + sep)
        //...
    }

Trong Kotlin, Preconditions cũng được viết ngắn gọn thành:

fun join(sep: String, strings: List<String>): String {
        require(sep.length < 2) { "sep.length < 2: " + sep}
        //...
    }

#3 Let Trong Kotlin có 2 từ khóa cơ bản là varval . Từ khóa val sử dụng khi giá trị của biến không thay đổi

val user: User? = null
        if (user != null) {
            //user not null
        }

Từ khóa var sử dụng khi giá trị của biến thay đổi

var user: User? = null
        if (user != null) {
            //user might be null 
        }

Ta có thêm từ khóa khác là let, bằng việc sử dụng let, các biến trong block sẽ đảm bảo không thể null, bạn không cần phải thêm dấu ? nữa

var user: User? = null
        user?.let {
            // it == user not null, only read once
        }

Bên trong block của let, bạn có thể dùng nhiều reference nếu bạn muốn

class Foo {
        @Volatile
        var user: User? = null

        fun doSomething() {
            user?.let { user ->
                //user not null, only read once!
            }
        }
    }

Bên cạnh đó, khi chúng ta gọi 1 hàm và muốn sử dụng giá trị trả về của nó nhiều lần, ta cũng có thể sử dụng let

someMethod().let { result ->
            //use result multiple times
        }

#4 Multiline String Literals Khi chúng ta có 1 String có chứa nhiều dòng, ở Java ta phải sử dụng toán tử \n

val string = "foo\nbar\nbaz"

hoặc

val string = "foo\n"
                +"bar\n"
                +"baz"

Bạn không phải làm những điều như vậy trong Kotlin, với việc chỉ cần thêm nháy " ở trước dòng đầu tiên và sau dòng cuối cùng.

val string = """foo
            bar
            baz"""

Hoặc sử dụng các lệnh trim

val foo = "FOO!"
val bar = "BAR!"
val baz = "BAZ!"
val string = """|$foo
                          |$bar
                          |$baz""".trimMargin()

#5 Name your import Khi có Conflict, đặc biệt về việc thay đổi tên class dẫn đến import sai, chắc chắn là sẽ rất mất thời gian để fix lại Ví dụ như:

package com.kotlinexample.ui

import ...

import android.view.View // Conflict

class UserInfoFragment : Fragment(), com.kotlinexample.ui.View { // Conflict

    override fun onCreateView(inflater: LayoutInflater, 
                              container: ViewGroup?, 
                              state: Bundle?): View = // Conflict
            inflater.inflate(user_info_fragment,
                             container,
                             false)
}

interface View // Conflict

Nhưng với Kotlin, bạn có thể đặt tên cho import và dùng nó trong class, khi đó thì mọi việc sẽ trở nên rất đơn giản

import android.view.View as AndroidView // Named import

class UserInfoFragment : Fragment(), View {
    
    override fun onCreateView(inflater: LayoutInflater, 
                              container: ViewGroup?, 
                              state: Bundle?): AndroidView = // Using named import
}

Vẫn còn rất nhiều những mẹo nhỏ bạn có thể dùng để việc sử dụng Kotlin trở nên thú vị hơn, mình sẽ giới thiệu tiếp ở các phần sau. Chúc các bạn code vui vẻ!


All Rights Reserved