2013-09-28 2 views
1

예외 처리의 우수 사례와 관련하여 여러 기사를 읽었습니다. 그것의 대부분은 예기치 않은 예외를 태클했지만 아직 저자가 예상했다. 나는 단지 을 명확히하고 내가 할 수있는 가능한 나쁜 습관을 제거하고 싶습니다.. 이미 이러한 문제가 이미 발생할 것으로 예상하기 때문에 예외를 던지는 것은 약간 중복되는 것으로 가정합니다.예상되는 예외 처리

의 나는이 코드를 가지고 있다고 가정 해 봅시다 :

string fileName = Path.Combine(Application.StartupPath, "sometextfile.txt"); 

// There's a possibility that the file doesn't exist <<<<<<<<<<<<<<<<<<<<< 
if (!File.Exists(fileName)) 
{ 
    // Do something here 
    return; 
} 

// Therefore, this will return an exception 
using (StreamReader file = 
    new StreamReader(fileName)) 
{ 
    // Some code here 
} 

은 물론, 내가 무엇을 할 것이라고하는 것은 메시지 박스가 "파일을 찾을 수 없습니다"말을 사용자에게 알려 드리고자합니다. 이 작업을 효율적으로 또는보다 효과적으로 수행 할 수 있습니까?

내가 예상되는 오류 코드가 그 특정 상황에 대한 오류 메시지를 표시하는 메시지 박스를 호출하는 방법 만들 포함하는 열거 만드는 것입니다있는 또 다른 아이디어 :

enum ErrorCodes {null, zero, ...} 
public void showError(ErrorCodes error) 
{ 
    string message; 
    switch (error) 
     { 
     case ErrorCode.null: 
     { 
      message = "value cannot be null"; 
      break; 
     } 
     case ErrorCode.zero: 
     { 
      message = "cannot divide by zero"; 
      break; 
     } 
} 

MessageBox.Show(message, Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error); 
} 
+4

이것은 모두 실제로 * 나쁜 생각입니다. 이미이 코드가 없으면 괜찮은 예외 메시지가 나타납니다. StreamReader 생성자가 Message 속성을 throw하고 표시하는 예외를 잡습니다. –

+1

그래, 이해 하겠지만 사용자가 쉽게 이해할 수있는 맞춤 메시지를 보여주고 싶다. 잡는 것보다 예외를 피하는 것이 더 좋지 않은가? – CudoX

+0

메시지 프리젠 테이션을 io 액세스와 분리해야합니다. 아마 당신의 코드가 언젠가 콘솔 앱에서 사용될 것입니까? Btw는 예기치 않은 실행 경로에만 예외를 사용하고 존재하지 않는 파일은 예외로 사용하지 않습니다. –

답변

1

코드의 경우를 예를 들어 클릭 할 때의 이벤트 핸들러와 같이 프런트 엔드에있는 파일에 액세스하려는 경우 오류 상황을 확인하고 메시지를 표시 한 다음 돌아 오는 것이 좋습니다.

내가 제대로 질문을 이해한다면 당신은이 작업을 수행해야하는지 여부를 알고 싶어, 잘 될 것

public void button_Click() { 
    if(!File.Exists(textBox.Text)) { 
     MessageBox.Show("Could not find the file"); 
     return; 
    } 

    ProcessFile(textBox.Text); // would have thrown an exception if the file didn't exist 
} 

에는 processFile 그것을 처리되지 않습니다 예외의 다른 종류를 throw하는 경우를 제외하고.

이 작업을 수행 할 수 있습니다 :

public void button_Click() { 
    try { 
     ProcessFile(textBox.Text); // throwns an exception if the file didn't exist 
    } catch(Exception ex) { 
     MessageBox.Show(GetUserMessage(ex)); 
     return; 
    } 
} 

을 내 생각에이 두 가지를 모두 수행하는 것이 좋습니다 :

public void button_Click() { 
    try { 
     if(!File.Exists(textBox.Text)) { 
      MessageBox.Show("Could not find the file"); 
      return; 
     } 

     ProcessFile(textBox.Text); // throwns an exception if the file didn't exist 
    } catch(Exception ex) { 
     MessageBox.Show(GetUserMessage(ex)); 
     return; 
    } 
} 

당신이 관련 사용자에게 가장 구체적인 메시지를 제공 할 수있는이 방법을 그가 무엇을하고 있었는지 이 지점에서. 예를 들어 Excel 파일을 열려고하면 "가져 오려는 Excel 파일을 찾을 수 없습니다"라고 말할 수 있습니다.

파일을 삭제하려고 시도한 시점과 파일을 처리하려고 시도한 시점 사이에 파일 이름이 바뀐 경우에도 작동합니다.

public void button_Click() { 
    try { 
     if(!File.Exists(textBox.Text)) { 
      throw new UserException("Could not find the file"); 
     } 

     ProcessFile(textBox.Text); // throwns an exception if the file didn't exist 
    } catch(Exception ex) { 
     MessageBox.Show(GetUserMessage(ex)); 
     return; 
    } 
} 

