예외 처리에 try catch를 사용하는 것이 가장 좋은 방법


201

선임 개발자라고 주장하는 누군가의 동료의 코드를 유지하면서 종종 다음 코드가 표시됩니다.

try
{
  //do something
}
catch
{
  //Do nothing
}

또는 때때로 다음 try catch블록 과 같은 로그 파일에 로깅 정보를 작성합니다.

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);
}

그들이 한 일이 최선의 방법인지 궁금합니다. 내 생각에 사용자가 시스템에서 일어나는 일을 알아야하기 때문에 혼란 스럽습니다.

조언 좀주세요


128
스 니펫 # 1은 허용되지 않는 시간의 99.999 %입니다.
leppie

22
다음 두 가지 이유로 인해 사용자에게 직접 예외를 표시하는 것은 결코 좋은 생각이 아닙니다. 1. 평범한 사용자 인 경우 오류 메시지를 읽는 데 짜증이납니다. 2. 소위 해커라면 유용한 정보를 얻을 수 있습니다. 모범 사례 인 IMO는 예외를 기록하고 친숙한 오류 메시지를 표시하는 것입니다.
Leri

4
@leppie 예상치 못한 일이 발생 NullReference하거나 (예 : ArgumentNull애플리케이션 흐름의 일부가 아닌) 수정해야 할 버그가 있으므로 로깅하면 코드를 훨씬 빠르게 디버깅하는 데 도움이됩니다.
Leri

14
try-catch 블록을 사용하여 예외를 숨기는 것은 일반적으로 게으른 프로그래밍의 결과입니다. 입력을 테스트하기 위해 유효성 검사 코드를 작성하는 대신 자주 사용되는 바로 가기입니다. 코드 작동에 영향을 미치지 않는 예외가 발생할 수있는 경우가 종종 있으며, 이렇게 숨기는 것이 좋습니다. 그러나 이것은 매우 드 rare니다.
Corey 2019

12
@ Toan, 배치 작업 인 경우 최상위 레벨 (Main)에서 로그를 잡은 다음 작업이 비정상적으로 종료되었다는 경보를 설정하기 위해 다시 던집니다. 웹 응용 프로그램 인 경우 예외 버블을 전역 처리기로 보내고 로깅 한 다음 사용자를 오류 화면으로 리디렉션합니다. 유스 케이스 시나리오는 예외를 기록하거나 처리 한 후 해당 예외로 수행 할 작업을 지시합니다.
Anthony Pegram 6

답변:


300

내 예외 처리 전략은 다음과 같습니다.

  • 에 연결하여 처리되지 않은 모든 예외 를 포착하려면 Application.ThreadException event다음을 결정하십시오.

    • UI 응용 프로그램의 경우 : 사과 메시지 (winforms)로 사용자에게 팝업
    • 서비스 또는 콘솔 응용 프로그램의 경우 파일 (서비스 또는 콘솔)에 기록

그런 다음 항상 외부 에서 실행되는 모든 코드를 묶 습니다 try/catch.

  • Winforms 인프라에 의해 발생 된 모든 이벤트 (로드, 클릭, 선택 변경 ...)
  • 타사 구성 요소에서 발생한 모든 이벤트

그런 다음 'try / catch'로 묶습니다.

  • 모든 내가 그 작업을 항상 작동하지 않을 수 있습니다 알고 (IO 작업을 잠재적 인 제로 부문 ...로 계산). 그런 경우에, 나는 ApplicationException("custom message", innerException)실제로 일어난 일을 추적하기 위해 새로운 것을 던졌습니다.

또한 예외를 올바르게 정렬 하기 위해 최선을 다합니다 . 다음과 같은 예외가 있습니다.

  • 사용자에게 즉시 보여줘야합니다
  • 계단식 문제를 피하기 위해 일을 모으기 위해 추가 처리가 필요합니다 (예 : 채우기 finally중 섹션 에 .EndUpdate TreeView넣기)
  • 사용자는 신경 쓰지 않지만 무슨 일이 있었는지 아는 것이 중요합니다. 그래서 나는 항상 그것들을 기록합니다.

    • 이벤트 로그에서
    • 또는 디스크의 .log 파일에

응용 프로그램 최상위 오류 처리기에서 예외를 처리하기 위해 일부 정적 메서드디자인 하는 것이 좋습니다 .

