Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

아이템 75. 예외의 상세 메시지에 실패 관련 정보를 담으라 #180

Open
JoisFe opened this issue Mar 26, 2023 Discussed in #179 · 0 comments
Open

아이템 75. 예외의 상세 메시지에 실패 관련 정보를 담으라 #180

JoisFe opened this issue Mar 26, 2023 Discussed in #179 · 0 comments

Comments

@JoisFe
Copy link
Member

JoisFe commented Mar 26, 2023

Discussed in https://github.com/orgs/Study-2-Effective-Java/discussions/179

Originally posted by JoisFe March 26, 2023

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

스택 추적 (Stack Trace)

  • 예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 그 예외의 스택 추적 정보를 자동으로 출력
  • 스택 추적은 예외 객체의 toString 메서드를 호출해 얻는 문자열 (보통은 예외의 클래스 이름 뒤에 상세 메시지가 붙는 형태)
  • 해당 정보가 실패 원인을 분석해야 하는 프로그래머 혹은 SRE (Site Reliability Engineer, SRE)가 얻을 수 있는 유일한 정보인 경우가 많음
  • 또한 실패를 재현하기 어렵다면 더 자세한 정보를 얻기 어렵거나 불가능함

예외의 toString 메서드에 실패 원인에 관한 정보를 가능한 많이 담아 반환하는 일은 매우 중요

  • 사후 분석을 위해 실패 순간의 상황을 정확히 포착해 예외의 상세 메시지에 담아야 함!

예외의 상세 메시지를 작성하는 방법

실패 순간을 포착하려면 발생한 예외에 관련된 모든 매개변수와 필드의 값을 실패 메시지에 담아야 함

  • EX) IndexOutOfBoundsException의 상세 메시지는 범위의 최솟값과 최댓값, 그리고 그 범위를 벗어났다는 인덱스의 값을 담아야 함
  • (해당 정보는 실패에 관한 많은 것을 알려줌)
  • 셋 중 한두 개 혹은 셋 모두가 잘못됐을 수 있기 때문
  • 이상의 현상들은 모두 원인이 다르므로 현상을 보면 무엇을 고쳐야 할지를 분석하는데 도움이 됨
  • 관련 데이터를 모두 담아야 하지만 장황할 필요는 없음 (문제를 분석하는 사람은 스택 추척뿐만 아니라 관련 문서, 소스코드를 함께 살펴보기 때문)

예외의 상세 메시지와 최종 사용자에게 보여줄 오류 메시지를 혼동해선 안됨

  • 최종 사용자에게는 친절한 안내 메시지를 보여줘야 함
  • 반면 예외 메시지는 가독성 보단 담긴 내용이 훨씬 중요
  • 예외 메시지의 주 소비층은 문제를 분석해야 할 프로그래머와 SRE 엔지니어 이기 때문

실패를 적절히 포착하려면 필요한 정보를 예외 생성자에서 모두 받아서 상세 메시지까지 미리 생성해놓는 방법 또한 괜찮음

  • EX) 현재의 IndexOutOfBoundsException 생성자는 String을 받지만 아래의 예시 코드와 같이 구현해도 좋음
    /**
     * 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에 드디어 정수 인덱스 값을 받는 생성자가 추가되었음
  • 하지만 아쉽게도 최솟값과 최댓값까지 받지는 않음
  • 이처럼 자바 라이브러리에서 이 조언을 적극 수용하진 않았지만 위 같은 코드처럼 권장함!
  • 이렇게 하면 프로그래머가 던지는 예외는 자연스럽게 실패를 더 잘 포착함
  • 또한 고품질의 상세 메시지를 만들어내는 코드를 예외 클래스 안으로 모아주는 효과가 있음
  • 따라서 클래스 사용자가 메시지를 만드는 작업을 중복하지 않아도 됨

예외는 실패와 관련한 정보를 얻을 수 있는 접근자 메서드를 적절히 제공하는 것이 좋음

  • 위 내용은 아이템 70. 복구할 수 있는 상황에는 검사 예외를, 프로그래밍 오류에는 런타임 예외를 사용하라 #164 참고
  • 앞의 예시 코드를 예로 들면 lowerBound, upperBound, index 정도가 적당
  • 포착한 실패 정보는 예외 상황을 복구하는 데 유용할 수 있으므로 접근자 메서드는 비검사 예외보다는 검사 예외에서 더 빛을 발함
  • 비검사 예외의 상세 정보에 프로그램적으로 접근하길 원하는 프로그래머는 드물 것이지만 (전혀 없지는 않음)
  • 하지만 toString이 반환한 값에 포함된 정보를 얻어올 수 있는 API를 제공하자 일반 원칙을 따른다는 관점에서는 비검사 예외에도 상세 정보를 알려주는 접근자 메서드를 제공하는 것을 권함!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant