안드로이드 개발자 노트
[이펙티브 코틀린] Item7. 결과 부족이 발생할 경우 null과 Failure를 사용하라 본문
반응형
함수가 원하는 결과를 만들어 낼 수 없을 때가 있습니다.
- 서버로부터 데이터를 읽어 들이려고 했는데, 인터넷 연결 문제로 읽어 들이지 못한 경우
- 조건에 맞는 첫 번째 요소를 찾으려 했는데, 조건에 맞는 요소가 없는 경우
- 텍스트를 파싱해서 객체를 만들려고 했는데, 텍스트의 형식이 맞지 않는 경우
이러한 상황을 처리하는 메커니즘은 두 가지가 있습니다.
- null 또는 '실패를 나타내는 sealed 클래스'를 리턴한다.
- 예외를 throw한다.
여기서 예외는 정보를 전달하는 방법으로 사용해서는 안되며, 이유를 정리하면 다음과 같습니다.
- 예외가 전파되는 과정을 제대로 추적하지 못한다.
- 코틀린의 모든 예외는 unchecked(반드시 처리하게 강제되는 예외)이다.
- 예외는 예외적인 상황을 처리하기 위해서 만들어졌으므로 명시적인 테스트만큼 빠르게 동작하지 않는다.
- try-catch 블록 내부에 코드를 배치하면, 컴파일러가 할 수 있는 최적화가 제한된다.
반면, null과 Failure는 예상되는 오류를 표현할 때 명시적이고, 효율적이며, 간단한 방법으로 처리할 수 있습니다.
충분히 예측할 수 있는 범위의 오류는 null과 Failure를 사용하고, 예측하기 어려운 예외적인 범위의 오류는 예외를 throw해서 처리하는 것이 좋습니다.
간단한 예를 살펴봅시다.
inline fun <reified T> String.readObjectOrNull(): T? {
//...
if (incorrectSign) {
return null
}
//...
return result
}
inline fun <reified T> String.readObject(): Result<T> {
//...
if (incorrectSign) {
return Failure(JsonParsingException())
}
//...
return Success(result)
}
sealed class Result<out T>
class Success<out T>(val result: T): Result<T>()
class Failure(val throwable: Throwable): Result<Nothing>()
class JsonParsingException: Exception()
null을 처리해야 한다면, 사용자는 safe call 또는 Elvis 연산자 같은 다양한 널 안정성 기능을 활용합니다.
Result와 같은 공용체(union type)를 리턴하기로 했다면, when 표현식을 사용해서 처리합니다.
val age = userText.readObjectOrNull<Person>()?.age ?: -1
val person = userText.readObjectOrNull<Person>()
val age = when(person) {
is Success -> person.age
is Failure -> -1
}
null 값과 sealed result 클래스는 명시적으로 처리해야 하며, 어플리케이션의 흐름을 중지하지도 않습니다.
추가적인 정보를 전달해야 한다면 sealed result 클래스를 사용하고, 그렇지 않으면 null을 사용하는 것이 일반적입니다.
반응형
'Kotlin > 이펙티브 코틀린' 카테고리의 다른 글
[이펙티브 코틀린] Item8. 적절하게 null을 처리하라 (0) | 2023.09.09 |
---|---|
[이펙티브 코틀린] Item6. 사용자 정의 오류보다는 표준 오류를 사용하라 (0) | 2023.09.03 |
[이펙티브 코틀린] Item5. 예외를 활용해 코드에 제한을 걸어라 (0) | 2023.09.03 |