[아이템49] 매개변수가 유효한지 검사해라

2024. 11. 20. 23:44·1️⃣ 백앤드/이펙티브 자바

1. 오류는 가능한 한 빨리 잡자

오류를 발생한 즉시 잡지 못하면 오류를 감지하기 어렵고, 지점을 찾기 어려워진다. 예를 들어 인덱스 값은 음수이면 안되며, 객체 참조는 null 이면 안된다 와 같은 특정 조건을 메서드와 생성자의 매개변수에 바라는 경우가 있다. 메서드 본체로 넘어가기 전, 매개변수를 확인해야 깔끔한 방식으로 예외를 던질 수 있다. 

public 과 protected 메서드는 매개변수 값이 잘못됐을 때 던지는 예외를 문서화하자

@throws 자바독 태그를 사용하자. IllegalArgumentException, IndexOutOfBoundException, NullPointerException 등이 될 것이다. 이를 문서화하고 제약을 어겼을 때 발생하는 예외도 기술하자. 전형적인 예시를 살펴보자.

/**
 * (현재 값 mod m) 값을 반환한다. 이 메서드는
 * 항상 음이 아닌 BigInteger를 반환한다는 점에서 remainder 메서드와 다르다.
 *
 * @param m 계수(양수여야 한다)
 * @return 현재 값 mod m
 * @throws ArithmeticException m이 0보다 작거나 같으면 발생한다.
 */
public BigInteger mod(BigInteger m) {
    if (m.signum() <= 0) {
        throw new ArithmeticException("계수(m)는 양수여야 합니다. " + m);
    ... // 계산 수행
}

이 메서드는 m 이 null 이면, m.signum() 호출 때 NullPointerException 을 던진다. 이는 메서드가 아닌 BigInteger 클래스 수준에서 기술되었다. 클래스 수준에서 기술할 수 있다면 훨씬 깔끔한 방법이 될 수 있다.

 

2. 자바에 추가된 검사 기능

자바 7에서는 java.util.Objects.requireNonNull 메서드를 통해 null 검사를 수동으로 하지 않아도 되었다. 예외 메세지도 지정할 수 있다. 또한 입력을 그대로 반환하기도 하여 값을 사용함과 동시에 null 검사를 수행할 수 있다.

this.strategy = Objects.requiredNonNull(strategy, "전략");

자바 9에서는 Objects 에 범위 검사도 가능해졌다. checkFromIndexSize, checkFromToIndex, checkIndex 라는 메서드들은 리스트와 배열 전용으로 설계되어 유연하지는 않다. 그래도 유용하게 사용될 수 있다.

 

3. private 메서드의 매개변수 검증

public 이 아닌 메서드라면 단언문(assert) 을 사용해 매개변수 유효성을 체크하자. 아래 예시를 살펴보자.

private static void sort(long a[], int offset, int length) {
	assert a != null;
	assert offset >= 0 && offset <= a.length;
	assert length >= 0 && length <= a.length = offset;
	... // 계산 수행
}

assert 를 통해 선언된 조건이 무조건 참이라고 선언해버린다. 실패하면, AssertionError 를 던진다.

assertionError

그리고, 런타임에 아무런 효과도, 아무런 성능 저하도 없다. 참고로, 메서드가 직접 사용하지는 않으나 나중에 쓰기 위해 저장하는 매개변수는 특히 더 신경쓰자. 나중에 메서드로부터 반환받고 사용하려 할 때 에러가 발생한다면, 디버깅이 괴로워질 수 있다. 추가로,생성자 매개변수의 유효성 검사는 클래스 불변식을 어기는 객체가 만들어지지 않게 하는데 꼭 필요하다. 예를 들어, final 필드를 사용하는 클래스에서 불변성을 유지하려면, 생성자에서 상태를 설정한 후 해당 필드를 변경할 수 없게 해야 한다.

 

4. 예외

메서드 몸체 실행 전에 매개변수 유효성 검사를 한다는 규칙에도 물론 예외는 있다. 유효성 검사 비용이 지나치게 높거나, 실용적이지 않거나, 계산 과정에서 암묵적으로 검사가 수행될 수 있다. 예를 들어, Collection.sort(List) 메서드를 생각해보면 원소들이 모두 상호 비교될 수 있어야 한다. 만약 비교될 수 없는 타입이 들어가 있다면 비교할 때 이미 ClassCastException 을 던질 것이다. 미리 손수 비교할 필요가 없다는 것이다.

결론은 매개변수에 제약을 두는 게 좋다는게 아니라, 최대한 범용적으로 설계하자. 제약이 적을수록 좋을 수 있다.

'1️⃣ 백앤드 > 이펙티브 자바' 카테고리의 다른 글

[아이템51] 메서드 시그니처를 신중히 설계하라  (0) 2024.11.24
[아이템50] 적시에 방어적 복사본을 만들라  (0) 2024.11.21
[아이템48] 스트림 병렬화는 주의해서 적용하라  (0) 2024.11.20
[아이템47] 반환 타입으로는 스트림보다 컬렉션이 낫다  (0) 2024.11.19
[아이템46] 스트림에서는 부작용 없는 함수를 사용하라  (0) 2024.11.18
'1️⃣ 백앤드/이펙티브 자바' 카테고리의 다른 글
  • [아이템51] 메서드 시그니처를 신중히 설계하라
  • [아이템50] 적시에 방어적 복사본을 만들라
  • [아이템48] 스트림 병렬화는 주의해서 적용하라
  • [아이템47] 반환 타입으로는 스트림보다 컬렉션이 낫다
HOZINU
HOZINU
주니어 백앤드 개발자의 세상만사 이모저모. 주로 개발 이야기를 다룸.
  • HOZINU
    백엔드 탐험 일지
    HOZINU
  • 전체
    오늘
    어제
  • 블로그 메뉴

    • ⛪ HOME
    • 🌍 GITHUB
    • 카테고리 (73)
      • 1️⃣ 백앤드 (72)
        • 이펙티브 자바 (72)
      • 2️⃣ CS (0)
        • 운영체제 (0)
        • 네트워크 기초 (0)
        • 네트워크 응용 (0)
        • SSL & PKI (0)
        • 기타 (0)
      • 3️⃣ 코딩테스트 (0)
      • 4️⃣ 개인공부 (0)
        • MSA (0)
        • REDIS (0)
      • 5️⃣ 일상이야기 (1)
  • 인기 글

  • 태그

    컴포지션
    equals
    try-with-resources
    hashcode
    빌더
    정적 팩터리 메서드
    finalizer
    싱글턴
    계층구조
    optional
    멤버클래스
    캡슐화
    정보은닉
    CLONE
    표준예외
    맥북
    Cleaner
    로타입
    Comparable
    의존객체
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
HOZINU
[아이템49] 매개변수가 유효한지 검사해라
상단으로

티스토리툴바