아이템 7 - 결과 부족이 발생할 경우 null과 Failure를 사용하라
ds_chanin
·2022. 3. 2. 00:21
- 다른 시스템에서 데이터를 인터넷 연결등의 이유로 받아오지 못하는 경우
- 조건에 맞는 요소를 찾지 못하는 경우
- 파싱을 시도했으나 형식이 맞지않아 실패하는 경우
위와 같이 함수가 원하는 결과를 만들어 내지 못할 때 예외를 정보를 전달하는 방법으로 사용해서는 안된다. 다음과 같은 방식을 고려하자.
- 충분히 예측할 수 있는 범위의 오류
- null, 실패를 나타내는 sealed 클래스를 반환한다.
- null을 반환하는 경우: 추가적인 정보를 전달하지 않아도 되는 경우
- sealed 클래스를 반환하는 경우: 추가적인 정보를 전달해야 하는 경우
- null, 실패를 나타내는 sealed 클래스를 반환한다.
- 예측하기 어려운 경우
- 예외를 throw 한다.
예외를 정보를 전달하는 방법으로 사용하면 다음과 같은 문제가 발생하기 때문이다.
- 개발자가 exception이 전파되는 과정을 제대로 추적하지 못한다.
- 코틀린의 모든 exception은 uncheck exception라서 클라이언트가 처리하지 않을 수 있고, 문서에도 제대로 드러나지 않아 파악하기 힘들다.
- try-catch 블럭에 코드를 작성하면 컴파일러의 최적화가 제한된다.
- try-catch 가 비용이 드는 이유: 컴파일 타임에 코드를 정렬하고 최적화해야 하는데, 이는 exception이 어느 시점에서 발생하더라도 일련의 순서대로 코드가 실행된 것처럼 보여져야하는 작업이다. 그리고 try-catch 블럭이 있을때 이러한 작업은 비용이 많이 들 수 있고 최적화가 되지 않는 경우가 있다고 한다.
가장많은 점수를 받은 답변을 보니 오류가 발생할 때 해당 오류를 catch 하는 try블럭을 탐색하는데 비용이 많이 든다고 한다. 즉, try-catch 블럭이 있으면 excepcatch 블럭이 존재하든
예제 코드
AS-IS
fun chargeWithTryCatch() {
try {
chargeThrowException()
//충전 성공을 기록한다.
} catch (exception: IllegalStateException) {
//충전 실패를 기록한다.
}
}
fun chargeThrowException() {
throw IllegalStateException("충전실패")
}
TO-BE
fun chargeWithOutTryCatch() {
val result = chargeReturnThrow()
when (result) {
is ChargeResult.Failure -> {
//충전 실패를 기록한다.
}
is ChargeResult.Success -> {
//충전 성공을 기록한다.
}
}
}
fun chargeReturnThrow(): ChargeResult {
return ChargeResult.Failure(IllegalStateException("충전실패"))
}
sealed class ChargeResult {
class Success() : ChargeResult()
class Failure(val throwable: Throwable) : ChargeResult()
}
엘비스(Elvis) 연산자를 사용하기
개발자는 항상 Collection에서 요소를 안전하게 추출할 것이라 예상한다. 따라서 nullable한 요소가 Collection에서 나오면 안된다. 이 경우 null이 발생할 수 있다는 경고를 주려면 getOrNull을 사용하거나 ?: 를 사용하여 명시적으로 리턴되는 값을 알려주도록 하자.
'스터디 > 이펙티브코틀린' 카테고리의 다른 글
아이템 9 - use를 사용하여 리소스를 닫아라 (0) | 2022.03.05 |
---|---|
아이템 8 - 적절하게 null을 처리하라 (0) | 2022.03.03 |
아이템 6 - 사용자 정의 오류보다는 표준 오류를 사용하라 (0) | 2022.03.02 |
아이템 5 - 예외를 활용해 코드에 제한을 걸어라 (0) | 2022.03.01 |
아이템 4 - inferred 타입으로 리턴하지 말라 (2) | 2022.02.28 |