확인 된 예외를 포착하고 RuntimeException을 발생시키는 것이 좋은 방법입니까?


70

나는 동료의 일부 코드를 읽었으며 종종 다양한 예외를 포착하고 대신 항상 'RuntimeException'을 던졌습니다. 나는 항상 이것이 나쁜 습관이라고 생각했다. 내가 잘못?


17
"체크 된 예외의 가격은 공개 / 폐쇄 원칙 위반입니다. 코드의 메소드에서 체크 된 예외를 던지고 캐치가 3 단계 이상인 경우, 귀하와 캐치 사이의 각 메소드의 서명에서 해당 예외를 선언해야합니다 이는 낮은 수준의 소프트웨어 변경으로 인해 더 높은 수준의 서명 변경이 발생할 수 있음을 의미합니다. " —Robert C. Martin,«청결 코드», 107 페이지
Songo

6
Jim Waldo가 "Java : The Good Parts" shop.oreilly.com/product/9780596803742.do 에서 확인되지 않은 예외에 대해 언급 한 것은 흥미 롭습니다. 성인 프로그래머는 확인 된 예외 만 처리해야합니다. 우리는 단지 6 년 전에 나온 JUG에서 그것을 읽었고 좋은 조언처럼 보였습니다! 이제 기능적 프로그래밍을 통해 확인 된 예외는 완전히 다루기 힘들다. 스칼라와 코 틀린과 같은 언어에는 언어가 없습니다. 검사되지 않은 예외도 검사하기 시작했습니다.
GlenPeterson

@GlenPeterson 당신은 또한 실행을 피하고 대신 합계 유형을 사용하는 FP의 조언을 얻습니다
jk.

기능적인 인터페이스의 명백한 경우도 있습니다 : 내장 기능 인터페이스 (즉 Function, Predicate매개 변수화하지 않는, 등등) 조항을 던졌습니다. 이것은 당신이 있다는 것을 의미 필요 () 메소드 어떤 스트림의 내부 루프의 모든 체크 된 예외를 잡을 랩, 그리고 다시 발생 할 수 있습니다. 그 자체로 확인 된 예외가 나쁜 생각인지에 대한 균형을 유지합니다.
Joel Cornett

예외를 통해 의미를 전달하기 위해 RuntimeException의 사용자 정의 서브 클래스를 작성하는 데 아무런 문제가 없습니다.
Joel Cornett

답변:


55

나는 동료가 잘못하고 있는지 아닌지를 알기에 충분한 맥락을 알지 못하므로 일반적인 의미에서 이에 대해 논쟁 할 것입니다.

확인 된 예외를 여러 가지 런타임 예외로 바꾸는 것이 항상 잘못된 습관이라고 생각하지 않습니다 . 확인 된 예외종종 개발자에 의해 오용 되고 남용 됩니다.

확인되지 않은 예외를 사용하지 않을 경우 (복구 할 수없는 조건 또는 제어 흐름) 사용하기가 매우 쉽습니다. 특히 확인 된 예외가 호출자가 복구 할 수없는 조건에 사용되는 경우 유용한 메시지 / 상태로 해당 예외를 런타임 예외로 바꾸는 것이 정당하다고 생각합니다. 불행히도 많은 경우, 회복 불가능한 상황에 처하게되면 빈 캐치 블록이있는 경향이 있으며 이는 최악의 일 중 하나입니다. 이러한 문제를 디버깅하는 것은 개발자가 겪을 수있는 가장 큰 고통 중 하나입니다.

따라서 복구 가능한 조건을 처리한다고 생각되면 그에 따라 처리해야하며 예외가 런타임 예외로 바뀌지 않아야합니다. 복구 할 수없는 조건에 대해 확인 된 예외가 사용되는 경우 런타임 예외로 전환하는 것이 정당화 됩니다.


17
대부분의 실제 응용 프로그램에서는 복구 할 수없는 조건이 거의 없습니다. "이 작업은 실패 했으므로 멋진 오류 메시지를 표시 / 로그하고 다음 메시지를 계속 / 다음에 기다립니다"라고 말할 수있는 수준이 거의 있습니다.
Michael Borgwardt