나는 또한 다음과 같은 노력을 강요한다.

  • 기억 ALL 예외는 최상위까지 버블된다 . 예외 핸들러를 어디에나 둘 필요는 없습니다.
  • 재사용 가능하거나 깊은 호출 함수는 예외를 표시하거나 기록 할 필요가 없습니다. 자동으로 버블 링되거나 예외 처리기의 일부 사용자 지정 메시지와 함께 다시 발생합니다.

마지막으로 :

나쁜:

// DON'T DO THIS, ITS BAD
try
{
    ...
}
catch 
{
   // only air...
}

쓸모없는:

// DONT'T DO THIS, ITS USELESS
try
{
    ...
}
catch(Exception ex)
{
    throw ex;
}

캐치없이 마침내 시도하는 것은 완벽하게 유효합니다.

try
{
    listView1.BeginUpdate();

    // If an exception occurs in the following code, then the finally will be executed
    // and the exception will be thrown
    ...
}
finally
{
    // I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURED OR NOT
    listView1.EndUpdate();
}

내가 최상위에서하는 일 :

// i.e When the user clicks on a button
try
{
    ...
}
catch(Exception ex)
{
    ex.Log(); // Log exception

    -- OR --

    ex.Log().Display(); // Log exception, then show it to the user with apologies...
}

일부 호출 된 함수에서 수행하는 작업 :

// Calculation module
try
{
    ...
}
catch(Exception ex)
{
    // Add useful information to the exception
    throw new ApplicationException("Something wrong happened in the calculation module :", ex);
}

// IO module
try
{
    ...
}
catch(Exception ex)
{
    throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}

예외 처리 (사용자 지정 예외)와 많은 관련이 있지만, 명심하려고하는 규칙은 간단한 응용 프로그램에 충분합니다.

다음은 포착 된 예외를 편안한 방식으로 처리하는 확장 메소드의 예입니다. 그것들은 서로 연결될 수있는 방식으로 구현되며, 사용자 자신의 예외 처리를 추가하는 것은 매우 쉽습니다.

// Usage:

try
{
    // boom
}
catch(Exception ex)
{
    // Only log exception
    ex.Log();

    -- OR --

    // Only display exception
    ex.Display();

    -- OR --

    // Log, then display exception
    ex.Log().Display();

    -- OR --

    // Add some user-friendly message to an exception
    new ApplicationException("Unable to calculate !", ex).Log().Display();
}

// Extension methods

internal static Exception Log(this Exception ex)
{
    File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
    return ex;
}

internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
    MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
    return ex;
}

98
catch(Exception ex) { throw ex; }C # 의 경우 예외 유형에 관계없이 중복보다 나쁩니다 . 다시 던지려면을 사용하십시오 throw;. 전자의 경우 예외는 귀하의 것에서 유래 한 것처럼 보이지만 throw ex후자 는 예외로 원래의 throw진술 에서 유래 합니다.
CVn

2
왜 후크 않는 Application.ThreadException이벤트를 하고 로모그래퍼 모든 예외를 랩 catch(Exception ex) {ex.Log(ex);}. 전자가 훌륭한 연습이라는 데 동의하지만 후자는 오류 로그를 복제 할 위험이 있으며 예외가 발생했음을 숨 깁니다. 또한 throw ex매우 나쁘다.
키이스

1
catch (Exception ex)에 대해 이해했습니다. {throw ex; } 쓸모없는. 따라서 "중복"은 "이 작업을 수행하지 마십시오"라고 말하는 것이 가장 좋은 단어라고 생각합니다. 그렇기 때문에 try catch의 첫 두 가지 예를 피해야한다는 점을 더 잘 설명하기 위해 게시물을 약간 변경했습니다.
래리

3
위대하고 건설적인 대답, 무엇보다도 나는 공기만 이라는 문구를 즐겼습니다 .) Application.ThreadException이벤트 덕분에 나는 그 점을 잘 알지 못했습니다.
Mahdi Tahsildari


61

모범 사례는 예외 처리 가 문제를 숨기지 않아야한다는 것 입니다. 이것은 try-catch블록이 매우 드 물어야 함을 의미합니다 .

