2016-08-23 3 views
-1

하위 메서드가 예외를 throw하면 전용 "패키지"예외의 캡슐화가 좋은 것으로 간주됩니까?구성 요소를 통해 예외를 throw하는 것이 좋습니다.

public String doStuff() throws UtilsException { 
     try { 
      throw new NullPointerException("test"); 
     } catch (NullPointerException e) { 
      throw new UtilsException("something occured", e); 
     } 
    } 

    //use this exception for all classes of this package/component 
    public class UtilsException extends Exception { 
     private static final long serialVersionUID = 1L; 

     public UtilsException() { 
      super(); 
     } 

     public UtilsException(String message, Throwable cause) { 
      super(message, cause); 
     } 

     public UtilsException(String message) { 
      super(message); 
     } 

     public UtilsException(Throwable cause) { 
      super(cause); 
     } 

    } 

Optional.empty() 복잡한 응용 프로그램의 잡기/던지는 피하기 위해 대안이 될 수 있을까?

public Optional<String> doStuff() throws UtilsException { 
     try { 
      return Optional.of("ok"); 
     } catch (NullPointerException e) { 
      LOG.error("Something append... {}", e.getMessage()); 
      return Optional.empty(); 
     } 
    } 
+1

하위 예외를 상위 예외로 래핑하는 것은 일부 설정에서는 좋은 방법 일 수 있지만 'NullPointerException'에 대해 말하는 경우에는 예외가 아닙니다. 당신은'NullPointerException'을 잡아서는 안됩니다. 그것은 귀하의 모든 레벨에서 동일한 의미를 지닙니다. 'Optional'은'NullPointerException'이 발생한 보고서가 아니라 잠재적으로 부재중 인 값을 캡슐화합니다. 우선 NullPointerException을 피하십시오. 'Optional'을 사용하면됩니다. – Holger

+0

NullPointerException은 설정을 설명하기위한 것이 었습니다. 감싸는 것은 예외의 근원을 따르는 것이 흥미로운 것처럼 보인다. –

+1

그럼 정말 나쁜 예를 골랐어 요. 클래스 바이트를로드하는 동안 발생한'IOException'을 캡슐화하는'ClassNotFoundException'을 고려하십시오. 특수한 경우는 확인 된 예외를 허용하지 않는 API 계층입니다 (예 : 데이터베이스에 대한'Collection' 뷰를 고려하십시오. 그곳에는 기본 스토리지 시스템의 오류를 래핑해야합니다. 'IllegalStateException' 또는'NoSuchElementException'에서. 제 생각에는 이것들이 더 좋은 예입니다. – Holger

답변

1

첫째, 당신은 결코 캐치 (일반 또는 런타임 예외) NullPointerException이 다른 사람과 같은 복귀가 someting는 일을해야한다. 좋아, 어쩌면 거기에 버그가있는 타사 api()처럼 그렇게해야 할 경우가 거의 없습니다.

NullPointer, ClassCast, IllegalArgument 등의 예외는 프로그램에 버그가있을 때 발생하며 을 버블 링하여 프로그램의 상위 구성 요소에서 처리하도록해야합니다.

예외가 오류를 알리는에 대한 "책임"이다 고 말했다되고 그건

, (그리고 악명 높은 문구가 온다)가 달려 ..., 따라서 그들에 무엇을 결정하기 위해 그들을 사용하는 발신자에 대한 정보해야 해야 할 것. 다음 사항을 고려하십시오 : 당신은 위의 예에서 볼 수 있듯이

public void readFile(String path) throws IOException { 
    // read file content 
    return content; 
} 


try { 
    return readFile("foo.txt"); 
} catch(FileNotFound e) { 
    // For this specific scenario not finding the file is not a problem  
    return ""; 
} catch(IOException e) { 
    // This we are not expecting to happen, if the file exists we should be 
    // able to read it, otherwise we should inform the user. 
    log.error(e); 
    display("We had a problem reading the file, Check the file permissions and try again"); 
} 

것은, 당신이 때를 무엇을 결정할 수있는 클라이언트의 능력을 제거하기 때문에이 경우 에서 다른 예외의 IOException가 포장 싶지 않을 것이다 오류가 발생했습니다. 또한

는 IOException가 발신자가 결정할 수 있도록 예외 객체가 너무 좀 더 구체적인 오류를 당신의 방법은 발생 오류의 종류를 일반화하기 위해 상속을 을 사용하고 던질 수 있기 때문에 "포장"의 한 형태 있습니다 무엇 할 것.

포장지

예외를 래핑하는 것은 좋은 습관이며 진행 방법입니다. 예를 들어, 기상 정보를 얻는 것이 주 기능인 lib를 만드는 경우입니다.

첫 번째 버전에서는 간단하게 유지하고 타사 API를 사용하여 그 날의 값을 가져 왔습니다. API의 주요 방법은 다음과 같습니다.

public Weather getWeather(Date day) throws HTTPException { 
    return weather.get(day); 
} 

귀하의 API를 꽤 잘하고있다 그러나 당신은 당신이 날씨 API에 너무 많은 요청을하고있는 및 당신은 매우 빨리 지불 시작해야합니다 나타났습니다. 그런 다음 데이터베이스 테이블 에 결과를 캐시하기로 결정하여 요청 량을 줄일 수 있습니다. 당신은 가장 확실하게 당신의 API의 사용자 암호를 해독되므로이 문을 던졌습니다에

public Weather getWeather(Date day) throws HTTPException, SQLException { 
    Weather w = getFromCache(day); 
    if (w != null) { 
     return w; 
    } else { 
     return getAndCache(day); 
    } 
} 

지금 당신은 문제가 있다면, 당신은이 새로운 예외를 추가 할 수 없습니다.

캐시 API에서 wheter api 또는 의 데이터를 가져 오는 데 문제가 있으면 api의 사용자는 아무런 관심이 없습니다. 단지 오류가 발생하기를 원할뿐입니다.이러한 예외를 에 포장하면 WeatherFetchException과 같이 일반적으로 예외를 적용하는 것이 좋습니다.

가 의미가 때 당신은 정말 달려 ... 나에게 엄지 손가락의

규칙은, 의미 당신의 예외를 유지하고 당신이 그들을 포장 할 경우에만 할 볼 수 있듯이 호출자가 오류를 처리하는 기능이 제거되지 않은 경우

그냥 예외를 감싸는 것이 가장 좋은 방법은 아닙니다.

관련 문제