1 minute read

메서드 혹은 생성자에서, 매개변수 제약은 반드시 문서화해야 하며 메서드 내 로직이 수행되기 전에 선행되어 검사해야 한다.

이와 같은 매개변수 검사를 제대로 하지 못한다면…

  • 메서드 수행 중 예외를 던지며 실패
  • 메서드가 수행되지만 잘못된 결과를 반환
  • 메서드가 문제없이 수행되지만, 어떤 객체의 상태를 변이시켜 알 수 없는 미래에 메서드와 관련 없는 오류가 발생

위와 같은 문제가 발생할 수 있다.

public & protected 메서드

/** * (현재 값 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);    
	... // 계산 수행
}

위와 같이, 매개변수의 제약을 문서화한다면 그 제약을 어겼을때 발생하는 예외도 함께 기술해야 한다.

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

Java 7부터는 java.util.Objects.requireNonNull 메서드를 사용해 더 이상 null 검사를 수동으로 하지 않아도 된다.

또한, Java 9에서는 ObjectscheckFromIndexSize, checkFromToIndex, checkIndex라는 범위 검사 기능도 더해졌다. 다만 이 메서드들은 예외 메시지를 지정할 수 없고, 리스트와 배열 전용이며 닫힌 범위는 다룰 수 없다는 단점이 있다.

private 메서드

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;
    ...// 계산 수행
}

private 메서드는 제작자가 직접 메서드 호출 상황을 통제할 수 있으므로 유효한 값만이 메서드에 넘져진다고 보증해야 한다.

이와 같은 경우, 단언문 (assert)를 사용해 매개변수 유효성을 검사하자.

  • 실패시 AssertionError를 던진다.
  • 런타임에 효과 및 성능 저하가 없다.

생성자 매개변수와 같이 메서드가 직접 사용하지 않으나 나중에 쓰기 위해 저장하는 경우, 특히 더 신경 써서 검사해야 한다.

예외

다음과 같은 경우 매개변수 유효성 검사를 시행하지 않을 수도 있다.

  • 유효성 검사 비용이 지나치게 높을때
  • 계산 과정에서 암묵적으로 검사가 수행될 때 (Collections.sort(List))

Leave a comment