<aside> 💡

이번 장에서는 메서드를 설계할 때 주의할 점들을 살펴본다. 구체적으로는 매개변수와 반환값을 어떻게 처리해야 하는지, 메서드 시그니처는 어떻게 설계해야 하는지, 문서화는 어떻게 해야 하는지를 다룬다. 이번 장의 내용 중 상당 부분은 메서드뿐 아니라 생성자에도 적용된다. 그리고 사용성, 견고성, 유연성에 집중할 것이다.

</aside>

49] 매개변수가 유효한지 검사하라

메서드와 생성자의 입력 매개변수의 값은 특정 조건을 만족해야 한다. 이런 제약은 반드시 문서화해야하며 메서드 몸체가 시작되기 전에 검사해야 “오류는 가능한 한 빨리 잡아야 한다”는 일반 원칙에 부합한다. 또한 메서드 몸체가 실행되기 전에 매개변수를 확인한다면 잘못된 값이 넘어왔을 때 즉각적이고 깔끔한 방식으로 예외를 던질 수 있다.

- 매개변수 유효성을 제대로 검사하지 못하면 생기는 문제

메서드가 수행되는 중간에 모호한 예외를 던지며 실패 할 수 있다. ******더 나쁜 상황은 메서드가 잘 수행되지만 잘못된 결과를 반환할 때다. 다시 말해 매개변수 검사에 실패하면 **실패 원자성(아이템 76)**을 어기는 결과를 낳을 수 있다.

- 매개변수 값이 잘못됐을때 던지는 예외를 문서화 하자

@throws JavaDoc 을 사용하면 된다. 보통은 IllegalArgumentException, IndexOutOfBoundsException, 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);
    // ... (계산 수행)
}

해당 메서드는 mnull이면 NullPointerException을 던진다. 클래스 수준 주석은 각 메서드에 일일이 기술하는 것보다 훨씬 깔끔한 방법이다. 또한 @Nullable 이나 이와 비슷한 애너테이션을 사용할 수도 있지만 표준적인 방법은 아니다.

- java.util.objects.requireNonNull

하지만 자바 7에 추가된 java.util.objects.requireNonNull 메서드는 유연하고 사용하기도 편하니, 더 이상 null 검사를 수동으로 하지 않아도 된다.

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

이처럼 반환값은 그냥 무시하고 필요한 곳 어디서든 순수한 null 검사 목적으로 사용해도 된다.

자바 9에서는 Objects에 범위 검사 기능도 더해졌다. checkFromIndexSize, checkFromToIndex, checkIndex라는 메서드들인데, 예외 메시지를 지정할 수 없고, 리스트와 배열 전용으로 설계되어서 이런 제약이 걸림돌이 되지 않을 경우 유용하고 편하게 사용할 수 있다.

- 단언문(assert)