Result

sumi Yoo·2022년 11월 18일
0

Result 용도

  • 외부 서비스에 의존하는 로직이라 예외 발생 가능성이 빈번한 컴포넌트
  • 해당 컴포넌트에서 에러가 발생할 수 있다는 것을 클라이언트에게 알려주고 싶을 때, 에러 핸들링을 다른 컴포넌트에 강제하고 위임하고 싶을 때
  • try … catch를 쓰고 싶지 않을 때

runCatching

runCatching 블록 안에서 성공/실패 여부가 캡슐화된 Result<T> 형태로 리턴합니다.

runCatching 예시

val colorName: Result<String> = runCatching {
    when (color) {
        Color.BLUE -> "파란색"
        Color.RED -> "빨간색"
        Color.YELLOW -> "노란색"
        Color.ARMARNTH -> throw Error("처음 들어보는 색")
    }
}.onSuccess { it:String ->
    //성공시만 실행
}.onFailure { it:Throwable ->
    //실패시만 실행 (try - catch문의 catch와 유사)
}

프로퍼티

Result<T>타입은 isSuccess와 isFailure를 프로퍼티로 갖습니다.

feature("Repository Test") {
    val repository = MockRepository()
    val dummyUser = SampleHleper.dummyUser()

    scenario("should be able to insert a user In Repo") {
        val result = runCatching {
            runBlocking { repository.insert(dummyUser) }
        }

        result.isSuccess shouldBe true
    }
}

Result 타입에서 값 가져오기

  • getOrThrow()
colorName.getOrThrow() 
// runBlocking문에서 에러가 발생한경우 해당에러를 리턴합니다.
  • getOrDefault
colorName.getOrDefault(defaultValue = "미상") 
//runBlocking문에서 에러가 발생한경우 defaultValue 파라미터를 리턴합니다.
  • getOrNull
colorName.getOrNull()
// runBlock문에서 에러가 발생한경우 null값을 리턴합니다.
  • getOrElse
colorName.getOrElse{ exception: Throwable -> 
}
// runBlocking문에서 에러가 발생한경우 exception을 인자로받아
// 블록안의 값을 리턴합니다.캡슐화된 타입값과 같아야하기때문에 다른타입을
// 리턴하고싶다면 아래 mapCatching을 사용해야합니다.

map, mapCatching


val firstUserAge: Result<Int> = runCatching {
    "123"
}.map { it: String ->
    it.toInt()
}


val secondUserAge: Result<Int> = runCatching {
    "123"
}.mapCatching { it: String ->
    it.toInt()
}

차이점 (에러가 발생한 경우)

  • map
    map은 블록 안의 에러가 발생할경우 바깥으로 에러를 보냅니다.

try {
    runCatching {
        database.getUser(id)
    }.map { user: User? ->
        //강제로 에러를 발생시킵니다.
        throw Error("유저정보를 가져올 수 없습니다.")
    }.onSuccess {
        //map 블록에서 에러 발생시 실행되지않습니다.
    }.onFailure {
        //map 블록에서 에러 발생시 실행되지 않습니다.
    }
} catch (e:Exception) {
    //map 블록에서  발생한 에러를 인자로받아 호출됩니다.
}
  • mapCatching
    mapCatching은 블록 안의 에러를 내부에서 처리하며 onFailure로 받을 수 있습니다.
runCatching {
    database.getUser(id)
}.mapCatching { user: User? ->
    //강제로 에러를 발생시킵니다.
    throw Error("유저정보를 가져올 수 없습니다.")
}.onSuccess {
    //mapCatching 블록에서 에러 발생시 실행되지않습니다.
}.onFailure {
    //mapCatching 블록에서 에러 발생시 호출됩니다. 
}

recover, recoverCatching

map이 runCatching이 성공할 경우 호출되었다면 recover은 실패했을 경우 호출됩니다.

  • recover
try {
    runCatching {
       throw Error("runBlock문 에러발생")
    }.recover { it: String ->
        throw Error("recover문 에러발생")
    }.onFailure {
        //에러가 전달되지않습니다.
    }
} catch (e: Exception) {
    //recover에서 발생한 에러가 받아집니다.
}
  • recoverCatching
runCatching {
    throw Error("runBlock문 에러발생")
}.recoverCatching { it: String ->
    throw Error("recover문 에러발생")
}.onFailure {
    //이곳에서 에러를 받습니다.
}

0개의 댓글