2008-08-22 2 views
40

레거시 코드를 FXCop로 분석하는 동안 try 블록 내에서 일반적인 예외 오류를 발견하는 것이 그리 나쁘거나 특정 예외를 찾아야하는 경우가 있습니다. 엽서에 대한 생각은 제발.일반적인 예외를 잡는 것이 그렇게 나쁘지 않습니까?

+1

입력을 예측할 수없고 실패가 옵션이 아닌 경우 - 유일한 방법입니다. 물론 다음에 오류를 올바르게 처리 할 수 ​​있도록 오류를 기록하지 않는 것이 좋습니다. – mehtunguh

+1

[programmers.stackexchange] (http://programmers.stackexchange.com/)에 더 적합한 질문입니까? – HardcoreBro

+0

나는 이것이 "[** Pokémon 잡기 ** - 모두 잡아야 함] (http://salesforce.stackexchange.com/q/136920/587)"이라고도합니다. –

답변

73

이 질문 중 하나는 분명히 유일한 대답은 "달라집니다"입니다.

중요한 것은 그것이 당신이 예외를 잡는 곳입니다. 일반적으로 라이브러리는 프로그램의 최상위 레벨 (예 : 메인 메소드 또는 컨트롤러의 액션 메소드 상단 등)에서 예외를 포착하는 것이 더 보수적이어야하며, 잡는 것에 더 자유주의가 될 수 있습니다. 그 이유는, 예를 들면, 라이브러리에서 모든 예외를 포착하고 싶지는 않습니다. 라이브러리와 관련이없는 문제, 예를 들어 "OutOfMemoryException"과 같은 문제를 숨길 수 있기 때문에 마스크를 사용하여 사용자에게 알릴 수 있습니다. 예외를 잡는 main() 메서드 내에서 예외를 잡아 내고 표시 한 다음 종료 할 때 예외를 잡는 것에 대해 이야기하고 있다면 여기에 예외를 잡는 것이 안전 할 것입니다.

모든 예외를 포착하는 가장 중요한 규칙은 모든 예외를 자동으로 삼가야한다는 것입니다. 자바에서이 같은 :

try { 
    something(); 
} catch (Exception ex) {} 

또는이 파이썬 :

try: 
    something() 
except: 
    pass 

이러한 추적하기 어려운 몇 가지 문제가 될 수 있기 때문이다.

좋은 규칙은 자신이 올바르게 처리 할 수있는 예외 만 잡아야한다는 것입니다. 예외를 완벽하게 처리 할 수 ​​없다면 할 수있는 사람에게 거품을 내 보내야합니다.

+7

언어 테두리에서 모든 예외를 잡아서 번역하는 것도 좋은 방법입니다. –

3

글쎄, 일반적인 예외 또는 특정 예외를 잡는 것 사이의 차이점을 보지 못했습니다. 예외가 여러 개일 경우 예외에 따라 다르게 대응할 수 있습니다.

일반 예외로 IOException과 NullPointerException을 모두 잡아낼 수 있지만 프로그램 반응 방식이 다를 수 있습니다.

0

프레임 워크 내에서 특정 예외 만 잡는 것이 좋습니다 (호스트 응용 프로그램이 디스크 채움과 같은 가장자리 케이스를 처리 할 수 ​​있도록).하지만 왜 그렇게해서는 안되는 지 알지 못합니다. 우리의 응용 프로그램 코드에서 모든 예외를 포착 할 수 있습니다. 간단히 말해서 무엇이 잘못 될지라도 앱이 충돌하는 것을 원하지 않는 때가 있습니다.

1

대부분의 경우 일반적인 예외를 포착 할 필요가 없습니다. 물론 선택의 여지가없는 상황이 있지만이 경우에는 왜 잡을 필요가 있는지 확인하는 것이 좋습니다. 어쩌면 디자인에 뭔가 잘못되었을 수도 있습니다.

19

응용 프로그램의 프런트 엔드에서 일부 로깅 및 정리 코드를 수행하지 않는 한 모든 예외를 catch하는 것이 좋지 않다고 생각합니다.

내 기본 규칙은 예상 한 모든 예외를 잡는 것이며 다른 것은 버그입니다.

당신이 모든 것을 붙잡고 계속한다면, 그것은 자동차 대시 보드의 경고등 위에 튀어 나와있는 석고를 두는 것과 같습니다. 더 이상 볼 수는 없지만 모든 것이 괜찮다는 의미는 아닙니다.

3

요점은 두 가지입니다.

첫 번째로 어떤 예외가 발생했는지 모르는 경우 어떻게 복구 할 수 있습니까? 사용자가 파일 이름을 잘못 입력 할 것으로 예상되면 FileNotFoundException을 예상하고 사용자에게 다시 시도하도록 알릴 수 있습니다. 동일한 코드가 NullReferenceException을 생성하고 사용자에게 다시 시도하도록 지시했다면 어떤 일이 발생했는지 알 수 없습니다.

두 번째로 FxCop 지침은 라이브러리/프레임 워크 코드에만 초점을 맞추고 있습니다. 모든 규칙이 EXE 또는 ASP.Net 웹 사이트에 적용되도록 디자인 된 것은 아닙니다. 따라서 모든 예외를 기록하고 애플리케이션을 멋지게 종료하는 전역 예외 처리기를 갖는 것은 좋은 일입니다.

+0

예외에 의해 로직을 코딩하는 것은 좋지 않습니다. 사용자가 제공 한 파일이 존재하지 않는다면 File.exists()를 확인하는 메소드가 있습니다. –

+0

@KrzysztofCichocki - 저는 이것이 오래되었음을 알고 있습니다 만, 실제로 이런 식으로 예외를 사용하는 파일 논리를 코딩하는 것이 더 정확합니다. Eric Lippert [여기] (https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/)에 대한 좋은 설명이 있습니다. 그는이 유형을 "외인성"예외라고합니다. – Olly

14

예! (응용 프로그램의 "상단"제외)

예외를 포착하고 코드 실행을 계속 진행하면 특정 문제를 해결하고 우회하거나 해결할 수 있음을 알 수 있습니다. 복구 가능 상황 인 복구 가능 상황입니다. Catching Exception 또는 SystemException은 IO 오류, 네트워크 오류, 메모리 부족 오류, 누락 된 코드 오류, Null 포인터 역 참조 등의 문제를 catch한다는 것을 의미합니다. 당신이 이것들을 다룰 수 있다고 말하는 것은 거짓말입니다.

잘 조직 된 응용 프로그램에서 이러한 복구 할 수없는 문제는 스택 위로 처리해야합니다.

또한 코드가 발전함에 따라 나중에 호출 된 메서드에에 추가 된 이라는 새 예외를 catch하지 않아도됩니다.

+0

캐치를 사용하여 추가 정보를 추가 한 다음 다시 올릴 수 있습니까? –

8

제 생각에는 일 것으로 예상되는 모든 예외를 포착해야하지만이 규칙은 인터페이스 논리 이외에는 적용되지 않습니다. 호출 스택을 따라 가면서 모든 예외를 잡아 내고, 몇 가지 로깅을 수행하고, 사용자 의견을 제공하고, 필요하고 가능한 경우 정상적으로 종료하는 방법을 만들어야합니다.

불친절한 스택 트레이스가 화면에 덤핑되어 응용 프로그램이 충돌하는 것보다 더 나쁜 것은 없습니다. 코드에 대한 (아마도 원하지 않는) 통찰력을 제공 할뿐만 아니라 최종 사용자를 혼란스럽게하고 때로는 경쟁 응용 프로그램을 위협하기도합니다.

3

모든 예외를 포착 할 때의 문제는 기대하지 않는 것 또는 실제로 이 아니라이 잡아야하는 것을 잡을 수 있다는 것입니다. 사실 어떤 종류의 예외는 무언가가 잘못되었다는 것을 나타내며, 계속하기 전에 정리해야만 그렇지 않으면 데이터 무결성 문제 및 추적하기 쉽지 않은 다른 버그가 발생할 수 있습니다.

한 예로, 한 프로젝트에서 CriticalException이라는 예외 유형을 구현했습니다. 이것은 개발자 및/또는 관리 직원이 개입해야하는 오류 상태를 나타냅니다. 그렇지 않으면 고객의 청구가 잘못되거나 다른 데이터 무결성 문제가 발생할 수 있습니다. 또한 예외를 기록하는 것만으로는 충분하지 않고 전자 메일 알림을 보내야하는 다른 유사한 경우에도 사용할 수 있습니다.

예외 개념을 제대로 이해하지 못한 다른 개발자가 모든 예외를 무시한 일반 try ... catch 블록에이 예외를 던질 수있는 코드를 래핑했습니다. 다행히도, 나는 그것을 발견했다. 그러나 그것이 잡히기로되어 있었던 "매우 드문"모퉁이 사건이 내가 예상했던 것보다 훨씬 더 흔한 것으로 밝혀 졌기 때문에 특히 심각한 문제를 초래할 수 있었다.

일반적으로 정확히을 알고 100 % 확신하지 않는 한 일반적인 예외를 포착하는 것은 좋지 않습니다. 어떤 종류의 예외가 발생하고 상황에 따라 다릅니다. 의심 스럽다면 최상위 레벨 예외 처리기로 버블 링하도록하십시오.

비슷한 규칙은 System.Exception 유형의 예외를 절대로 throw하지 않습니다. 개발자 (또는 다른 개발자)는 다른 사용자가 통과 할 수있게하면서 호출 스택을 높이는 특정 예외를 잡을 수 있습니다.

(.NET 2.0에서는 스레드가 잡히지 않는 예외를 발견하면 전체 앱 도메인을 언로드하므로 일반 스레드에서 스레드의 본문을 래핑해야합니다. catch 블록을 생성하고 예외를 전역 예외 처리 코드에 전달하십시오.)

+0

'CriticalException'을 호출 한 코드가'Thread.Abort (Thread.CurrentThread)'로 불리우면 어떻게 될까요? 중단 된 스레드는 알려진 상태 ('중단 '호출)에 있기 때문에 해당 방법의 정상적인 위험은 적용되지 않습니다. 'catch (Exception ex)'를 수행하는 코드는 결과적으로 발생하는 thread-abort 예외를 포착 할 수 있지만 호출 체인을 전파하지는 않습니다. 물론 더 의미있는 이름의 예외가 비슷한 방식으로 작동 할 수있는 방법이 있다면 더 좋을 것입니다.하지만 .NET에서 그러한 기능이 없다는 것을 알고 있습니다. – supercat

4

이 문제와 관련하여 많은 논란이있었습니다. 개인적으로, 나는 당신이 할 수있는 최악은 예외를 삼키는 것이라고 믿습니다. 다음 최악의 경우는 사용자가 기술적인 불만스런 점보로 가득 찬 화면을 얻을 때까지 예외를 허용합니다.

+7

예외적 인 거품을 띄우는 것이 최종 사용자에게 표시하는 것을 의미하지는 않습니다. 일반 오류 페이지를 표시하고 조사를 위해 기록한 다음 예외를 일으킨 문제를 처음부터 해결할 수 있습니다. – jammycakes

+2

질문에 응답하지 않습니다. –

-2

일반적인 예외를 제외하면, 나는 불타는 건물 안에 다이너마이트의 막대기를 들고 퓨즈를내는 것과 같은 느낌이 듭니다. 그것은 잠시 동안 도움이된다. 그러나 다이너마이트는 잠시 후에 불어 날 것이다.

일반적인 경우 예외를 잡는 것이 필요하지만 디버그 용도로만 사용할 수 있습니다. 오류와 버그는 수정해서는 안되며 숨겨서는 안됩니다.

+0

오류를 수정하는 것을 좋아하지 않는 사람이 적어도 두 명은 있다는 것을 알았습니다 ... – Tzen

1

나는 예외 잡기와 그것을 기록하고 그것을 다시 던지기 위해 악마의 옹호자와 놀고 싶습니다. 예를 들어, 코드 어딘가에 있으며 예기치 않은 예외가 발생하면이를 catch하고 간단한 스택 추적에서 사용할 수없는 의미있는 상태 정보를 기록한 다음 상위 계층에 다시 전달하면됩니다. 다루다.

0

두 가지 완전히 다른 사용 사례가 있습니다. 첫 번째는 대부분의 사람들이 생각하고있는 것으로, 체크 된 예외를 필요로하는 일부 연산을 try/catch합니다. 이는 어떤 의미로도 포기해서는 안됩니다.

그러나 둘째, 계속할 수있을 때 프로그램이 중단되지 않도록하는 것입니다. 이러한 경우는 다음과 같습니다

  • 는 모든 스레드의 상단 (기본적으로는, 예외가 흔적도없이 사라질 것입니다!) 당신이 목록을 처리하는 루프 내부
  • 를 종료하지 않을 것으로 예상 메인 처리 루프 내부
  • 하나의 오류로 인해 다른 사용자가 멈추지 않아야하는 객체가 있습니다.
  • "메인"스레드 맨 - 메모리가 부족할 때 약간의 데이터를 덤프하는 것처럼 여기에서 충돌을 제어 할 수 있습니다.
  • "Runner"가 코드를 실행하는 경우 (예 : 누군가가 청취자를 추가하고 청취자를 호출하는 경우) 코드를 실행할 때 예외를 기록하여 문제를 기록하고 다른 사람에게 계속 통보하도록해야합니다 청취자.

이 경우 프로그래밍/예기치 않은 오류를 잡아 로그하고 계속하려면이 경우 항상 예외 (예 : Throwable일지도 모름)를 잡아 내고 싶어합니다.

관련 문제