c# 예제 성능 - 예외 처리를 위해 try catch를 사용하는 것이 모범 사례입니다.





7 Answers

가장 좋은 방법은 예외 처리 가 결코 문제를 숨기지 않아야한다는 것 입니다. 이것은 try-catch 블록이 극히 드문 경우임을 의미합니다.

try-catch 사용하는 것이 의미가있는 3 가지 경우가 있습니다.

  1. 최대한 낮은 우선 순위로 알려진 예외를 처리하십시오. 그러나 예외를 예상하는 경우 먼저 테스트하는 것이 더 좋습니다. 예를 들어 구문 분석, 형식 지정 및 산술 예외는 특정 try-catch 보다는 논리 검사를 통해 항상 잘 처리됩니다.

  2. 예외 (예 : 트랜잭션 로깅 또는 롤백)에 대해 작업해야하는 경우 예외를 다시 throw하십시오.

  3. 가능한 한 높은 수준의 예외로 예외를 처리해야합니다. 예외를 소비하고 다시 throw하지 않는 유일한 코드는 UI 또는 공용 API 여야합니다.

원격 API에 연결 중이라고 가정하면 여기에 특정 오류가 예상됩니다 (이러한 상황에서 해결해야 할 사항이 있음).이 경우는 1입니다.

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

return true;

기대하지 않는 다른 예외는 발견되지 않습니다.

이제 데이터베이스에 무언가를 저장하려고한다고 가정 해보십시오. 실패 할 경우 다시 롤백해야하므로 case 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에 대한 예상 오류 또는 손 오류 처리 방지).

사례 2조차도 더 나은 패턴으로 대체 될 수 있습니다. 예를 들어 트랜잭션 범위 (블록에서 커밋되지 않은 트랜잭션을 롤백하는 블록 사용)는 개발자가 모범 사례 패턴을 잘못 선택하는 것을 어렵게 만듭니다.

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

TL : 최선의 방법은 실제로 try-catch 블록을 사용하지 않는 것입니다.

예외처리 무시 throw

수석 개발자라고 주장하는 사람조차도 동료 코드를 유지하면서 다음 코드를 자주 볼 수 있습니다.

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

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

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

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

제게 조언 해주세요.




사용자가 코드에서 일어난 일에 대해 걱정할 필요가있는 유일한 경우는 문제를 피하기 위해 할 수 있거나해야 할 일이있는 경우입니다. 사용자가 양식의 데이터를 변경할 수 있다면 문제를 피하기 위해 버튼을 누르거나 응용 프로그램 설정을 변경 한 다음 알려주십시오. 그러나 사용자가 피할 수있는 능력이없는 경고 또는 오류만으로도 제품에 대한 신뢰를 잃을 수 있습니다.

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

정신없는 코딩은 잘못된 코딩의 유일한 종류입니다. 이러한 상황에서 수행 할 수있는 좋은 점이 있다는 것을 느끼는 사실은 좋은 코딩에 투자되었음을 보여 주지만 이러한 상황에서 일반적인 규칙에 도장을 찍지 말고 처음부터 던져야 할 이유를 이해하고 당신은 그것을 복구 할 수 있습니다.




두 번째 방법 (예외 유형을 지정하는 방법)이 더 좋습니다. 이것의 장점은이 예외 유형이 코드에서 발생할 수 있다는 것을 알고 있다는 것입니다. 이 유형의 예외를 처리하고 있으며 다시 시작할 수 있습니다. 다른 예외가 발생하면 코드에서 버그를 찾는 데 도움이되는 잘못된 것이 있음을 의미합니다. 응용 프로그램이 결국 충돌하지만 사용자가 놓친 버그 (버그)가 수정되어야한다는 것을 알게됩니다.




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

  1. file \ database에 로그인하십시오.
  2. 비행 중에 그것을 고치려고 노력하십시오 (아마 그 작업을하는 다른 방법을 시도하십시오)
  3. 문제를 해결할 수 없다면 사용자에게 오류가 있음을 알리고 작업을 중단하십시오.



모범 사례는 오류가 발생할 때 예외를 throw하는 것입니다. 오류가 발생했기 때문에 오류가 숨겨져서는 안됩니다.

그러나 실생활에서는 이것을 숨기고 자 할 때 여러 가지 상황을 가질 수 있습니다.

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



인수가없는 catch 는 단순히 예외를 먹는 것이며 아무 쓸모가 없습니다. 치명적인 오류가 발생하면 어떻게해야합니까? catch없이 catch를 사용하면 어떤 일이 일어 났는지 알 수있는 방법이 없습니다.

catch 문은 FileNotFoundException 과 같은보다 구체적인 예외를 잡아야하며, 결국 에는 다른 예외를 잡아 로그에 남기는 Exception 을 잡아야합니다.




예외를 사용하여 다음을 시도합니다.

먼저, 0으로 나누기, IO 작업 등 특별한 유형의 예외를 catch하고 이에 따라 코드를 작성합니다. 예를 들어 사용자에게 경고 할 수있는 값의 출현에 따라 제로에 의한 나눗셈 (중간 계산 (인수가 아닌)의 간단한 계산기는 제로에 도달 함) 또는 자동으로 해당 예외를 처리하고, 로깅 처리를 계속합니다.

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

코드에서 다음과 같이 :

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
}





Related