6
사실 @MichaelBorgwardt이지만, 이러한 종류의 처리 장소는 종종 응용 프로그램의 최상위 수준에 있으므로 개발자가 예외를 낮은 수준에서 "처리"하는 경우 일반적으로 처리를 쉽게 제거하고 예외를 적용 할 수 있습니다. 위로 향하여. 예를 들어, JSF와 같은 웹 프레임 워크는 최상위 레벨에서 예외를 포착하고 로그 메시지를 인쇄하며 다른 요청을 계속 처리합니다 (기본 처리가 적합 함을 말하지는 않음).
DavidS

40

GOOD수 있습니다 . 읽어주세요:

http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html

대부분의 경우 클라이언트 코드는 SQLException에 대해 아무것도 할 수 없습니다. 확인되지 않은 예외로 변환하는 것을 망설이지 마십시오. 다음 코드를 고려하십시오.

public void dataAccessCode(){
  try{
      ..some code that throws SQLException
  }catch(SQLException ex){
      ex.printStacktrace();
  }
} 

이 catch 블록은 예외를 억제하고 아무 것도 수행하지 않습니다. 정당한 것은 내 클라이언트가 SQLException에 대해 할 수있는 일이 없다는 것입니다. 다음과 같은 방식으로 처리하는 것은 어떻습니까?

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
} 

SQLException을 RuntimeException으로 변환합니다. SQLException이 발생하면 catch 절에서 새로운 RuntimeException이 발생합니다. 실행 스레드가 일시 중단되고 예외가보고됩니다. 그러나 불필요한 예외 처리로 비즈니스 오브젝트 계층을 손상 시키지는 않습니다. 특히 SQLException에 대해 아무것도 수행 할 수 없기 때문입니다. 캐치에 근본 원인이 필요한 경우 JDK1.4부터 모든 예외 클래스에서 사용 가능한 getCause () 메소드를 사용할 수 있습니다.

확인 된 예외를 던져서 복구 할 수없는 것은 도움이되지 않습니다.

어떤 사람들은 확인 된 예외를 전혀 사용해서는 안된다고 생각합니다. http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html을 참조하십시오 .