try-catch의미를 사용하는 것이 3 가지 상황이 있습니다 .

  1. 알려진 예외는 항상 가능한 한 낮게 처리하십시오 . 그러나 예외가 예상되는 경우 일반적으로 먼저 예외를 테스트하는 것이 좋습니다. 예를 들어 구문 분석, 형식 지정 및 산술 예외는 거의 항상 논리 검사보다 먼저 처리하는 것이 좋습니다 try-catch.

  2. 예외에 대한 작업 (예 : 트랜잭션 로깅 또는 롤백)이 필요한 경우 예외를 다시 발생시킵니다.

  3. 알 수없는 예외는 항상 가능한 한 높게 처리하십시오. 예외를 소비하고 다시 발생시키지 않아야하는 유일한 코드는 UI 또는 공용 API 여야합니다.

원격 API에 연결한다고 가정 해 봅시다. 여기서 특정 오류가 발생하고 그러한 상황에서 문제가 있음을 알고 있으므로이 경우 1입니다.

try 
{
    remoteApi.Connect()
}
catch(ApiConnectionSecurityException ex) 
{
    // User's security details have expired
    return false;
}

return true;

예상하지 못한 다른 예외는 발견되지 않습니다.

이제 데이터베이스에 무언가를 저장하려고한다고 가정하십시오. 실패하면 롤백해야하므로 사례 2가 있습니다.

try
{
    DBConnection.Save();
}
catch
{
    // Roll back the DB changes so they aren't corrupted on ANY exception
    DBConnection.Rollback();

    // Re-throw the exception, it's critical that the user knows that it failed to save
    throw;
}

우리는 예외를 다시 던진다는 것을 명심하십시오. 높은 코드는 여전히 무언가 실패했음을 알아야합니다.

마지막으로 우리는 UI를 가지고 있습니다-여기서 우리는 처리되지 않은 예외를 완전히 원하지 않지만, 그것들을 숨기고 싶지는 않습니다. 다음은 사례 3의 예입니다.

try
{
    // Do something
}
catch(Exception ex) 
{
    // Log exception for developers
    WriteException2LogFile(ex);

    // Display message to users
    DisplayWarningBox("An error has occurred, please contact support!");
}

그러나 대부분의 API 또는 UI 프레임 워크에는 사례 3을 수행하는 일반적인 방법이 있습니다. 예를 들어 ASP.Net에는 예외 세부 정보를 덤프하는 노란색 오류 화면이 있지만 프로덕션 환경에서는보다 일반적인 메시지로 대체 될 수 있습니다. 이를 수행하는 것은 많은 코드를 절약 할뿐만 아니라 오류 로깅 및 표시가 하드 코딩이 아닌 구성 결정이어야하므로 모범 사례입니다.

이것은 모두 사례 1 (알려진 예외)과 사례 3 (일회성 UI 처리)이 더 나은 패턴을 가짐을 의미합니다 (예상 된 오류 또는 손 오류 처리를 UI로 전달하지 않음).

예를 들어 트랜잭션 범위 ( using블록 동안 커밋되지 않은 트랜잭션을 롤백하는 블록)와 같이 사례 2도 더 나은 패턴으로 대체 될 수 있으므로 개발자가 모범 사례 패턴을 잘못 이해하기가 더 어려워집니다.

예를 들어 대규모 ASP.Net 응용 프로그램이 있다고 가정합니다. 오류 로깅은 ELMAH 를 통해 가능하며 , 오류 표시는 유익한 로컬 YSoD 및 프로덕션에서 현지화 된 메시지 일 수 있습니다. 데이터베이스 연결은 모두 트랜잭션 범위 및 using블록을 통해 이루어질 수 있습니다 . 단일 try-catch블록이 필요하지 않습니다 .

TL; DR : 모범 사례는 실제로 try-catch블록 을 전혀 사용하지 않는 것 입니다.


4
@Jorj 당신은 전체 게시물을 읽어야하며, 만약 당신이 여전히 동의하지 않는다면 아마도 당신이 내 결론을 좋아하지 않는다고 말하는 것보다 내 주장에 반대하는 것이 더 건설적 일 것입니다. 거의 항상 더 나은 패턴이 try-catch있습니다. (매우 가끔) 유용 할 수 있으며, 절대로 사용해서는 안된다고 주장하는 것이 아니라 99 %의 시간이 더 좋은 방법입니다.
키이스

거의 모든 .net 개발 유형의 베스트 답변은 글로벌 수준에서 예외를 처리하는 데 훨씬 더 적합한 HANDLER를 보유하고 있기 때문에 일관성있게 처리하는 것이 훨씬 쉬워지고 간단하게 처리 할 수 ​​있습니다. 개발 (업데이트 누군가가 스택 추적을 위해 로그 파일을 통해 파고 싶어하는 이유 ??) @Kieth, 나는 TLDR을 이끌고 전역 처리기의 예를 추가합니다 (예 : ThreadException, Application_Error 등). 꼭 특정 오류를 잡을 수 있지만, 시도 / 잡기 / 로그 적 방법을 래핑하는 미친
b_levitt

