# 2021/12/08

silmxmail·2022년 1월 7일
0

1일1문서

목록 보기
3/17

https://premsinghsodha7.medium.com/kotlin-how-to-write-code-more-readable-and-clean-best-practices-ac6cac160f3d

How to write Claen code

if를 써서 분기를 나누지말고 When을 사용하자.

//Don't
fun getProvinceByCityName(cityName: String): String {
    val cityNameLower = cityName.toLowerCase()
    if (cityName == "karachi" || cityName == "hyderabad") {
        return "Sindh"
    }
    if (cityName == "lahore" || cityName == "faisalabad") {
        return "Punjab"
    }
    if (cityName == "islamabad") {
        return "Islamabad"
    }
    return "unknown"
}
//Do
fun getProvinceByCityName(cityName: String) = when (cityName.toLowerCase()) {
    "karachi", "hyderabad" -> "Sindh"
    "lahore", "faisalabad" -> "Punjab"
    "islamabad" -> "Islamabad"
    else -> "unknown"
}

Top-Level (Extension) Functions for Utility Functions

//Don't
object StringUtil {
    fun countAmountOfZ(string: String): Int{
        return string.length - string.replace("z", "").length
    }
}
StringUtil.countAmountOfX("zFunzWithzKotlinz")
//Do
fun String.countAmountOfZ(): Int {
    return length - replace("z", "").length
}
"zFunzWithzKotlinz".countAmountOfX()

객체 생성시 default값을 바로 넣을 수 있다.

//Don't
val config = Search()
    .setTerm("game of thrones")
    .setRecursive(true)
    .setFollowSymlinks(true)
//Do
val config2 = Search(
    term = "game of thrones",
    recursive = true,
    followSymlinks = true
)

apply()를 사용하자.

//Don't
val dataSource = BasicDataSource()
dataSource.name = "User 1"
dataSource.url = "www.xyz.com"
dataSource.username = "username"
dataSource.password = "password"
//Do
val dataSource = BasicDataSource().apply {
    name = "User 1"
    url = "www.xyz.com"
    username = "username"
    password = "password"
}

Don’t Overload for Default Arguments

//Don't
fun find(name: String){
    find(name, true)
}
fun find(name: String, recursive: Boolean){}
//Do
fun find(name: String, recursive: Boolean = true){}

Nullablity를 가볍게 따루자. 엘비스를 이용하여. if == null을 피하자.

//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")
//Don't
if (service !is MyService) {
    throw IllegalArgumentException("No MyService")
}
service.getData()
//Do
service as? MyService ?: throw IllegalArgumentException("No MyService")
service.getData()

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

let()을 활용하자.

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

Concise Mapping with Single Expression Functions

// 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
}
// Do
fun mapToDTO(entity: SnippetEntity) = SnippetDTO(
        code = entity.code,
        date = entity.date,
        author = "${entity.author.firstName} ${entity.author.lastName}"
)
val dto = mapToDTO(entity)
// Do
fun SnippetEntity.toDTO() = SnippetDTO(
        code = code,
        date = date,
        author = "${author.firstName} ${author.lastName}"
)
val dto = entity.toDTO()

Sealed Class를 활용하여 예외처리를 하자.

// Definition
sealed class UserProfileResult {
    data class Success(val userProfile: UserProfileDTO) : UserProfileResult()
    data class Error(val message: String, val cause: Exception? = null) : UserProfileResult()
}
// Usage
val avatarUrl = when (val result = client.requestUserProfile(userId)) {
    is UserProfileResult.Success -> result.userProfile.avatarUrl
    is UserProfileResult.Error -> "http://domain.com/defaultAvatar.png"
}
profile
러닝커브를 따라서 등반중입니다.

0개의 댓글