본문 바로가기
공부/이펙티브코틀린

아이템 5 - 예외를 활용해 코드에 제한을 걸어라

by 띵커베르 2024. 3. 31.
728x90
  • 확실하게 어떤 형태로 동작해야 하는 코드가 있다면, 예외를 활용해 제한을 걸어주는 것이 좋다
  • 아래에 몇가지 코드를 제시함
// require: 파라미터를 검증
fun acceptOnlyTwo(num: Int) {
    // 원하는것만 적는다
    require(num == 2) { "2만 허용!" }

    // 원하는게 아닐경우를 적는다
    if(num != 2) {
        throw IllegalArgumentException("2만 허용!")
    }
}

// check: 상태혹은 멤버 변수를 검증
class Person {
    val status: PersonStatus = PersonStatus.PLAYING

    fun sleep() {
        check(this.status == PersonStatus.PLAYING) { "에러 메시지!" }

        if(this.status != PersonStatus.PLAYING) {
            throw IllegalStateException("에러 메시지!")
        }
    }

    enum class PersonStatus {
        PLAYING, SLEEPING
    }
}

 

  • 아규먼트 - 일반적으로 require 함수를 사용
fun factorialRequireTest(n: Int): Long {
    require(n >= 0) {
        "Cannot calculate factorial of $n because it is smaller than 0"
    }
    return if (n <= 1) 1 else factorialRequireTest(n - 1) * n
}

 

  • 상태 - 일반적으로 check 함수를 사용
  • Assert 계열 함수 사용
    • 주로 테스트 또는 개발 단계에서 사용하고 개인적으로 require, check 를 사용하고 테스트 시에는 가독성이 더 나은 AssertJ 를 주로 사용 함
  • nullability 와 스마트 캐스팅
    • require 와 check 블록으로 어떤 조건을 확인해서 true 가 나왔다면 해당 조건은 이후로도 true 일 거라고 가정합니다.
fun printLength(input: String?) {
    val nonNullInput = requireNotNull(input) { "input cannot be null" }
    // 이 시점부터 nonNullInput 은 non-null 타입으로 캐스트됩니다.
    println(nonNullInput.length)
}

@Test
fun requireNotNullTest() {
    printLength("Hello") // 5를 출력
    printLength(null) // 예외 발생: input cannot be null
}

 

  • 변수를 언팩(unpack) 하는 용도로 활용할 수 있다
    • 언팩 - 주로 null 가능성이 있는 변수에서 실제 값을 꺼내는 과정을 의미
fun printNonNullValue(value: Int?) {
    val nonNullValue = requireNotNull(value) { "Value cannot be null" }
    // nonNullValue 변수는 여기서 non-null Int 타입으로 "언팩"됩니다.
    println(nonNullValue)
}
// 프로퍼티에 문제가 있어 null 일 때 여러 처리를 해야할 때도, return/throw 와 run 함수를 조합해서 활용하면 됩니다.
fun sendMail(person: Person, text: String) {
    val email: String = person.email ?: run { 
        println("email is null")
        return
    }
}

 

 


정리

  • 제한을 훨씬 더 쉽게 확인할 수 있다
  • 애플리케이션을 더 안정적으로 지킬 수 있다
  • 코드를 잘못 쓰는 상황을 막을 수 있다
  • 스마트 캐스팅을 활용할 수 있다

 

개인생각

  • api 매개변수는 @Validated 하듯이 간단한 메서드간의 Validate 는 require 와 check 를 잘 활용해보자.
  • Elvis 연산자는 nullable 을 확인할 때 굉장이 많이 사용되는 관용적인 방벙이니, 처리가 필요할때 써보면 좋을듯 하다.
728x90

댓글