34

예외는 차단 오류 입니다.

우선, 모범 사례는 블로킹 오류가 아닌 한 모든 종류의 오류에 대해 예외를 throw하지 않아야합니다 .

오류가 차단 되면 예외를 처리하십시오. 예외가 이미 발생하면 예외이기 때문에 숨길 필요가 없습니다. 사용자에게 알리십시오 (모든 예외를 UI에서 사용자에게 유용한 것으로 다시 포맷해야합니다).

소프트웨어 개발자로 당신의 임무는 방지하기 위해 노력하는 예외적 인 경우 일부 매개 변수 또는 런타임 상황은 예외가 종료 될 수 있습니다. 즉, 예외를 음소거해서는 안되지만 피해야 합니다.

예를 들어 일부 정수 입력에 잘못된 형식이있을 수있는 경우 int.TryParse대신을 사용하십시오 int.Parse. "실패하면 단순히 예외를 던지십시오"라고 말하는 대신이 작업을 수행 할 수있는 경우가 많이 있습니다.

예외를 던지는 것은 비싸다.

결국 예외가 발생하면 로그에 예외를 작성하는 대신 예외가 발생하면 모범 사례 중 하나는 첫 번째 예외 처리기에서 예외를 포착하는 것입니다 . 예를 들면 다음과 같습니다.

  • ASP.NET : Global.asax Application_Error
  • 기타 : AppDomain.FirstChanceException 이벤트 .

내 입장은 로컬 try / catch가 예외를 다른 것으로 번역 할 수있는 특별한 경우를 처리하거나 매우, 매우, 매우, 매우 특별한 경우 (라이브러리 버그) 전체 버그를 해결하기 위해 음소거 해야하는 관련이없는 예외를 던짐).

나머지 경우 :

  • 예외를 피하십시오.
  • 이것이 가능하지 않은 경우 : 첫 번째 예외 처리기.
  • 또는 AOP (PostSharp aspect)를 사용하십시오.

일부 의견에 @thewhiteambit에 대답하는 중 ...

@thewhiteambit는 말했다 :

예외는 치명적인 오류가 아니라 예외입니다! 때로는 오류조차되지 않지만 치명적 오류를 고려하는 것은 예외가 무엇인지 완전히 이해하지 못하는 것입니다.

우선 예외가 어떻게 오류가 될 수 없습니까?

  • 데이터베이스 연결이 없습니다 => 예외.
  • 일부 유형으로 구문 분석 할 수없는 잘못된 문자열 형식 => 예외
  • JSON을 구문 분석하려고 시도하고 입력이 실제로 JSON => 예외가 아닌 동안
  • null객체가 예상되는 동안 인수 => 예외
  • 일부 라이브러리에는 버그가 있습니다 => 예기치 않은 예외가 발생합니다.
  • 소켓 연결이 있고 연결이 끊어집니다. 그런 다음 메시지를 보내려고합니다 => 예외
  • ...

우리는 예외가 발생했을 때 1k 건을 나열 할 수 있으며 결국 가능한 모든 사례가 오류 가 될 것 입니다.

예외 하루가 끝나면 진단 정보를 수집하는 객체이기 때문에 . 메시지가 있고 문제가 발생했을 때 발생합니다.

예외적 인 경우가 없으면 아무도 예외를 던지지 않습니다. 예외 가 발생하면 일단 오류가 발생 하기 때문에 try / catch 사용을 시도 하지 않고 제어 흐름을 구현하기위한 예외가 발생하면 응용 프로그램 / 서비스가 예외적 인 경우에 입력 한 작업을 중지합니다 .

또한 Martin Fowler (Jim Shore)가 출판 한 페일-패스트 패러다임 을 확인하는 것이 좋습니다 . 이것은 얼마 전에이 문서를 읽기 전에도 예외를 처리하는 방법을 항상 이해 한 방법입니다.

[...] 그들을 고려하십시오 치명적 오류는 예외가 무엇인지에 대한 완전히 잘못된 이해입니다.

