메서드가 던지는 예외는 그 메서드를 올바로 사용하는 데 아주 중요한 정보다.
따라서 각 메서드가 던지는 예외 하나하나를 문서화하는 데 충분한 시간을 쏟아야 한다.
자바독 @throws 태그
검사 예외는 항상 따로따로 선언하고, 각 예외가 발생하는 상황을 자바독의 @throws 태그를 사용하여 정확히 문서화하자.
공통 상위 클래스 하나로 뭉뚱그려 선언하지는 말자.
- 극단적인 예로 메서드가 Exception이나 Throwable을 던진다고 선언해서는 안된다.
- 메서드 사용자에게 각 예외에 대처할 수 있는 힌트를 주지 못할뿐더러, 같은 맥락에서 발생할 여지가 있는 다른 예외들까지 삼켜버릴 수 있어 API 사용성을 크게 떨어뜨린다.
JWT Access 토큰을 재발급해주는 메서드
main은 오직 JVM만이 호출하므로 Exception을 던지도록 선언해도 괜찮다.
비검사 예외의 문서화
비검사 예외도 검사 예외처럼 문서화해 두면 좋다.
- 비검사 예외는 일반적으로 프로그래밍 오류를 뜻하는데, 자신이 일으킬 수 있는 오류들이 무엇인지 알려주면 프로그래머는 자연스럽게 해당 오류가 나지 않도록 코딩하게 된다.
잘 정비된 비검사 예외 문서는 사실상 그 메서드를 성공적으로 수행하기 위한 전제조건이 된다.
- public 메서드라면 필요한 전제조건을 문서화해야 하며, 그 수단으로 가장 좋은 것이 바로 비검사 예외들을 문서화하는 것이다.
발생 가능한 비검사 예외를 문서로 남기는 일은 인터페이스 메서드에서 특히 중요하다.
- 이 조건이 인터페이스의 일반 규약에 속하게 되어 그 인터페이스를 구현한 모든 구현체가 일관되게 동작하도록 해준다.
메서드가 던질 수 있는 예외를 각각 @throws 태그로 문서화하되, 비검사 예외는 메서드 선언의 throws 목록에 넣지 말자.
- 검사냐 비검사냐에 따라 API 사용자가 해야 할 일이 달라지므로 이 둘을 확실히 구분해 주는 게 좋다.
- 자바독 유틸리티는 메서드 선언의 throws 절에 등장하고 메서드 주석의 @throws 태그에도 명시한 예외와 @throws 태그에만 명시한 예외를 시각적으로 구분해 준다. 이로 인해 어느 것이 비검사 예외인지 알 수 있다.
비검사 예외를 현실적으로 문서화하기 불가능할 때
클래스를 수정하면서 새로운 비검사 예외를 던지게 되어도 소스 호환성과 바이너리 호환성이 그대로 유지된다는 게 가장 큰 이유다.
- 다른 사람이 작성한 클래스를 사용하는 메서드가 발생가능한 모든 예외를 공들여 문서화했을 때
- 후에 이 외부 클래스가 새로운 비검사 예외를 던지게 수정된다면, 아무 수정도 하지 않은 나의 메서드는 문서에 언급되지 않은 새로운 비검사 예외를 전파하게 될 것이다.
한 클래스에 정의된 많은 메서드가 같은 이유로 같은 예외를 던진다면 그 예외를 각각의 메서드가 아닌 클래스 설명에 추가하자.
- NullPointerException이 가장 흔한 사례인데, 클래스의 문서화 주석에 이 클래스의 모든 메서드는 인수로 null이 넘어오면 NullPointerException을 던진다라고 명시해 주자.
NullPointerException을 클래스 설명에 추가
/**
* 사용자 정보를 처리하는 클래스.
* 이 클래스의 모든 메서드는 인수로 null이 넘어오면 NullPointerException을 던집니다.
*/
public class UserProcessor {
/**
* 사용자 정보를 생성하는 메서드.
*
* @param name 사용자 이름 (null일 수 없음)
* @param age 사용자 나이 (null일 수 없음)
* @throws NullPointerException 인수가 null인 경우 발생
*/
public void createUser(String name, Integer age) throws NullPointerException {
if (name == null || age == null) {
throw new NullPointerException("Arguments cannot be null.");
}
// 사용자 정보 생성 작업 수행
}
/**
* 사용자 정보를 업데이트하는 메서드.
*
* @param name 사용자 이름 (null일 수 없음)
* @param age 사용자 나이 (null일 수 없음)
* @throws NullPointerException 인수가 null인 경우 발생
*/
public void updateUser(String name, Integer age) throws NullPointerException {
if (name == null || age == null) {
throw new NullPointerException("Arguments cannot be null.");
}
// 사용자 정보 업데이트 작업 수행
}
}
결론
- 메서드가 던질 가능성이 있는 모든 예외를 문서화하자.
- 검사 예외든 비검사 예외든, 추상 메서드든 구체 메서드든 모두 마찬가지다.
- 문서화에는 자바독의 @throws 태그를 사용하자.
- 검사 예외만 메서드 선언의 throws 문에 일일이 선언하고, 비검사 예외는 메서드 선언에는 기입하지 말자.
- 발생 가능한 예외를 문서로 남기지 않으면 다른 사람이 그 클래스나 인터페이스를 효과적으로 사용하기 어렵다.
'Java > Effective Java' 카테고리의 다른 글
[Effective Java] Item 76. 가능한 한 실패 원자적으로 만들라 (0) | 2023.08.12 |
---|---|
[Effective Java] Item 75. 예외의 상세 메시지에 실패 관련 정보를 담으라 (0) | 2023.08.12 |
[Effective Java] Item 73. 추상화 수준에 맞는 예외를 던지라 (0) | 2023.08.11 |
[Effective Java] Item 72. 표준 예외를 사용하라 (0) | 2023.08.06 |
[Effective Java] Item 71. 필요 없는 검사 예외 사용은 피하라 (0) | 2023.08.06 |