최근 브루스 에켈 (Bruce Eckel)과로드 존슨 (Rod Johnson)을 포함한 유명한 전문가들이 확인 된 예외에 대한 정통적인 입장에 완전히 동의했지만, 확인 된 예외의 독점적 사용은 그다지 좋은 아이디어가 아니라고 결론을 내렸다. 검사 된 예외는 많은 대규모 프로젝트에서 중요한 문제의 원인이되었습니다. Eckel은 모든 예외 사항을 확인하지 말 것을 제안하면서보다 극단적 인 견해를 취합니다. 존슨의 견해는 더 보수적이지만, 여전히 확인 된 예외에 대한 정통 선호는 과도하다고 제안합니다. (거의 확실하게 Java 기술을 사용한 경험이 많은 C #의 설계자는 언어 디자인에서 확인 된 예외를 생략하여 모든 예외를 확인되지 않은 예외로 만들었습니다.

또한 같은 링크에서 :

확인되지 않은 예외를 사용하기로 한 결정은 복잡한 것이며 명확한 대답이 없다는 것이 분명합니다. Sun의 조언은 아무것도 사용하지 않는 것이며 C # 접근 방식 (Eckel과 다른 사람들이 동의하는)은 모든 것에 사용하는 것입니다. 다른 사람들은 "중간계가있다"고 말합니다.


13

아니요, 당신은 틀리지 않습니다. 그의 연습은 매우 잘못 인도되어 있습니다. 문제를 일으킨 문제를 포착하는 예외를 던져야합니다. RunTimeException이 광범위하고 도달했습니다. NullPointerException, ArgumentException 등이어야합니다. 무엇이 잘못되었는지 정확하게 설명하는 것. 이를 통해 처리해야하는 문제와 "생존하지 않는"시나리오 여야하는 오류와 프로그램의 생존을 가능하게하는 문제를 차별화 할 수 있습니다. 질문에 제공된 정보에 빠진 것이 없으면 "다음 오류시 이력서"보다 그가하는 일이 약간 더 낫습니다.


1
힌트 주셔서 감사합니다. 그리고 RuntimeException에서 직접 상속받은 사용자 정의 예외를 던지면 어떻게 될까요?
RoflcoptrException

27
@Gary Buyn은 : 많은 사람들이 확인이 끝난 예외는 실패 언어 설계 실험이라고 생각하고 그들이 하지 습관의 문제로, 드물게 사용되어야하는 것들이다.
Michael Borgwardt

7
@Gary Buyn : 토론에 대한 개요를 잘 보여주는 기사가 있습니다. ibm.com/developerworks/java/library/j-jtp05254/index.html 또한 Java가이 기능을 도입한지 15 년이 넘었지만 다른 언어에서는 채택하지 않았습니다. C ++도 비슷한 기능을 사용하지 않습니다.
Michael Borgwardt

7
@ c_maker : 실제로 Bloch는 대부분 정통보기를 홍보하며 귀하의 의견은 주로 더 많은 예외, 기간을 사용하는 것에 관한 것 같습니다. 내 견해로는 확인 된 예외를 사용하는 유일한 유효한 이유는 모든 발신자가 즉시 처리 해야하는 조건이기 때문입니다.
Michael Borgwardt

14
불필요하게 던지는 검사 예외는 캡슐화를 위반합니다. 'getAccounts ()'와 같은 간단한 메소드에서 'SQLException', 'NullPointerException'또는 'FileNotFoundException'이 발생하면 어떻게합니까? 당신은 그것을 처리 할 수 ​​있습니까? 아마도 'catch (Exception e) {}'일 것입니다. 게다가 예외는 구현에 따라 다릅니다! 계약의 일부가되어서는 안됩니다! 당신이 알아야 할 것은 오류 가 있다는 입니다. 구현이 변경되면 어떻게 되나요? 갑자기 모든 것이 바뀌어야 메소드가 더 이상 'SQLException'을 발생시키지 않고 대신 'ParseXMLException'을 발생시킵니다!
KL

8

따라 다릅니다.

이 연습은 현명 할 수도 있습니다 . 웹 개발과 같은 많은 상황이 있습니다. 예외가 발생하면 아무것도 할 수 없습니다 (예 : 코드에서 일치하지 않는 DB를 복구 할 수 없기 때문에 개발자 만 할 수 있습니다). 이러한 상황에서는 throw 된 예외를 런타임 예외로 랩하여 다시 던지는 것이 좋습니다. 일부 예외 처리 계층에서 이러한 모든 예외를 포착 할 수있는 것보다 오류를 기록하고 사용자에게 멋진 현지화 된 오류 코드 + 메시지를 표시하십시오.

반면 , 예외가 런타임이 아닌 경우 (체크 된 경우) API 개발자는이 예외를 해결할 수 있으며 복구해야 함을 나타냅니다. 가능하다면 분명히해야합니다.

다른 해결책은이 확인 된 예외를 호출 계층에 다시 던지지 만 예외가 발생한 곳에서 해결할 수 없으면 여기에서도 해결할 수 없을 것입니다 ...


API 개발자가 수행 한 작업을 알고 확인 된 예외를 잘 사용했으면합니다. 런타임 예외를 처리하는 것을 선호하는 API를 보았습니다. 문서화하면서 클라이언트가 원하는 경우 잡을 수있는 옵션이 있습니다.
c_maker

예외를 발생시키는 메소드는 일반적으로 호출자가 예외를 복구 할 수 있는지 알 수 없습니다. 반면에, 내부 메소드가 예외를 던진 이유를 알고 이유가 외부 메소드의 API와 일치하는 경우 메소드가 내부 메소드에 의해 발생 된 확인 된 예외 만 이스케이프하도록해야합니다. 내부 메소드가 예기치 않은 확인 된 예외를 처리하는 경우, 확인 된 예외로 버블 링하면 호출자에게 발생한 상황에 대한 잘못된 정보가 남을 수 있습니다.
supercat

2
exception handling layer예를 들어 webapp, 필터 등 을 언급 해 주셔서 감사합니다 .
Jake Toronto

5

이것에 대한 의견을 듣고 싶지만 이것이 반드시 나쁜 습관이 아닌 경우가 있습니다. (또는 심하게 나쁘다). 그러나 어쩌면 나는 틀렸다.

종종 사용중인 API가 특정 유스 케이스에서 실제로 발생한다고 상상할 수없는 예외를 throw합니다. 이 경우 잡은 예외를 원인으로하여 RuntimeException을 발생시키는 것이 좋습니다. 이 예외가 발생하면 프로그래밍 오류의 원인 일 수 있으며 올바른 스펙을위한 범위 내에 있지 않습니다.

RuntimeException이 나중에 잡히지 않고 무시된다고 가정하면 OnErrorResumeNext 근처에 없습니다.

OnErrorResumeNext는 누군가 예외를 잡아서 단순히 무시하거나 그냥 인쇄 할 때 발생합니다. 이것은 거의 모든 경우에 아주 나쁜 습관입니다.


이것은 호출 트리의 맨 위 근처에있을 수 있습니다. 여기서 할 수있는 유일한 일은 정상적으로 복구하려고 시도하고 특정 오류를 아는 것이 실제로 도움이되지 않는 것입니다. 이 경우 오류를 기록하고 계속 진행해야합니다 (다음 레코드 처리, 사용자에게 오류가 발생했음을 알리는 등). 그렇지 않으면 아닙니다. 실제로는 예외와 거의 같은 예외를 처리해야합니다. 다음 처리기에서는 예외를 흰 코끼리로 감싸지 마십시오.
Michael K

@MichaelK 문제는 "실제로 오류에 가깝다"는 사실은 종종 "직접 제어 할 수없는 여러 개의 중간 계층을 통한 것"을 의미합니다. 예를 들어, 수업에서 특정 인터페이스를 구현해야하는 경우 내 손이 묶여 있습니다. 이것은 호출 트리에서 임의로 깊게 발생할 수 있습니다. 인터페이스가 내 통제하에 있더라도 throw 선언을 추가하면 생각할 수있는 구체적인 구현이 제한되어 있으면 추상화가 누출 될 수 있습니다. 모든 고객이 몇 가지 구현 세부 사항에 대한 비용을 지불하게하는 것은 훌륭한 디자인 트레이드 오프 IMO가 아닙니다.
Tim Seguine

4

TL; DR

전제

  • 오류가 복구 불가능한 경우 런타임 예외가 발생해야합니다. 오류가 코드에 있고 외부 상태에 의존하지 않는 경우 (복구가 코드를 수정 함).
  • 코드가 정확하지만 네트워크 연결이 없거나 파일을 찾을 수 없거나 손상된 등의 외부 상태가 예상되지 않은 경우 확인 된 예외가 발생해야합니다.

결론

전파 또는 인터페이스 코드가 기본 구현이 외부 상태에 따라 달라진다고 가정하는 경우 확인 된 예외를 런타임 예외로 다시 던질 수 있습니다.


이 절에서는 예외 중 하나가 발생해야하는시기에 대해 설명합니다. 결론에 대한 자세한 설명을 읽으려면 다음 가로 막대로 건너 뛸 수 있습니다.

런타임 예외를 발생시키는 것이 적절한시기는 언제입니까? 코드가 정확하지 않고 코드를 수정하여 복구가 적절한 경우 런타임 예외가 발생합니다.

예를 들어, 다음에 대한 런타임 예외를 발생시키는 것이 적절합니다.

float nan = 1/0;

이것은 제로 런타임 예외로 나누기를 던질 것입니다. 코드 에 결함이 있기 때문에 적합합니다 .

또는 예를 들어 다음은 HashMap의 생성자 의 일부입니다 .

public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " +
                loadFactor);
    // more irrelevant code...
}