일반적으로 예외 일부 작업 흐름을 차단 하고 사람이 이해할 수있는 오류로 변환하기 위해 처리됩니다. 따라서 예외는 실제로 응용 프로그램 / 서비스의 완전한 충돌을 피하고 문제가 있음을 사용자 / 소비자에게 알리기 위해 오류 사례를 처리하고 처리하는 더 나은 패러다임 인 것 같습니다.

@thewhiteambit에 대한 추가 답변

예를 들어, 데이터베이스 연결이 누락 된 경우 프로그램은 예외적으로 로컬 파일에 계속 기록하고 데이터베이스를 다시 사용할 수있게되면 변경 사항을 데이터베이스에 보낼 수 있습니다. 기본 영어를 Parse ( "1,5")로 시도 할 때 실패하고 완전히 해석되는 독일어 해석으로 다시 시도하는 것과 같이 예외에 대한 언어 로컬 해석을 사용하여 유효하지 않은 문자열 대 숫자 캐스팅을 다시 구문 분석하려고 시도 할 수 있습니다. 점 대신 구분 기호로 쉼표를 사용하기 때문에 좋습니다. 이러한 예외는 차단되어서는 안되며 예외 처리 만 필요합니다.

  1. 데이터를 데이터베이스에 유지하지 않고 앱이 오프라인에서 작동 할 수있는 경우 예외를 사용해서는 안됩니다.이를 사용 하여 제어 흐름을 구현 try/catch하는 것은 안티 패턴으로 간주됩니다. 오프라인 작업은 가능한 유스 케이스이므로 데이터베이스에 액세스 할 수 있는지 여부를 확인하기 위해 제어 플로우를 구현하고 도달 할 수 없을 때까지 기다리지 않습니다 .

  2. 파싱 것은 또한 예상되는 경우입니다 ( 예외적하지 CASE ). 이것을 예상하면 예외를 사용하여 흐름을 제어하지 마십시오! . 자신의 문화가 무엇인지 알기 위해 사용자로부터 일부 메타 데이터를 얻고이를 위해 포맷터를 사용합니다! .NET은이 환경과 다른 환경도 지원하며 응용 프로그램 / 서비스의 문화권 별 사용을 기대하는 경우 숫자 형식을 피해야하기 때문에 예외가 발생합니다 .

처리되지 않은 예외는 보통 오류가되지만 예외 자체는 codeproject.com/Articles/15921/Not-All-Exceptions-Are-Errors가 아닙니다.

이 기사는 저자의 의견이나 관점 일뿐입니다.

Wikipedia는 또한 articule author (s)의 의견 일 수 있기 때문에 나는 그것이 교리 라고 말하지는 않지만 일부 기사에서 예외 기사에 의한 코딩이 무엇을 말하는지 확인하십시오 .

[...] 프로그램을 계속하기 위해 발생하는 특정 오류를 처리하기 위해 이러한 예외를 사용하는 것을 예외로 코딩이라고합니다. 이 안티 패턴은 성능 및 유지 관리면에서 소프트웨어를 빠르게 저하시킬 수 있습니다.

또한 어딘가에 말합니다 :

잘못된 예외 사용법

예외에 의한 코딩은 종종 잘못된 예외 사용과 함께 소프트웨어의 추가 문제로 이어질 수 있습니다. 고유 한 문제에 대해 예외 처리를 사용하는 것 외에도 예외가 발생한 후에도 잘못된 예외 사용은 코드를 실행하여 더 많은 문제를 해결합니다. 이 불량한 프로그래밍 방법은 많은 소프트웨어 언어의 goto 방법과 유사하지만 소프트웨어의 문제가 감지 된 후에 만 ​​발생합니다.

솔직히, 나는 소프트웨어를 개발할 수 없다고 믿어 유스 케이스를 심각하게 생각하지 않습니다. 알고 있다면 ...

  • 데이터베이스가 오프라인 상태가 될 수 있습니다 ...
  • 일부 파일을 잠글 수 있습니다 ...
  • 일부 형식이 지원되지 않을 수 있습니다 ...
  • 일부 도메인 확인이 실패 할 수 있습니다 ...
  • 앱이 오프라인 모드에서 작동해야합니다.
  • 어떤 유스 케이스라도 ...

... 당신은 그것에 대한 예외를 사용하지 않습니다 . 당신은 것입니다 지원 일반 제어 흐름을 사용하여 이러한 사용 사례를.

