티스토리 뷰
728x90
반응형
매개변수가 유효한지 검사하라
- 메서드와 생성자 대부분은 입력 매개변수의 값이 특정 조건을 만족하기를 바랍니다. 예를 들어 인덱스의 값은 음수여서는 안되고, 객체 참조는 NULL이어서는 안됩니다. 이런식의 제약은 반드시 문서화해야하며, 메서드 몸체가 시작되기 전에 검사해야 합니다.
- 오류는 가능한 한 빨리 잡아야하며, 오류를 발생한 즉시 잡지 못하면 해당 오류를 감지하기 어려워지고, 감지하더라도 오류의 발생 지점을 찾기 어려워집니다.
💡 매개변수 검사를 제대로 하지 않은 경우
- 메서드가 수행되는 중간에 모하한 예외를 던지며 실패할 수 있습니다.
- 더 나쁜 상황은 메서드가 잘 수행되지만 잘못된 결과를 반환하는 상황이 발생할 수도 있습니다.
- 더 좋지 않은 상황은 메서드는 문제없이 수행됐지만 어떤 객체를 이상한 상태로 만들어 놓아서 미래에 알 수 없는 시점에 이 메서드와는 관련없는 오류를 낼 때입니다.
- 다시 말해 매개변수 검사에 실패하면 실패 원자성을 어기는 결과를 초래할 수 있습니다. 실패 원자성이란, 객체가 메서드 호출해 실패하더라도 상태가 이전과 동일해야 한다는 것입니다.
💡 public과 protected 메서드는 문서화하라
- 매개변수의 제약을 문서화하고 이 제약을 어겼을 때 발생할 수 있는 예외를 명시하면 해당 API를 사용하는 개발자가 해당 제약을 지킬 확률을 높일 수 있습니다.
- 아래에서는 NPE에 대한 내용은 기술되어 있지 않지만, BigInteger 클래스 수준에서 기술하였기 때문에 이 클래스의 public 메서드 전체에 적용되기에 각 메서드에서 기술할 필요가 없습니다.
/**
* (현재 값 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);
}
//...
}
💡 Objects.requireNonNull
- 자바 7에 추가된 Objects.requireNonNull 메서드는 null 검사를 자동으로 해줍니다. 내부적으로는 아래처럼 되어 있으며, null인 경우를 체크해주고 null이 아니라면 값을 그대로 반환합니다.
public class Example {
public static void main(String[] args) {
String s = null;
s = Objects.requireNonNull(s, "해당 문자열은 NULL입니다.");
System.out.println(s);
}
}
public class Objects {
// ...
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
// ...
public static <T> T requireNonNull(T obj, String message) {
if (obj == null)
throw new NullPointerException(message);
return obj;
}
}
💡 단언문(assert)를 사용한 매개변수 유효성 검증
- 공개되지 않은 메서드(private)라면 메서드가 호출되는 상황을 통제할 수 있습니다. 즉 public이 아닌 메서드라면 단언문을 사용해 매개변수 유효성을 검증할 수 있습니다.
- 이 단언문들은 자신이 단언한 조건이 무조건 참이라고 선언합니다. 만약 참이 아닌 경우 AssertionError가 발생합니다.
- 단언문은 일반적인 유효성 검사와 다릅니다.
- 다른점 1 - 실패하면 무조건 AssertionError가 발생합니다.
- 다른점 2 - 런타임에는 아무런 효과도 성능 저하도 없습니다. 단 java를 싱핼할 때 명령줄에서 --ea 혹은 --enablessertions 플래그를 설정하면 런타임에도 영향을 미칩니다.
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;
// 계산 수행
}
💡 매개변수 유효성검사 예외상황
- 항상 로직 최상단에서 매개변수 유효성 검사를 해야하는것만은 아닙니다.
- 유효성 검사 비용이 너무 높거나 실용적이지 않거나, 계산 과정에서 암묵적으로 검사가 수행될 때는 예외상황으로 둘 수 있습니다.
💡 매개변수 유효성검사 예외상황에 대한 예시
- List를 정렬하는데 Collections.sort() 메서드 같은 경우 모든 원소가 상호 비교될 수 있어야 정렬을 할 수 있는데, 상호 비교할 수 없는 경우 ClassCastException을 던집니다. 그렇기에 이런 경우는 비교하기전에 모든 객체의 상호 비교성을 검사할 필요가 없습니다.
✔️ 정리
- 일반적으로 로직의 최상단에 매개변수에 대한 유효성 검사 로직을 넣는게 좋습니다. 이를 놓칠 경우 잘못된 값으로 인해 오류를 감지하는게 어려워지고, 더욱 심각한 상황이되면 오류의 발생 지점을 찾기 어려워집니다.
728x90
반응형
'스터디 > 이펙티브 자바' 카테고리의 다른 글
이펙티브 자바 - Item51. 메서드 시그니처를 신중히 설계하라 (0) | 2022.08.04 |
---|---|
이펙티브 자바 - Item50. 적시에 방어적 복사본을 만들라 (0) | 2022.08.03 |
이펙티브 자바 - Item48. 스트림 병렬화는 주의해서 적용하라 (0) | 2022.08.01 |
이펙티브 자바 - Item47. 반환 타입으로는 스트림보다 컬렉션이 낫다 (0) | 2022.08.01 |
이펙티브 자바 - Item46. 스트림에서는 부작용 없는 함수를 사용하라 (0) | 2022.07.31 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- 람다 표현식
- 트랜잭셔널 아웃박스 패턴 스프링 부트 예제
- spring boot redisson destributed lock
- java userThread와 DaemonThread
- redis sorted set
- 자바 백엔드 개발자 추천 도서
- pipeline architecture
- spring boot excel download paging
- microkernel architecture
- JDK Dynamic Proxy와 CGLIB의 차이
- spring boot redisson sorted set
- space based architecture
- polling publisher spring boot
- spring boot poi excel download
- 서비스 기반 아키텍처
- spring boot redis 대기열 구현
- transactional outbox pattern spring boot
- redis sorted set으로 대기열 구현
- transactional outbox pattern
- spring boot excel download oom
- 트랜잭셔널 아웃박스 패턴 스프링부트
- spring boot 엑셀 다운로드
- spring boot redisson 분산락 구현
- pipe and filter architecture
- redis 대기열 구현
- @ControllerAdvice
- java ThreadLocal
- 레이어드 아키텍처란
- 공간 기반 아키텍처
- service based architecture
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
글 보관함