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

ds_chanin

·

2022. 3. 1. 02:10


  • require : 아규먼트를 제한한다.
  • check : 상태와 관련된 동작을 제한한다.
  • assert : 어떤것이 true인지 확인한다. test 모드에서만 작동한다.
  • return, throw와 함께 활용하는 엘비스(Elvis) 연산자

위 블럭을 이용하면 다양한 장점을 갖게 된다.

require과 check 블럭을 통해 문서를 통하지 않고도 어느정도 요구사항을 파악할 수 있고 예상치 못한동작을 방어할 수 있게된다. 그리고 스마트 캐스트 기능을 활용할 수 있게 되면서 타입 변환을 적게 할 수 있다.

아래는 스터디를 하면서 구성원들과 이야기한 내용을 정리한 것이다.

require

매개변수로 받은 값이 유효한지 검사하는 용도로 사용하는것이 올바른 것 같다.

예를들어 전달받은 Long이 양수여야만 하는지 검사를 하는등의 용도로 사용하는 것이 좋다.

check

매개변수와 관계없이 해당 객체가 가지고 있는 프로퍼티의 값이 해당 행동을 할 수 있는지를 검사하는 용도로 사용하는것이 좋은것 같다.

예를들어 충전요청의 상태가 REQUIRE 여야지 충전상태를 SUCCESS 로 변경할 수 있는 것과 같이 말이다.

assert

구성원 대다수의 의견이 굳이 테스트 모드에서만 동작하는 assert를 프로덕션 코드에 끼워넣어야 하는가? 로 사용하면서 얻는 이점보다 오히려 코드가 더러워지고 관리하기 힘들어진다는 의견이었다.

nullability와 스마트 캐스팅

require, check, requireNotNull, checkNotNull을 통해 스마트 캐스팅으로 타입변환 코드를 깔끔하게 해결할 수 있다.

fun changeDress(person: Person) {
    require(person.outfit is Dress) // 타입캐스팅과 throw를 한번에
    val dress: Dress = person.outfit
}

fun sendEmail(person: Person) {
    require(person.email != null) // 널체크와 throw를 한번에
    val email: String = person.email
}

//언팩
fun sendEmail(person: Person) {
    val email: String = requireNotNull(person.email)
}

로그와 같이 추가작업이 필요하다면 엘비스 연산자를 활용할 수 있다.