예기치 않은 사용 사례가 다루지 않으면 예외가 발생 하기 때문에 코드가 빠르게 실패 합니다. 예외는 예외적 인 경우 이기 때문 입니다.

반면에, 때로는 예상 예외를 던지는 예외적 인 경우 를 다루지 만 제어 흐름을 구현하기 위해 예외를 던지지는 않습니다. 일부 유스 케이스를 지원하지 않거나 코드가 특정 인수 또는 환경 데이터 / 속성에서 작동하지 않는다는 것을 상위 계층에 알리고 싶기 때문입니다.


6

코드에서 발생한 일에 대해 사용자에게 걱정해야 할 유일한 경우는 문제를 피하기 위해 할 수 있거나해야 할 일이 있는지 여부입니다. 양식의 데이터를 변경할 수있는 경우, 문제를 피하기 위해 버튼을 누르거나 응용 프로그램 설정을 변경 한 다음 알려주십시오. 그러나 사용자가 피할 수없는 경고 나 오류는 제품에 대한 신뢰를 잃게합니다.

예외 및 로그는 최종 사용자가 아닌 개발자를위한 것입니다. 각 예외를 잡을 때해야 할 올바른 일을 이해하는 것이 황금률을 적용하거나 응용 프로그램 전체의 안전망에 의존하는 것보다 훨씬 좋습니다.

마인드 코딩은 오로지 잘못된 코딩입니다. 이러한 상황에서 더 나은 것이 있다고 생각하면 좋은 코딩에 투자했지만 이러한 상황에서 일반적인 규칙을 찍지 말고 무엇을 던질 이유와 무엇을 이해 해야하는지 알 수 있습니다. 당신은 그것에서 복구 할 수 있습니다.


6

나는 이것이 오래된 질문이라는 것을 알고 있지만 여기에 아무도 MSDN 기사를 언급하지 않았으며 실제로 나를 위해 정리 한 문서였으며 MSDN에는 매우 좋은 문서 가 있습니다. 다음 조건에 해당하면 예외를 잡아야합니다.

  • 예외가 발생하는 이유를 잘 알고 있으며 FileNotFoundException 오브젝트를 발견 할 때 사용자에게 새 파일 이름을 입력하도록 프롬프트하는 것과 같은 특정 복구를 구현할 수 있습니다.

  • 보다 구체적인 새 예외를 작성하고 던질 수 있습니다.

int GetInt(int[] array, int index)
{
    try
    {
        return array[index];
    }
    catch(System.IndexOutOfRangeException e)
    {
        throw new System.ArgumentOutOfRangeException(
            "Parameter index is out of range.");
    }
}
  • 추가 처리를 위해 예외를 전달하기 전에 부분적으로 처리하려고합니다. 다음 예에서 catch 블록은 예외를 다시 발생시키기 전에 오류 로그에 항목을 추가하는 데 사용됩니다.
    try
{
    // Try to access a resource.
}
catch (System.UnauthorizedAccessException e)
{
    // Call a custom error logging procedure.
    LogError(e);
    // Re-throw the error.
    throw;     
}

전체 " 예외 및 예외 처리 "섹션과 예외에 대한 모범 사례를 읽는 것이 좋습니다 .


1

더 좋은 방법은 두 번째 방법 (예외 유형을 지정하는 방법)입니다. 이것의 장점은 코드에서 이러한 유형의 예외가 발생할 수 있다는 것입니다. 이 유형의 예외를 처리하고 있으며 다시 시작할 수 있습니다. 다른 예외가 발생하면 코드에서 버그를 찾는 데 도움이되는 무언가 잘못되었음을 의미합니다. 응용 프로그램이 결국 중단되지만 누락해야 할 버그가 있다는 것을 알게 될 것입니다.


1

예외를 제외하고 다음을 시도합니다.

먼저, 0으로 나누기, IO 연산 등과 같은 특수 유형의 예외를 포착하고 이에 따라 코드를 작성합니다. 예를 들어, 값의 신뢰성에 따라 0으로 나누거나 (중간 계산 (인수가 아닌) 계산에서 0으로 나누는 간단한 계산기) 또는 예외를 자동으로 처리 할 수 ​​있습니다. 처리를 계속합니다.

그런 다음 나머지 예외를 잡아서 기록하려고합니다. 가능하면 코드 실행을 허용하고, 그렇지 않으면 사용자에게 오류가 발생했음을 알리고 오류 보고서를 우편으로 보내도록 요청하십시오.

