결과 부족이 발생할 경우 null, Failure를 사용하라
로직을 수행할 때, 원하는 결과를 만들어 낼 수 없는 경우가 있다.
예를 들어, 서버로 데이터를 읽어 들일 때 인터넷 연결 문제로 못읽음, 텍스트 파싱할 때 형식이 맞지 않음 등등..
이러한 상황을 처리할 때 (1) null, Failure 리턴, (2) 예외 throw 방식을 사용한다. 하지만 (2)의 경우 다음과 같은 문제점이 있다.
일반적으로 예외는 정보를 전달하는 방법으로 사용해서는 안되고, 잘못된 특별한 상황을 나타내야 한다.
충분히 예측할 수 있는 범위의 오류는 null, Failure를 사용하고 예측하기 어려운 예외적인 범위의 오류는 throw가 낫다.
//null
inline fun <reified T> String.readObjectOrNull(): T? {
// ...
if (incorrectSign) {
return null
}
// ...
return result
}
//sealed Result
inline fun <reified T> String.readObject(): Result<T> {
// ...
if (incorrectSign) {
return Failure(JsonParsingException())
}
// ...
return Success(result)
}
sealed class Result<out T> //sealed는 컴파일러가 자식들을 알 수 있음
class Success<out T>(val result: T): Result<T>()
class Failure(val throwable: Throwable): Result<Nothing>()
class JsonParsingException: Exception()
null/sealed Result로 return 한다면 다음과 같이 엘비스 연산자/when으로 오류를 간단히 잡을 수 있다. 전체 애플리케이션을 중지시킬 수 있는 예외보다 나은 방식이다.
val age = userText.readObjectOrNull<Person>()?.age ?: -1
val person = userText.readObjectOrNull<Person>()
val age = when(person) {
is Success -> person.age
is Failure -> -1
}
참고로 sealed Result는 추가적인 정보를 전달할 때 사용한다.
https://bottom-to-top.tistory.com/69
sealed 관련: https://kotlinworld.com/165
잘봤습니다.