초기 용량 또는로드 팩터를 수정하려면 올바른 값이 전달되도록 코드를 편집하는 것이 적절합니다. 서버의 현재 상태, 디스크의 현재 상태, 파일 또는 다른 프로그램. 잘못된 인수로 호출되는 생성자는 호출 코드의 정확성에 따라 달라집니다. 잘못된 계산으로 인해 잘못된 매개 변수 또는 오류를 놓친 부적절한 흐름이 원인입니다.

확인 된 예외를 발생시키는 것이 언제 적절한가요? 코드를 변경하지 않고 문제 복구 할 수 있으면 확인 된 예외가 발생합니다 . 또는 다른 용어로 바꾸려면 코드가 올바른 동안 오류가 상태와 관련이있을 때 확인 된 예외가 발생합니다.

이제 "복구"라는 단어가 까다로울 수 있습니다. 목표를 달성하는 다른 방법을 찾을 수도 있습니다. 예를 들어 서버가 응답하지 않으면 다음 서버를 시도해야합니다. 이러한 종류의 복구가 가능하다면 훌륭하지만 복구가 의미하는 것은 아닙니다. 복구는 사용자에게 발생한 상황을 설명하는 오류 대화 상자를 표시하거나 서버 응용 프로그램 인 경우 복구가 가능할 수 있습니다 관리자에게 이메일을 보내거나 오류를 적절하고 간결하게 기록하기까지합니다.