코드에서는 다음과 같습니다.

try{
    //Some code here
}
catch(DivideByZeroException dz){
    AlerUserDivideByZerohappened();
}
catch(Exception e){
    treatGeneralException(e);
}
finally{
    //if a IO operation here i close the hanging handlers for example
}

1
제로 예외 등으로 0나누는 것은 a 대신 분자를 미리 확인하여 처리하는 것이 좋습니다 try-catch. 또한 왜 Exception여기서 일반을 잡을 까요? 예상치 못한 모든 경우에 오류 버블을 처리하는 것보다 오류 버블을 올리는 것이 좋습니다.
Keith

내가 제시 한 예에 대해 내가 쓴 것을 더 잘 읽으십시오. 물론 모든 계산기는 주어진 인수를 확인해야합니다. 내가 말한 것은 중간 단계에 관한 것이었다. 이 시점에서 사용자 인수 확인이 이미 발생했습니다. 또한 일부 응용 프로그램에서는 예외가 발생하지 않도록하는 것이 좋습니다. 일부 앱은 예외를 자동으로 처리해야하며 다른 앱은 예외를 오류로 처리해야합니다. 예를 들어 의료 소프트웨어 (예 : 엑스레이 기계)가 예외가 발생하면 중단되어야하는 예외가 발생하더라도 웹 서버가 실행되어야합니다.
Sorcerer86pt

어떤 앱 예외를 자동 으로 처리 해서는 안됩니다 . 때때로 코드에서 처리 할 수있는 예외가 있지만 이러한 사용은 드물고 예상되는 예외와 관련이 있습니다. 웹 서버의 예는 좋지 않은 것입니다. 오류가 기록되는 방법과 오류가 세부적으로 표시되는지 또는 HTTP 500 페이지로 표시되는지 여부를 선택할 수있는 구성 설정이 있어야하지만 오류를 자동으로 무시 해서는 안됩니다 .
키이스

사람들이 실제로 "goto"에 대한 동의어를 하나 더 추가하도록 동기를 부여하는 것이 무엇인지 파악하려고합니다. 그러나 0으로 나누는 것과 관련하여 이것은 언어 향상을 정당화하는 하나의 예외 유형입니다. 왜? A) 0은 통계적으로 데이터 세트에서 무한대이며 B) 예외를 사용하는 것이 훨씬 더 효율적일 수 있습니다. 분할을 수행하는 것이 제로 제로를 테스트하는 한 가지 방법이기 때문입니다. A와 B가 참이면 예외를 사용하여 프로그램의 평균 실행이 더 빨라지고 더 작을 수도 있습니다.
Mike Layton

1

두 번째 방법은 좋은 방법입니다.

관련 오류가 아닌 런타임 예외 (예 : 오류)를 표시하여 오류를 표시하지 않고 응용 프로그램 사용자를 혼동하지 않으려면 오류를 기록하면 기술 팀에서 문제를 찾아 해결할 수 있습니다.

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);//it will write the or log the error in a text file
}

전체 응용 프로그램에 대한 두 번째 접근 방법을 사용하는 것이 좋습니다.


2
두 번째 방법은 오류가 발생한 것보다 사용자를 보여주지 않습니다. 예를 들어, 그들이 무언가를 저장하고 있다면 그것이 실패했다는 것을 알지 못할 것입니다. catch블록은 항상throw 예외를 버블 링하도록 호출 하거나 사용자에게 조치가 실패했음을 알려주는 무언가를 표시하거나 표시해야합니다. 6 개월이 지난 후 검색을 시도하여 찾을 수없는 경우가 아니라도 저장하지 못한 경우 지원 요청을 받으려고합니다.
키이스

0

빈 캐치 블록을 두는 것이 더 나쁜 일입니다. 오류가있는 경우 처리하는 가장 좋은 방법은 다음과 같습니다.

  1. file \ database 등에 로그인하십시오.
  2. 즉시 수정하려고 시도하십시오 (해당 작업을 수행하는 다른 방법을 시도 할 수도 있음)
  3. 이를 해결할 수없는 경우 오류가 있음을 사용자에게 알리고 물론 작업을 중단하십시오

0

