Skip to content

아이템 73. 추상화 수준에 맞는 예외를 던지라 - Fin #181

Open
@Irisation23

Description

@Irisation23

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

Originally posted by bunsung92 March 21, 2023
📝 구성

Table of contents generated with markdown-toc


0. TL;DR 📚

  • 아래 계층의 예외 처리가 어렵고, 그 예외를 상위 계층을 통해 노출한다면 예외 번역을 사용하라.
  • 예외 연쇄를 이용하면 상위 계층에는 맥락에 어울리는 고수준 예외를 던지면서 근본 원인도 함께 알려주어 오류 분석에 도움이 된다.

예외 번역? 예외 연쇄?


1. 잘못 처리된 예외

  • 메서드가 저수준 예외를 처리하지 않고, 바깥으로 전파하는 경우 (발생 위치에서 예외 처리하지 않는 경우를 말함) 에 대한 문제 발생
    • 수행하려는 일과 관련없는 예외가 발생할 수있다.
    • 구현 방식을 바꾸면 또 다른 예외를 발생시켜 기존 클라이언트 프로그램을 깨뜨릴 수 있다.

2. 예외 번역(Exception Translation)

위와 같은 상황에서의 해결책으로 제시 될 수 있는 방법이다.

  • 상위 계층에서는 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꿔 던져야 한다.
public abstract class AbstractSequentialList<E> extends AbstractList<E> {
    
    /**
     * Returns the element at the specified position in this list.
     *
     * @param index index of the element to return
     * @return the element at the specified position in this list
     * @throws IndexOutOfBoundsException if the index is out of range
     *         (index < 0 || index >= size())
     */
    public E get(int index) {
        try {
            return listIterator(index).next();
        } catch (NoSuchElementException exc) {
            throw new IndexOutOfBoundsException("Index: "+index);
        }
    }
}
  • 예외 번역시 저수준 예외가 디버깅에 도움이 된다면 예외 연쇄(exception chanining)을 사용하는게 좋다.

3. 예외 연쇄(exception chanining)

문제의 근본 원인(cause)인 저수준 예외를 고수준 예외에 실어 보내는 방식이다.

예외 연쇄라는 용어를 보다 더 쉽게 이해하기에 좋은 방법은 상승이라는 키워드를 생각 해 보는게 좋을것 같다.
저수준 -> 고수준
보다 더 추상화된 클래스에서의 예외 처리등을 키워드로 잡을 수 있다.

  • 별도의 접근자 메서드(Throwable 의 getCause()) 를 통해 필요하다면 언제든 저수준 예외를 꺼내 볼 수 있다.
class HigherLevelException extends Exception {
    HigherLevelException(Throwable cause) {
        super(cause);
    }
}

class ChildClass {
    public void publicAPIMethod() {
        try {
            //do somthing...
        } catch (LowerLevelException cause) {
            throw new HigherLevelException(cause);
        }
    }
}
  • 대부분의 표준 예외는 예외 연쇄용 생성자를 갖고 있다.
  • 예외 연쇄는 문제의 원인을 (getCause 메서드) 프로그램에서 접근할 수 있게 해주며, 원인과 고수준 예외의 스택 추적 정보 통합을 해준다.
  • 예외를 전파하는 것보다 예외 번역하는 것이 우수한 방법 이지만 남용해서는 안된다.
  • 가능하다면 저수준 메서드는 예외를 발생하지 않도록 하는것이 최선이다.
  • 때로는 상위 계층 메서드 의 매개변수 값을 아래 계층 메서드로 건내기 전에 미리 검사하는 방법으로 목적을 달성할 수 있다.(아이템 49. 매개변수가 유효한지 검사하라 #114 )

3.1 차선책

  • 아래 계층에서의 예외를 피할 수 없다면, 상위 계층에서 그 예외를 조용히 처리하여 문제를 API 호출자에게 전파하지 않는 방법이 있다.
  • 상위 계층에서 해당 처리를 이었다면 로깅을 통해 기록하는게 좋다.
  • 클라이언트 코드와 사용자에게 문제를 전파하지 않으면서 프로그래머가 로그를 분석해 추가 조치를 취할 수 있도록 해주기 때문이다.
image

4. 최종 정리 📚

그래서 추상화 수준에 맞는 예외는 무엇일까? 🤔

  • 예외 번역예외 연쇄를 고려한 예외의 처리이다.
  • 예외 번역은 저수준 예외를 처리하고 있는 자신(this) 수준에 맞는 예외로 바꿔 던지는 것이다.
  • 예외 연쇄는 문제의 원인(cause) 저수준 예외를 고수준 예외에 실어 보내는 방식이다.

5. 회고 🧹

2023-03-26 일

  • 고수준, 저수준, 예외 번역, 예외 연쇄 등등 용어가 쉽지않은 파트였다.
  • 원인을 던져주냐가 예외 번역과 예외 연쇄를 구분 지어주는 포인트라 생각 할 수 있는것 같다.
  • 예외를 다루는 일은 언제나 중요하며, 로깅하는 습관 역시 뼈에 박아야 한다고 생각한다.
  • 따라서, 진행될 프로젝트에는 예외도 상황에 맞게, 원하는 예외 처리를 할 수 있도록 노력해야겠다.

출처

https://github.com/Meet-Coder-Study/book-effective-java/blob/main/10%EC%9E%A5/73_%EC%B6%94%EC%83%81%ED%99%94_%EC%88%98%EC%A4%80%EC%97%90_%EB%A7%9E%EB%8A%94_%EC%98%88%EC%99%B8%EB%A5%BC_%EB%8D%98%EC%A0%B8%EB%9D%BC_%EA%B9%80%EC%84%9D%EB%9E%98.md
https://data-flair.training/blogs/java-exception/

Metadata

Metadata

Assignees

Labels

10장 예외이펙티브 자바 10장 (예외)

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions