2009-11-20 12 views
2

이것은 리팩터링 질문입니다.예외 예외 사용

try 
{ 
    string line = GetFirstLineFromFile(); //Gets first line from a text file, this line would be a number. 
    int value = ConvertToInteger(line); // Gets the integer value from the string. 
    int result = DivideByValue(value); // Divides some number with the value retrieved. 
} 
catch(Exception ex) 
{ 
} 

내 관심사는 이러한 상황에서 예외 처리를위한 최선의 방법입니다. 확실히 모든 것을 단일 try catch로 래핑하는 것은 모든 것에 대한 예외를 기대한다고 말하는 것과 같습니다. 우리가 일반적인 예외적 권리를 잡을 곳이 있어야합니까?

답변

0

하나의 큰 일반 블록에서 여러 예외를 절대로 잡아서는 안된다고 말하는 사람들의 말을 경청하지 마십시오. 어떤 경우에는 일반적인 오류 처리를 수행하는 것이 가장 합리적인 방법이며, 그렇게 할 수있는 능력이 언어에 존재합니다.

몇 가지 예외가있을 수 있습니다 (예 : catch 블록에서 복구). 이러한 예외는 개별적으로 catch하려는 예외의 종류와 가능한 한 일어난다.

그러나 실제 상황에서 직면하게 될 예외의 대부분은 예기치 않은 예외입니다. 이들은 프로그래머 오류 (버그), 실패한 어설 션, 하드웨어 오류, 네트워크 연결 끊김 등의 결과입니다.

최소한의 중단으로 이러한 예측할 수없는 예외를 처리하는 특정 "초 점"을 지정하여 소프트웨어를 방어 적으로 디자인해야합니다 응용 프로그램의 나머지 부분. 대부분의 경우 예외를 "처리하는"것은 현재 작업을 중단하고 오류를 로깅하거나 예기치 않은 오류가 발생했음을 사용자에게 알리는 것을 의미하는 경우가 많습니다.프로그램이 디스크에 파일을 저장하는 경우)

그래서 예를 들어, 당신은 저장 중에 잘못되면 그 일을 잡으려고 시도 블록에 작업을 전체 저장 포장 수 :

try { 
    // attempt to perform the save operation 
    doSave(); 

} catch (Throwable t) { 
    // tell the user that the save failed for unexpected reasons 
    // and log the error somewhere 
    informUser("save failed!"); 
    log("save failed!", t); 

} finally { 
    // last minute cleanup (happens whether save succeeded or failed) 
    ... 
} 

공지 사항이 우리 여기서 멋진 초크 포인트 메소드를 선택하고 (doSave())이 시점 이상으로 예상치 못한 오류가 발생하지 않도록하십시오. 초크 포인트는 취소 가능한 단일 작업 (저장)을 나타냅니다. 예상치 못한 예외가 발생하는 경우 해당 작업은 분명히 토스트이지만, 나머지 애플리케이션은 초크 포인트의 다른 쪽에서 어떤 일이 발생하든 관계없이 양호한 상태로 유지됩니다.

또한이 관용구가 doSave() 어딘가에서 예외의 일부를 처리하지 못하게한다는 것을 알 수 있습니다. 그래서 던져 질 수있는 예외가 있거나 복구 할 수있는 특별한 방법이 있다면 doSave()에서 그렇게하십시오. 하지만 그 밖의 모든 것에는 당신의 초크 포인트가 있습니다.

당신도 당신의 주요 방법으로 전체 프로그램에 대한 일반적인 캐치되지 않는 예외 핸들러를 설정할 수 있습니다 : 당신이 현명하게 다른 초크 포인트를 설정 한 경우,