mrmuggles의 답변에 언급 된 예를 들어 보겠습니다.

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
}

이것은 확인 된 예외를 처리하는 올바른 방법이 아닙니다. 방법의 범위 에서 예외를 처리 할 수 없다는 것만으로 앱이 중단되는 것은 아닙니다. 대신 다음과 같이 더 높은 범위로 전파하는 것이 적절합니다.

public Data dataAccessCode() throws SQLException {
    // some code that communicates with the database
}

호출자가 복구 할 수있게합니다.

public void loadDataAndShowUi() {
    try {
        Data data = dataAccessCode();
        showUiForData(data);
    } catch(SQLException e) {
        // Recover by showing an error alert dialog
        showCantLoadDataErrorDialog();
    }
}

확인 된 예외는 정적 분석 도구이므로 프로그래머가 구현을 배우거나 시행 착오 프로세스를 거치지 않아도 특정 호출에서 잘못 될 수있는 문제를 분명히합니다. 따라서 오류 흐름의 일부가 무시되지 않습니다. 점검 된 예외를 런타임 예외로 다시 던지는 것은이 노동 절약 정적 분석 기능에 대해 작동합니다.

또한 호출 계층은 위에서 설명한 것처럼 더 큰 사물 체계에 대한 더 나은 컨텍스트를 가지고 있음을 언급 할 가치가 있습니다. dataAccessCode호출 되는 원인은 여러 가지 일 수 있으며 , 호출의 특정 이유는 호출자에게만 표시되므로 실패시 올바른 복구에서 더 나은 결정을 내릴 수 있습니다.

이제 우리는 이러한 차이점을 분명히 알았으므로 확인 된 예외를 런타임 예외로 다시 던져도 괜찮을 때 추론을 진행할 수 있습니다.


위에서 주어진 예외를 RuntimeException으로 다시 던지는 것이 언제 적절한가요? 사용중인 코드가 외부 상태에 대한 의존성을 가정하지만 외부 코드에 의존하지 않는다는 것을 분명히 주장 할 수 있습니다.

다음을 고려하세요:

StringReader sr = new StringReader("{\"test\":\"test\"}");
try {
    doesSomethingWithReader(sr); // calls #read, so propagates IOException
} catch (IOException e) {
    throw new IllegalStateException(e);
}

이 예제 IOException에서 API는 Reader외부 상태에 액세스하도록 설계되었으므로 코드가 전파 되고 있지만 StringReader구현시 외부 상태에 액세스하지 않는다는 것을 알고 있습니다. 이 범위에서 우리는 호출에 관련된 부분이 IO 또는 다른 외부 상태에 액세스하지 않는다고 확신 할 수있는 구현 범위를 알지 못하는 동료를 놀라게하지 않고 예외를 런타임 예외로 안전하게 다시 던질 수 있습니다. IO 액세스 코드에서)가 발생한다고 가정합니다 IOException.


외부 엄격히 의존 예외 상태로 유지하는 이유 확인은 그들이 (예측 코드의 버전마다 재생 될 것이다 논리 따라 예외 달리) 비 결정적이다. 예를 들어 0으로 나누려고하면 항상 예외가 발생합니다. 0으로 나누지 않으면 예외가 발생하지 않으며 예외가 발생하지 않기 때문에 해당 예외를 처리 할 필요가 없습니다. 그러나 파일에 액세스하는 경우 한 번 성공한다고해서 다음에 성공한다는 의미는 아닙니다. 사용자가 권한을 변경했거나 다른 프로세스가 파일을 삭제 또는 수정했을 수 있습니다. 따라서 항상 예외적 인 경우를 처리해야합니다. 그렇지 않으면 버그가있을 수 있습니다.


2

독립형 애플리케이션 용. 응용 프로그램이 예외를 처리 할 수 ​​없다는 것을 알면 검사 된 RuntimeException을 throw하는 대신 오류를 발생시키고 응용 프로그램 충돌을 일으키고 버그보고를 희망하며 응용 프로그램을 수정하십시오. ( 확인 된 것과 확인되지 않은 것에 대한 찬반 양론 에 대한 자세한 내용 은 mrmuggles답변 을 참조하십시오 .)


2

