[교재 EffectiveJava] 아이템 75. 예외의 상세 메시지에 실패 관련 정보를 담으라

반응형
728x90
반응형

예외의 상세 메시지 권장

예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 그 예외의 스택 추적(stack trace) 정보를 자동으로 출력한다. 스택 추적은 예외 객체의 toString 메서드를 호출하여 얻는 문자열이다.  이 정보가 실패 원인을 분석하는 유일한 정보인 경우가 많으며 해당 실패를 재현하기 어렵다면 더 자세한 정보를 얻기가 어렵거나 불가능하다. 따라서 예외의 toString 메서드에 실패 원인에 관한 정보를 가능한 한 많이 담아 반환하는 일이 아주 중요하다. 사후 분석을 위해 실패 순간의 상황을 정확히 포착해 예외의 상세 메시지에 담아야한다.

 

실패 순간을 포착하려면 발생한 예외에 관여된 모든 매개변수와 필드의 값을 실패 메시지에 담아야한다. 예외가 발생한 원인은 제각각이므로, 예외의 상세 메시지를 통해 무엇을 고쳐야할지 분석하는데 도움을 받을 수 있다. 

 

관련 데이터를 모두 담아야 하지만 장황할 필요는 없다.

문제를 분석하는 사람은 스택 추적뿐 아니라 관련 문서와 소스 코드를 함께 살펴본다. 스택 추적에는 예외가 발생한 파일 이름과 줄 번호, 스택에서 호출한 다른 메서드들의 파일 이름, 줄버호까지 정확히 기록되어있다.

 

예외의 상세 메시지와 최종 사용자에게 보여줄 오류 메시지를 혼동해서는 안된다. 최종 사용자에게는 친절한 안내 메세지를 보여줘야하고, 예외 메시지는 가독성보다는 담긴 내용이 훨씬 중요하다. 실패를 적절히 포착하려면 필요한 정보를 예외 생성자에서 모두 받아서 상세 메시지까지 미리 생성해놓는 방법도 괜찮다. 

 

예를들어, IndexOutOfBoundsException 생성자는 String을 받고있다.

 

IndexOutOfBoundsException.java
/**
* Constructs an {@code IndexOutOfBoundsException} with the specified detail
* message.
*
* @param s the detail message
*/
public IndexOutOfBoundsException(String s) {
    super(s);
}

위 코드를 다음과 같이 구현했어도 좋았을 것이다. 

 /**
   * IndexOutOfBoundsException을 생성한다.
   *
   * @param lowerBound 인덱스의 최솟값
   * @param upperBound 인덱스의 최댓값 + 1
   * @param index 인덱스의 실젯값
   */
  public IndexOutOfBoundsException(int lowerBound, int upperBound, int index) {
    // 실패를 포착하는 상세 메시지를 생성한다.
    super(String.format(
        "최솟값: %d, 최댓값: %d, 인덱스: %d",
        lowerBound, upperBound, index));

    // 프로그램에서 이용할 수 있도록 실패 정보를 저장해둔다.
    this.lowerBound = lowerBound;
    this.upperBound = upperBound;
    this.index = index;
  }

자바9에서 정수 인덱스를 받는 생성자가 추가되었다.

 

IndexOutOfBoundsException.java
/**
* Constructs a new {@code IndexOutOfBoundsException} class with an
* argument indicating the illegal index.
*
* <p>The index is included in this exception's detail message.  The
* exact presentation format of the detail message is unspecified.
*
* @param index the illegal index.
* @since 9
*/
public IndexOutOfBoundsException(int index) {
    super("Index out of range: " + index);
}

아쉽게도 인덱스만 받고, 최댓값과 최솟값은 받지 않는다. 이처럼 자바 라이브러리에선느 이 조언을 적극 수용하지는 않지만, 위 바램 코드처럼 적용되었다면 실패를 더 잘 포착할 수 있다 

 

또한, 고품질의 상세 메시지를 만들어내는 코드를 예외 클래스 안으로 모아주는 효과도 있어, 클래스 사용자가 메시지를 만드는 작업을 중복하지 않아도 된다.

 

예외는 실패와 관련된 정보를 얻을 수 있는 접근자 메서드를 적절히 제공하는게 좋다. 포착한 실패 정보는 예외 상황을 극복하는데에 유용할 수 있으므로 접근자 메서드는 비검사 예외보다는 검사 예외에서 더 빛을 발한다. 

 

 

반응형

Designed by JB FACTORY