이 경우 자신의 예외 클래스 UserException를 작성하고 그냥 번역하지 않고 함께 그 메시지를 전달합니다 :

또는이와 비슷한 작업을 수행 할 수있다. 이렇게하면 메시지를 표시하는 데 사용하는 동일한 코드를 다시 사용할 수 있습니다. 클래스

오류가 다음 예외를 throw 할 몇 가지 클래스 라이브러리에서 발생하는 경우에서

예외. 예외의 목적은 오류가 눈에 띄지 않게 할 수 없다는 것입니다.

예를 들어, 당신은이 원하지해야

class MyFileHandler { 
    public void OpenFile(string fileName) { 
     if(!File.Exists(fileName)) return; 
     // do stuff 
    } 

    public void DoStuff() { 
     // do stuff 
    } 
} 

개발자 그가이 일을 가정 할 myFileHandlerInstance.OpenFile("note.txt")라고 이제합니다.당신과 같이, 부울을 반환 할 수 :

class MyFileHandler { 
    public bool OpenFile(string fileName) { 
     if(!File.Exists(fileName)) return false; 
     // do stuff 
     return true; 
    } 

    public void DoStuff() { 
     // do stuff 
    } 
} 

을하지만 지금은 그 값을 확인 개발자에 의존하고, 이것은 일반적인 방법으로 사용되지만 오류는 무시되었다 및 예외가 더 좋은 연습이되었습니다 이유입니다 간과.

사용자에게 무엇을 표시해야하는지는 예외 메시지를 직접 표시해서는 안되며, 개발자가 아닌 사용자를 대상으로합니다. 만약 당신이 좋아하면

public string GetUserErrorMessage(Exception ex) { 
    if(ex is FileLoadException) { 
     var fileLoadException = (FileLoadException)ex; 
     return "Sorry but we failed to load the file: " + fileLoadException.FileName; 
    } 
} 

당신은 오류 코드를 포함한 자세한 내용은 예외 속성을 검사 할 수 있습니다 : 그래서 같은 예외 객체를 사용하여 최적의 메시지를 반환하는 방법을 제안한다. 또한 어딘가에 사용자가 볼 수없는 어딘가에 자신의 디버깅 목적을 위해 어딘가에 실제 예외 정보를 캡처하는 것이 좋습니다.

+0

제안을 주셔서 감사합니다. 방금 몇 가지 설명을 원합니다. 예외에 관한 세부 정보를 이미 검사 한 경우 어떻게해야합니까?try-catch 문으로 둘러 싸서 "user-MessageBox"로 건너 뛰기보다는 예외 정보를 잡는 것이 현명합니다 (개발자가 이미 감지 한 _가 이미 예상 됨). – CudoX

+0

@ Gelo103097 저는 아닙니다. 확실히 귀하의 질문을 이해하지만 답변에 대한 답변을 업데이트했습니다. –

1

이러한 것들은 결코 쉬운 일이 아닙니다. 스페인의 종교 재판소와 마찬가지로 예외적으로 예외는 결코 예상되지 않는다. 첫 번째 예제에서 파일은 File.Exist를 호출 할 때 존재할 수 있지만 파일을 열려고하면 존재하지 않습니다 (파일 삭제, 네트워크 실패, 엄지 드라이브 꺼내기 등). 최대한 모범 사례 : 가능한 한 자신을 보호하고 최선을 다하는 방법을 알고 희망하는 예외 만 잡으십시오. 프로그램이 실패하고 수행 할 수있는 최선의 일은 처리되지 않은 오류가 가능한 코드의 사용자에게 명확하게 전달되는지 확인하는 것입니다 (두 번째 예제의 핵심).

오류를 알리는 작업은 코드의 용도와 사용하는 사람에 따라 크게 다릅니다. MessageBoxes는 자주 사용되지만 일반적으로 '유용하지 않습니다'. 오류의 원인이 사용자에게 명확하지 않은 경우 그들이 할 수있는 일은 jpg 이미지를 보내는 것입니다 (이것이 가장 좋은 경우입니다 : -D). 사용자가 정보를 잘라 내기/붙여 넣기 (스택 추적과 같은) 할 수있는 문제 및/또는 사용자 정의 대화 상자를 기록하는 방법을 제공하는 것이 훨씬 더 유용합니다. 사용자가 파일을 선택하고 네트워크 딸꾹질이있는 경우를 생각해보십시오. 그들은 발견되지 않은 파일에 대해이 오류가 발생했음을 알려주지 만 그 때까지 네트워크가 제대로 작동하기 때문에 본인 또는 본인이 보게됩니다. 간단한 "파일을 찾을 수 없음"메시지는 충분한 정보를 제공하므로 사용자에게 "잘 모르겠습니다. 지금은 잘되어서 다행"이라고 말하면됩니다 ... 이것은 자신감을 불러 일으키지 않습니다. 가장 좋은 방법은 적어도 일어난 일에 대해 대략적인 생각을하기에 충분한 '빵 부스러기'를 남기는 것입니다. 전체 파일 경로와 같은 것조차도 무엇이 잘못되었는지 알아내는 데 필요한 단서를 제공 할 수 있습니다.