이것은 많은 프레임 워크에서 일반적인 관행입니다. 예를 들어 Hibernate정확하게이 작업을 수행합니다. API는 API를 클라이언트 측에 방해해서는 안되며 API Exception를 호출하는 곳에서 처리 할 코드를 명시 적으로 작성해야하므로 방해가되어야합니다. 그러나 그 장소는 처음에 예외를 처리하기에 적합한 장소가 아닐 수도 있습니다.
사실 솔직히 말해서 이것은 "인기있는"주제이며 많은 논쟁이므로 한 편도 들지 않지만 친구가하는 일 / 제안은 평범하지 않거나 드물지 않다고 말할 것입니다.


1

"체크 된 예외"전체는 나쁜 생각입니다.

구조화 된 프로그래밍은 정보가 "가까운"경우에만 함수간에 전달 될 수 있습니다. 보다 정확하게는 정보가 두 가지 방식으로 만 기능간에 이동할 수 있습니다.

  1. 인수 전달을 통해 발신자에서 수신자로.

  2. 수신자에서 발신자에게 반환 값으로.

이것은 근본적으로 좋은 것입니다. 이것은 코드에 대해 로컬로 추론 할 수있게하는 것입니다. 프로그램의 일부를 이해하거나 수정해야하는 경우 해당 부분과 "가까운"부분 만 살펴 봐야합니다.

그러나 어떤 상황에서는 중간에 "알지 못하는"사람없이 "먼"기능으로 정보를 보내야합니다. 이것은 예외를 사용해야 할 때입니다. 예외는 발생기 (코드의 일부가 명령문을 포함 할 수 있음 )에서 핸들러 (코드의 일부 가 n 인 예외와 호환 되는 블록을 포함 할 수 있음 )로 전송 된 비밀 메시지 입니다.throwcatchthrow

확인 된 예외는 메커니즘의 비밀을 파괴하며 그 메커니즘의 존재 이유를 파괴합니다. 함수가 호출자가 정보를 "알도록"할 수있는 경우, 해당 정보를 반환 값의 일부로 직접 보냅니다.


메소드가 호출자가 제공하는 함수를 실행하는 경우 이러한 종류의 문제가 실제로 혼란을 초래할 수 있음을 언급하는 것이 좋습니다. 함수를받는 메소드의 저자는 많은 경우 호출자가 무엇을 기대하는지, 또는 호출자가 어떤 예외를 기대하는지 알거나 신경 쓸 이유가 없습니다. 메소드를 수신하는 코드가 확인 된 예외를 발생시키지 않을 것으로 예상되는 경우, 제공되는 메소드는 공급 업체가 포착 할 수있는 확인되지 않은 예외를 발생시키는 모든 확인 된 예외를 랩핑해야 할 수 있습니다.
supercat

0

상황에 따라 다를 수 있습니다. 어떤 시나리오에서는 친구가하고있는 일을하는 것이 현명합니다. 예를 들어, 일부 클라이언트에 대해 API를 노출하고 클라이언트가 구현 세부 사항을 가장 잘 알고 싶어하는 경우, 특정 구현 예외는 다음과 관련 될 수 있습니다. 구현 세부 사항이며 클라이언트에게 공개 할 수 없습니다.

확인 된 예외를 방해하지 않으면 클라이언트 자체가 예외적 인 조건을 사전 검증 할 수 있으므로 클라이언트가 더 깨끗한 코드를 작성할 수있는 API를 노출시킬 수 있습니다.

예를 들어 Integer.parseInt (String)은 문자열을 가져와 이에 해당하는 정수를 반환하고 문자열이 숫자가 아닌 경우 NumberFormatException을 발생시킵니다. 이제 필드 age가 있는 양식 제출 이이 방법을 통해 변환되었지만 클라이언트가 이미 유효성을 확인했을 것이므로 예외 확인을 강요 할 필요가 없습니다.


0

여기 몇 가지 질문이 있습니다.

  1. 확인 된 예외를 확인되지 않은 예외로 변환해야합니까?

일반적으로 발신자가 포착하고 복구 할 것으로 예상되는 예외를 확인해야합니다. 다른 예외 (유일하게 합리적인 결과가 전체 작업을 중단하는 것이거나 특별히 처리하는 것에 대해 걱정할 가치가없는 것으로 판단되는 경우)는 확인하지 않아야합니다.

