아이템 주제처럼
메서드나 생성자 작성 시 매개변수 유효검사를 왜 해야 하는지
이해하는 것이 요번 아이템의 핵심인 것 같다.
"메서드와 생성자 대부분은 입력 매개변수의 값이 특정 조건을 만족하기를 바란다.
... 이런 제약은 반드시 문서화해야 하며메서드 몸체가 시작되기 전에 검사해야 한다."
매개변수 검사를 제대로 하지 못하면 생기는 문제
▶️ 메서드가 수행되는 중간에 모호한 예외를 던질 수 있다.
▶️ 메서드가 잘 수행되었지만 잘못된 결과를 반환할 수 있다.
▶️ 메서드는 문제없이 수행됐지만,
어떤 객체를 이상한 상태로 만들어 놓아서 미래를 알 수 없는 시점에 메서드와 관련 없는 오류를 낼 수 있다.
(실패 원자성을 어기는 결과)
public과 protected 메서드는 매개변수 값이 잘못됐을 때 던지는 예외를 문서화해야 한다. (@throws 자바독 태그 사용)
보통 던지는 예외는 IllegalArgumentException, IndexOutOfBoundException, NullPointerException이다.
매개변수의 제약을 문서화한다면 그 제약을 어겼을 때 발생하는 예외도 함께 기술해야 한다.
예시)
public class Sample {
/**
* 항상 음이 아닌 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()이 호출될 때 NullPointException을 던지지만,
메서드 설명에 없는 이유는 개별 메서드가 아닌 BigInteger 클래스 수준에서 기술했기 때문이다.
클래스 수준 주석은 그 클래스의 모든 public 메서드에 적용되기 때문에
각 메서드에 일일이 기술하는 것보다 훨씬 깔끔한 방법이다.
자바의 null 검사 기능
@Nullable 같은 어노테이션을 사용해서 특정 매개변수가 null이 될 수 있음을 알려줄 수 있지만, 표준방법이 아니라고 한다.
👉 자바 7에 추가된 java.uti.Objects.requireNonNull 메서드
이걸 사용하면 null 검사를 수동으로 하지 않아도 되고, 원하는 예외 메시지도 지정할 수 있다.
또한 입력을 그대로 반환하므로 값을 사용하는 동시에 null 검사를 수행할 수 있다.
반환값은 그냥 무시하고 필요한 곳 어디서든 순수한 null 검사 목적으로 사용 가능하다.
this.strategy = Ojbects.requireNonNull(strategy, "전략");
👉 자바 9에 추가된 Objects에 범위 검사 기능 checkFromIndexSize, checkFromToIndex, checkIndex 메서드
예외 메시지를 지정할 수 없고, 리스트와 배열 전용으로 설계됐다.
또한 닫힌 범위는 다루지 못하는 제약들이 있기 때문에 null 검사 메서드만큼 유연하지 않다.
public이 아닌 메서드의 매개변수 유효성 검증 방법
👉 assert(단언문)
public이 아닌 메서드 즉, 공개되지 않은 메서드라면 메서드 호출 상황을 통제할 수 있고
유효한 값만이 메서드에 넘겨지리라는 걸 보증할 수 있다.
재귀 정렬용 private 도우미 함수
public class Sample2 {
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;
}
}
"핵심은 이 단언문들은 자신이 단언한 조건이 무조건 참이라고 선언한다는 것이다.
단언문은 몇 가지 점에서 유효성 검사와 다르다."
1️⃣ 실패하면 AssertionError를 던진다.
2️⃣ 런타임에 아무런 성능 저하도 없다.
메서드 몸체 실행 전에 매개변수 유효성을 검사하라의 예외
- 유효성 검사 비용이 지나치게 높거나 실용적이지 않을 때
- 계산 과정에서 암묵적 검사가 수행될 때
💡"암묵적 유효성 검사에 너무 의존했다가는 실패 원자성을 해칠 수 있으니 주의"
실패 원자성에 대한 블로그 글을 첨부해 보았다.
가능한 한 실패 원자적으로 만들자
실패 원자적(failure-atomic)
donghyeon.dev
정리
"메서드나 생성자를 작성할 때 그 매개변수들에 어떤 제약이 있는지 생각해야 한다.
그 제약들을 문서화하고 메서드 코드 시작 부분에서 명시적으로 검사해야 한다."
'🤓 스터디 > 이펙티브 자바' 카테고리의 다른 글
[아이템 51] 메서드 시그니처를 신중히 설계하라 (0) | 2023.04.17 |
---|---|
[아이템 50] 적시에 방어적 복사본을 만들라 (0) | 2023.04.17 |
[아이템 43] 람다보다는 메서드 참조를 사용하라 (2) | 2023.04.07 |
[아이템 25] 톱레벨 클래스는 한 파일에 하나만 담으라 (0) | 2023.04.07 |
[아이템 24] 멤버 클래스는 되도록 static으로 만들라 (0) | 2023.04.07 |
댓글