코틀린은 2010년에 처음 개발되었지만 2016년 2월에 첫 번째 안정 버전(stable version)이 공식적으로 배포되었을 정도로 굉장히 오랜 시간 동안 만들어지고 있고, 처음부터 대규모 애플리케이션을 실용적으로 만들기 위한 프로그래밍 언어로 설계되었고 현재는 모바일 애플리케이션, 웹 애플리케이션의 백엔드, 웹 애플리케이션의 프론트엔드 등 다양한 영역에서 활용되고 있습니다.
5️⃣예외를 통한 코드 제한
확실하게 동작해야 하는 코드가 있는 경우 예외를 통해 코드에 제한을 주는 것이 좋습니다.
require() : 매개변수에 제한을 걸 수 있고, 제한을 만족하지 못하면 예외 던집니다.
check() : 상태와 관련된 동작에 제한을 걸 수 있고, 제한을 만족하지 못하면 예외 던집니다.
assert() : 테스트 모드에서만 동작하며, 어떤 것이 true인지 확인할 수 있고, 제한을 만족하지 못하면 예외 던집니다.
return 또는 throw와 함께 활용하는 ?: (Elvis 연산자)
위와 같이 제한을 거는 이유는 뭘까요?
만약 문제가 생겨 메서드가 동작하지 못하고 종료되거나, 예상하지 못한 동작을 하게된다면, 메서드를 동작시키지 않는 것 보다 더 한 문제를 가져올 수 있습니다.
제한을 걸면 다른 개발자들이 보고 파악하기 수월합니다.
코드가 어느 정도 자체적으로 검사될 수 있으니, 관련된 단위 테스트를 줄일 수 있습니다.
스마트 캐스트 기능을 활용할 수 있게 되므로, 캐스트(타입 변환)를 적게 할 수 있습니다.
require
매개변수에 제한을 거는 require 함수를 활용하는 예를 들겠습니다.
1. 매개변수로 받은 Int 타입의 정수가 양의 정수여야 한다.
2. 매개변수로 받은 List 콜렉션의 리스트가 빈 값이 아니어야 한다.
3. 매개변수로 받은 String 타입의 문자열이 null이여선 안되고, 올바른 형식이어야 한다.
require(n >= 0)
require(list.isNotEmpty())
requireNotNull(value)
require(isCheckedForm(value)) { "$value의 형식이 만족하지 못했습니다." }
이와 같은 유효성 검사 코드는 함수의 가장 앞부분에 배치하므로 코드를 읽을 때쉽게 파악할 수 있고 람다를 활용해 예외를 던질 때 메세지를 정의할 수도 있습니다.
check
상태에 제한을 거는 check 함수를 활용하는 예를 들겠습니다.
1. 객체가 초기화 되어있는 경우에만 처리를 할 수 있다.
2. 로그인을 한 경우에만 처리를 할 수 있다.
3. 객체를 사용할 수 있는 시점에 처리할 수 있다.
check(this::isInitialized)
checkNotNull(token)
check(this::mediaPlayer.isOpen)
이와 같은 상태 검사 코드는 require 함수 뒤에 배치합니다. check를 나중에 하는 것 입니다.
nullability와 스마트 캐스팅
코틀린에서 require과 check 함수로 조건에 대해 true가 나왔다면, 해당 조건은 이후에도 true라고 가정하기 때문에 이를 활용해 타입 비교를 한다면, smart cast가 작동됩니다.
fun getFood(food: Food) {
require(food.type is FoodType.MILK)
val milk : FoodType.MILK = food.type
require(food.protein != null)
val protein: Long = food.protein
}
그리고 requireNotNull과 checkNotNull 모두 스마트 캐스트를 지원하기 때문에 변수를 unpack(객체에서 데이터를 꺼내 다른 변수에 저장하는 것)하는 용도로 사용할 수 있습니다.
val protein = requireNotNull(food.protein)
Elvis 연산자
Elvis 연산자를 활용해 throw 또는 return 등의 사용하여 코드를 읽기 쉽고 유연하게 사용할 수 있습니다.
fun cooking(food: Food) {
val name : String = food.name ?: return
또는
val name : String = food.name ?: run {
log.d(TAG, "name이 NULL 입니다.")
return
}
}
fun cooking(food: Food) {
val name : String = food.name ?: throw IllegalArgumentException("name is null")
}
이와 같이 예외를 활용해 코드를 제한하므로 얻을 수 있는 장점이 많습니다.
'Kotlin > 안전성, 가독성을 효과적인 향상시키는 사용법' 카테고리의 다른 글
👋Kotlin : 7️⃣결과를 만들어 낼 수 없는 경우 null과 failure를 사용 (0) | 2022.03.05 |
---|---|
👋Kotlin : 6️⃣사용자 정의 오류 보다는 표준 오류를 사용 (0) | 2022.03.04 |
👋Kotlin : 4️⃣Inferred(추론된) 타입으로 리턴하지 말라 (0) | 2022.03.01 |
👋Kotlin : 3️⃣최대한 플랫폼 타입 사용을 제한하라 (0) | 2022.03.01 |
👋Kotlin : 2️⃣변수의 스코프 최소화 (0) | 2022.03.01 |