코드에서 같은 연산에 대해 널 아님 단언을 자주 사용한다면 이 문제를 언급하는 적절한 단언과 함께 함수를 분리하는 것이 좋다. 예를 들어, 프로그램 로직에서 Map에 특정 키가 꼭 존재해야 하고 키가 없을 경우 아무 일도 일어나지 않는 것보다는 예외가 발생하는 편이 좋다고 가정해보자. 값을 일반적인 방법(각괄호)으로 읽는 대신 getValue()를 사용하면 키가 없는 경우 NoSucHElementException이 던져진다.
NonNullAssertions/ValueFromMap.kt
import atomictest.*
fun main() {
val map = mapOf(1 to "one")
map[1]!!.toUpperCase() eq "ONE"
map.getValue(1).toUpperCase() eq "ONE"
capture {
map[2]!!.toUpperCase()
} eq "NullPointerException"
capture {
map.getValue(2).toUpperCase()
} eq "NoSuchElementException: " +
"Key 2 is missing in the map."
}
NoSucHElementException과 같이 구체적인 예외를 던지면 뭔가 잘못됐을 때 더 유용한 상세 정보를 얻을 수 있다.
최적의 코드는 항상 안전한 호출과 자세한 예외를 반환하는 특별한 함수만 사용한다. null이 아니라는 점을 단언한 호출은 꼭 필요할 때만 사용하라. 널 아님 단언이 자바와 상호 작용하기 위해 추가된 것이긴 하지만, 자바와 상호 작용할 때 활용할 수 있는 더 나은 방법이 있다. 이에 대해서는 ‘부록 B, 자바 상호 운용성’에서 살펴보겠다.