예외에 따라 catch 및 복구가 필요한지 여부에 대한 판단이 작업중인 API의 판단과 다를 수 있습니다. 상황에 따라 중요한 경우가 있는데, 한 상황에서 처리 할 가치가있는 예외는 다른 상황에서는 처리 할 가치가 없을 수도 있습니다. 때로는 기존 인터페이스로 손을 강요합니다. 예, 확인 된 예외를 확인되지 않은 예외 (또는 다른 유형의 확인 된 예외)로 바꾸는 합당한 이유가 있습니다.

  1. 확인되지 않은 예외를 확인 된 예외로 바꾸려면 어떻게해야합니까?

가장 중요한 것은 예외 체인 기능을 사용하는 것입니다. 이렇게하면 원래 예외의 정보가 손실되지 않으며 디버깅에 사용될 수 있습니다.

둘째, 사용할 예외 유형을 결정해야합니다. 일반 런타임 예외를 사용하면 호출자가 문제점을 판별하기가 더 어려워 지지만 호출자가 문제점을 판별하려고 시도하는 경우 예외를 점검하지 않도록 변경하지 않아야 함을 표시 할 수 있습니다.


0

부울 질문에서 두 가지 논란의 여지가있는 답변 후에 다르게 대답하기는 어렵지만 소수의 장소에서도 언급 된 관점을 제시하고 싶습니다. 중요한 중요성을 충분히 강조하지 못했습니다.

몇 년 동안 나는 항상 누군가가 사소한 문제에 대해 혼란스러워한다는 것을 알았습니다.

레이어링. 소프트웨어 애플리케이션 (적어도 있어야 함)은 하나 이상의 레이어 더미입니다. 좋은 계층화에 대한 한 가지 중요한 기대는 하위 계층이 상위 계층의 여러 구성 요소에 기능을 제공한다는 것입니다.

앱에 아래의 NET, TCP, HTTP, REST, DATA MODEL, BUSINESS 계층이 있다고 가정 해 보겠습니다.

비즈니스 계층에서 휴면 통화를 실행하려면 잠시 기다려주십시오. 내가 왜 그렇게 말했어? HTTP 요청이나 TCP 트랜잭션을 말하거나 네트워크 패키지를 보내지 않은 이유는 무엇입니까? 이는 비즈니스 계층과 관련이 없기 때문입니다. 나는 그것들을 다루지 않을 것이고, 나는 그들의 세부 사항을 보지 않을 것입니다. 그들이 원인으로 얻는 예외에 깊이 빠져 있고 완벽하게 존재하는지 알고 싶지 않습니다.

또한 내일이면 TCP 프로토콜과 관련된 세부 정보를 처리하는 기본 전송 프로토콜을 변경하고 싶습니다. 내 REST 추상화가 자체 추상화에 좋은 역할을하지 못했음을 의미하기 때문에 세부 사항을 알고 있으면 더 나쁩니다. 특정 구현.

예외를 계층에서 계층으로 전환 할 때 모든 계층과 현재 계층이 제공하는 추상화에 어떤 의미가 있는지 다시 방문하는 것이 중요합니다. 예외를 다른 것으로 바꾸거나 여러 예외를 결합 할 수 있습니다. 또한 그것들을 체크에서 체크로 또는 그 반대로 전환 할 수도 있습니다.

물론, 당신이 말한 실제 장소는 다른 이야기이지만, 일반적으로-그렇습니다. 좋은 일이 될 수 있습니다.


-2

제 생각에는

프레임 워크 레벨에서, 동일한 위치에서 호출자에 대한 더 많은 시도 catch 블록을 줄이려면 런타임 예외를 포착해야합니다.

응용 프로그램 수준에서는 런타임 예외를 거의 캡처하지 않으므로이 방법이 잘못되었다고 생각합니다.


1
그리고 프레임 워크 수준에서 이러한 예외로 무엇을 할 것입니까?
Matthieu

프레임 워크에 예외를 처리 할 수있는 UI 계층이있는 경우 UI는 무언가 잘못되었다는 오류 메시지를 표시합니다. 한 페이지 자바 스크립트 앱의 경우 앱에서 오류 메시지가 표시 될 수 있습니다. 물론 더 깊은 계층이 실제로 오류를 복구 할 수없는 경우에만 UI 계층이 오류를 처리해야합니다.
Jake Toronto
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.