본문 바로가기

소프트웨어-이야기/프로그래밍 언어와 프레임워크

[예외처리] notification pattern

catched exception 

  • 회복해야하는 대상의 예외
  • 자바에서는 메서드가 던질 수 있는 확인된 예외 목록을 선언해야한다. 아니면 해당 예외를 try/catch으로 선언해야한다.
 public boolean validate() {
    if (this.description.length() > 100) {
      throw new DescriptionTooLongException();
    }

    final LocalDate parsedDate;

    try {
      parsedDate = LocalDate.parse(this.date);
    } catch (DateTimeParseException e) {
      throw new InvalidDateFormat();
    }

	....

    return true;
  }
public class DescriptionTooLongException extends Exception {

}
public class InvalidDateFormat extends Exception {

}

 

uncatched exception

  • 프로그램을 실행하면서 언제든 발생할 수 있는 종류의 예외.
  • 확인된 예외와 달리 메서드 시그니처에 명시적으로 오류를 선언하지 않으면 호출자도 이를 꼭 처리할 필요가 없다.
 public boolean validate() {
    if (this.description.length() > 100) {
      throw new IllegalArgumentException("The description is too long");
    }

    final LocalDate parsedDate;

    try {
      parsedDate = LocalDate.parse(this.date);
    } catch (DateTimeParseException e) {
      throw new IllegalArgumentException("Invalid format for date", e);
    }

	....

    return true;
  }

catched exception vs uncatched exception

예외가 발생했을 때, 프로그램이 회복되도록 강제할 것인지를 생각해보면 답이 나온다.

예를 들어, 일시적으로 발생하는 오류이면 retry를 시도하거나 안내 메시지를 출력해서 응용프로그램의 반응성을 훌륭하게 유지할 수 있다.

보통 비즈니스 로직 검증 (잘못된 형식이나 연산 등)시, 발생한 문제는 불필요한 try/catch 구문을 줄일 수 있도록 미확인 예외로 결정한다.

예외가 발생했을 때, 응용프로글매을 어떻게 회복시킬 것인지 애매한 상황도 있다. 이런 상황에서는 API 사용자에게 오류를 복구하라고 강제할 필요가 없다. 게다가 시스템 오류 (ex. 디스크 풀)가 발생했을 때, 사용자가 할 수 있는 일이 없으므로 시스템 오류도 미확인 예외로 지정한다.

즉, 대다수의 예외를 미확인 예외로 지정하고 꼭 필요한 상황에서만 확인된 예외로 지정해 불필요한 코드를 줄여야한다.

 

사용자가 지정한 Exception이 많은 경우, 각각의 예외에 적합하고 정확한 회복 기법을 구현할 수 있다. 그러나 너무 많은 설정 작업이 필요하고, 여러 예외를 선언해야하고, 사용자가 이 모든 예외를 처리해야해서 생산성이 현저하게 떨어지게 된다.

그렇다고 과도하게 동일한 미확인 예외로 지정하는 경우, 구체적인 회복 로직을 만들 수 없다.

그리고 두가지 패턴 모두 여러 오류가 발생했을 때, 모든 오류 목록을 확인할 수 없다.

 

Notification Pattern

이 경우에는 Notification 패턴을 사용하면 좋다.

import java.util.ArrayList;
import java.util.List;

public class Notification {

  private final List<String> errors = new ArrayList<>();

  public void addError(final String message) {
    errors.add(message);
  }

  public boolean hasErrors() {
    return !errors.isEmpty();
  }

  public String errorMessage() {
    return errors.toString();
  }

  public List<String> getErrors() {
    return this.errors;
  }
}

 

 

참고

실전자바소프트웨어개발 3장

https://github.com/sojeongw/real-world-software-development/blob/main/bank-statement-analyzer/src/main/java/com/demo/bankstatementanalyzer/Notification.java