public static void main(String [] args) { 
    try { 
     startApplication(); 
    } catch (Throwable t) { 
     informUser("unexpected error! quitting application"); 
     log("fatal application error", t); 
    } 

그러나 예외없는 것까지 어느 거품 여기까지. 일반적인 에러 처리를하고 싶다면, 스윙을 사용하고 있다면 주 스레드 나 AWT 스레드를 포함하여 중요한 스레드에 UncaughtExceptionHandler을 생성하고 할당 할 수 있습니다.


TL; 교리가 가능한 한 구체적으로 예외를 잡아야한다고 생각하지 마십시오. 특정 예외를 잡아서 처리하고 싶을 때나, "잘못 될 수있는 모든 것"을 잡아 내고 처리하기 위해 초크 포인트를 사용하려는 경우가 있습니다.

+0

정확하게. 특정 예외를 포착하는 것은 개발자가 이러한 특정 예외가 발생할 수 있다고 생각한다고 말합니다. 프런트 엔드 응용 프로그램에서 예상치 못한 문제가 발생할 경우를 대비해 사용자에게 친숙한 오류 메시지가 필요한 경우에도 일반 예외로 인해 하루가 절약됩니다. – theraneman

2

"일반 예외"를 잡지 마십시오.

어떻게 예외를 처리하고 응용 프로그램을 정상 상태로 유지하는 방법을 알고 있습니까? 그것은 버그를 숨기고 정말 나쁜 생각입니다.

catch (Exception)에 대한 게시물을 읽어보십시오.

+0

나는 그러한 코드를 작성하지 않을 것임을 알고 있습니다. 하지만 모든 래핑 try catch 블록을 제거한다고 말하면, 각 함수는 예외 처리를 수행합니다. 예상되는 모든 예외를 처리하고 catch 블록을 작성하는 것이 가능합니까? – theraneman

+2

호출하는 메서드에는 정의 된 예외 집합이 있어야합니다. 그런 다음 정의 된 예외 만 catch하십시오 ... – Guillaume

1

try 블록의 메서드뿐만 아니라 현재 추상화 수준에서 처리 할 수있는 예외가 무엇인지 생각해 볼 필요가 있습니다.

귀하의 경우 예를 들어 getFirstLineFromFile 메쏘드가 분명히 여기에 잡으려는 예외를 던질 수 있습니다. 이제 당신이 예외를 감싸고 다시 던지 든, 다른 행동을 취하든간에,이 수준에서 실제로 예외를 처리 할 수 ​​있는지 여부에 달려 있습니다. 대체 할 수있는 기본 파일이있는 경우를 생각해보십시오. 접근법은 경고를 기록하고 기본값을 계속 사용하는 것일 수 있습니다. 또는 전체 응용 프로그램이 사용자가 제공 한 파일을 읽는 것을 기본으로하는 경우에는 최상위 수준까지 전파되어 사용자에게 전달되어야하는 치명적인 예외 일 가능성이 큽니다.

"항상 던지기"또는 "전혀 던지지 않기"와 같은 단호하고 빠른 규칙은 없습니다. 일반적으로이 메소드의 정상적인 결과로 간주되지 않는 예외적 인 상황이있을 때마다 예외를 던져야하므로 메소드의 반환 유형에 의해 적절하게 설명 될 수 없다고 생각합니다. 예를 들어, 부울을 반환하는 isValidDbUser 메서드는 SQLException을 단지 return false으로 처리 할 수 ​​있지만 getNumProductsRegisteredInDB은 int를 반환해야 예외를 거의 전파해야합니다.

+0

C#을 통해 CLR을 읽은 경우 예외 처리는 확실히 사람들이 사용하는 것처럼 곧장 앞으로 진행되지 않습니다. 일반 예외를 언제 알 수 있습니까? 지금까지 내가 해왔 던 것은 특정 예외에 대한 catch 문을 추가 한 다음 일반 예외 catch 블록을 사용하는 것입니다. – theraneman

+0

왜 일반 예외를 잡을까요? 너는 그걸로 무엇을 할 수 있니? 내 마음 속에서 합법적으로 할 수있는 유일한 시간은 사용자를위한 적절한 응답으로 변환하기 위해 프로그램/webapp (또는 필수적이지 않을 수도있는 작업)의 최상위 레벨에 있습니다. webapp의 경우 적어도 전체 앱이 내려 오길 원하지는 않습니다. 그렇지 않으면 정리 코드를 실행하려면 'finally'블록을 사용하십시오. –