나에게 처리 예외는 비즈니스 규칙으로 볼 수 있습니다. 분명히 첫 번째 방법은 용납 할 수 없습니다. 두 번째는 더 나은 것이고 컨텍스트가 그렇게 말하면 100 % 올바른 방법 일 수 있습니다. 예를 들어 Outlook Addin을 개발 중입니다. addin이 처리되지 않은 예외를 throw하면 하나의 플러그인으로 인해 outlook이 자체를 파괴하지 않기 때문에 outlook 사용자가이를 알 수 있습니다. 그리고 당신은 무엇이 잘못되었는지 알아내는 데 어려움을 겪고 있습니다. 따라서이 경우 두 번째 접근 방식은 나에게 맞는 것입니다. 예외를 기록하는 것 외에도 사용자에게 오류 메시지를 표시하기로 결정할 수 있습니다. 비즈니스 규칙으로 간주합니다.


0

가장 좋은 방법은 오류가 발생할 때 예외를 발생시키는 것입니다. 오류가 발생했기 때문에 숨겨서는 안됩니다.

그러나 실제로는 이것을 숨기고 싶을 때 몇 가지 상황이있을 수 있습니다

  1. 타사 구성 요소에 의존하고 오류 발생시 프로그램을 계속 진행하려고합니다.
  2. 오류 발생시 계속해야하는 비즈니스 사례가 있습니다.

6
마십시오 하지 던져 Exception. 이제까지. Exception당신이 원하는 모든 것의 적절한 서브 클래스를 던져라. 그러나 Exception그것은 의미 정보를 전혀 제공 하지 않기 때문에 결코 아니다. 나는 밖으로 던지는 Exception것이 합리적 이지만 하위 클래스가 아닌 시나리오를 볼 수 없습니다 .
CVn


0

catch인수없이 간단하게되어 먹는 예외없이 사용이다. 치명적인 오류가 발생하면 어떻게합니까? 인수없이 catch를 사용하면 무슨 일이 있었는지 알 수있는 방법이 없습니다.

catch 문은보다 구체적인 예외를 포착 FileNotFoundException한 다음 마지막에Exception 다른 예외를 포착하고 기록 할 예외를 포착 해야 합니다.


catch(Exception)마지막에 왜 장군이 있습니까? 기대하지 않는다면 항상 다음 레이어로 전달하는 것이 가장 좋습니다.
Keith

1
@Keith 네 맞아 ...
예기치

0

때로는 사용자에게 아무 말도하지 않는 예외를 처리해야 할 때가 있습니다.

내 길은 :

  • 중요한 예외에 대해 응용 프로그램 수준 (예 : global.asax)에서 포착되지 않은 예외를 포착 (응용 프로그램은 유용 할 수 없음). 이 장소에서 나는 잡을 수 없다. 앱 수준에서 로그하고 시스템에서 작업을 수행하십시오.
  • "제자리에"잡아서 유용한 정보를 사용자에게 표시합니다 (잘못된 숫자를 입력하면 구문 분석 할 수 없음).
  • "백그라운드에서 업데이트 정보를 확인하지만 서비스가 실행되고 있지 않습니다"와 같은 한계 문제에 대해서는 아무런 조치도 취하지 않습니다.

반드시 모범 사례 일 필요는 없습니다. ;-)


0

나는 당신에게 뭔가를 말할 수 있습니다 :

스 니펫 # 1은 예외를 무시하므로 허용되지 않습니다. (아무것도하지 않은 것처럼 삼키는 중입니다).

따라서 아무것도하지 않거나 다시 던지는 캐치 블록을 추가하지 마십시오.

캐치 블록은 일부 값을 추가해야합니다. 예를 들어 최종 사용자에게 출력 메시지 또는 로그 오류.

정상적인 흐름 프로그램 논리에는 예외를 사용하지 마십시오. 예를 들면 다음과 같습니다.

예를 들어 입력 검증. <-이것은 예외적 인 상황이 아니며 IsValid(myInput);입력 항목이 유효한지 확인하는 방법 을 작성해야합니다 .

예외를 피하기위한 설계 코드. 예를 들면 다음과 같습니다.

int Parse(string input);

우리가 파싱 할 수없는 값을 int로 전달하면이 메소드는 다음과 같이 작성할 수 있습니다.

bool TryParse(string input,out int result); <-이 메소드는 구문 분석이 성공했는지 여부를 나타내는 부울을 리턴합니다.

어쩌면 이것이이 질문의 범위를 벗어나는 것일 수도 있지만 이것이 문제 try {} catch(){}와 예외 에 관한 올바른 결정을 내리는 데 도움이되기를 바랍니다 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.