2009-07-09 2 views
1

전자 메일을 보내는 단일 메서드로 간단한 클래스를 코딩하고 있습니다. 필자의 목표는 레거시 Visual Basic 6 프로젝트에서이를 구현하여 COM Interop 기능을 통해 COM 개체로 노출시키는 것입니다.예외 처리 : 인수 유효성 검사와 관련하여 얼마나 세분합니까?

세부 사항이 있습니다. 해결하기 어려운 부분이 있습니다. 매개 변수의 유효성을 검사하는 방법이 세분화되어야합니다. 그래서, 어떤 제안이 많이 이해할 수있을 것이다

public class MyMailerClass 
{ 
    #region Creation 
    public void SendMail(string from, string subject, string to, string body) 
    { 
     if (this.IsValidMessage(from, subject, to, body)) // CS1501 
     { 
      MailMessage msg = new MailMessage(); 
      msg.IsBodyHtml = true; 
      msg.From = new MailAddress(from); 
      msg.To.Add(to); 
      msg.Subject = subject; 
      msg.Body = body; 
      SmtpClient srv = new SmtpClient("SOME-SMTP-HOST.COM"); 
      srv.Send(msg); 
     } 
     else 
     { 
      throw new ApplicationException("Invalid message format."); 
     } 
    } 
    #endregion Creation 

    #region Validation 
    private bool IsValidMessage(string from, string subject, string to, string body) 
    { 
     Regex chk = new Regex(@"(\[email protected][a-zA-Z_]+?\.[a-zA-Z]{2,6})"); 
     if (!chk.IsMatch(from)) 
     { 
      return false; 
     } 
     if (!chk.IsMatch(to)) 
     { 
      return false; 
     } 
     if (!string.IsNullOrEmpty(subject)) 
     { 
      return false; 
     } 
     if (!string.IsNullOrEmpty(body)) 
     { 
      return false; 
     } 
     else 
     { 
      return true; 
     } 
    } 
    #endregion Validation 
} 

: 그 빛에, 난 정말에 대한 행복하지 않다, 그리고 일이 전혀 실제로 예외를 처리하고있어 방법 세부되어 아니다 귀하의 의견은 모두에 미리 감사드립니다.

참고 :이 특별한 경우에 엔터프라이즈 라이브러리 Validation Application Block을 구현하는 것이 편리할까요?

+0

당신을 ArgumentException을 잘못 사용하고 있습니다 - 두 번째 인수는 유효하지 않은 인수의 _name_이어야하는 _string_입니다. 대신, 당신은 그 논쟁의 가치를 거기에 전달하고 있습니다. 당신은 다음과 같이해야합니다 :'new ArgumentException ("잘못된 발신자 주소 :"+ from ","from "); –

+0

감사합니다. Pavel, 고맙습니다. –

+0

새로운 버전의 코드는 디버그하기가 어렵습니다. IsValidMessage()에서는 모든 조건을 한 줄로 확인합니다. 디버거를 사용하여 코드를 단계별로 실행할 때 만족되지 않는 것을 어떻게 찾을 수 있습니까? 다음과 같이 작성할 수 있습니다 : if (string.IsNullOrEmpty (subject)) {return false; } if (! string.IsNullOrEmpty (body)) {return false; } 그런 다음 Regex 객체를 만들고 조건을 한 번만 확인하면 조건이 만족되지 않으면 즉시 false가 반환됩니다. – sharptooth

답변

9

SendMail의 발신자에게 부과하는 계약을 고려하십시오. 그들은 당신에게 "유효한 이메일 주소"를 전달해야합니다. 유효한 사람을 누가 결정합니까? SendMail 않습니다. 기본적으로 귀하의 방법은 "높은 유지 보수"입니다 - 그것은 원하는 방식대로 정확하게 원하는 것이며, 귀하가 제공하고자하는 것이 만족 스러운지를 판단 할 수있는 유일한 방법은 노력하고 최선을 기원하는 것입니다.

호출자가이를 충족시키는 방법을 알지 못하거나, 예외를 피할 수있는 방법이없는 경우 유지 관리 방법을 많이 쓰지 마십시오. 부울을 반환하는 "IsValidAddress"메서드에 유효성 검사 논리를 추출합니다. 그런 다음 SendMail 메서드를 호출하여 IsValidAddress를 호출하고 유효하지 않은 경우 throw하십시오. 문제의

(1) 증가 분리 :

은이 변화에서 여러 좋은 효과를 얻을. SendMail의 임무는 전자 메일 주소가 유효한지 여부를 판단하지 않고 전자 메일 메커니즘을 작동시키는 것입니다. 해당 정책 결정을 검증을 전문으로하는 코드로 분리하십시오.

(2) 주소 확인은 그 자체로 유용한 도구입니다. 메일을 보내지 않고도 주소가 올바른지 여부를 알고 싶을 때가 많습니다.

(3) 유효 논리가 모두 하나의 합리적인 장소에 있기 때문에 쉽게 업데이트하고 향상시킬 수 있습니다.

(4) 발신자에게는 예외가 발생하지 않는다고 보장 할 수있는 방법이 있습니다. 호출 측이, 인수가 유효한 것을 보증하지 않고 메소드를 호출 할 수없는 경우, 예외를 캐치해야합니다. 이상적으로는 호출자가 코드를 수정하기 위해 예외를 처리하도록하지 말아야합니다. 비록 그들이 넘겨받은 데이터가 좋지 않을지라도 결코 던지지 않는 올바른 코드를 작성할 수있는 방법이 있어야합니다. 여기

은 내가 당신이 도움이 될 수있는이 주제에 쓴 기사의 몇 가지 있습니다 :

예외 처리 : http://ericlippert.com/2008/09/10/vexing-exceptions/

높은 유지 보수 방법 : 보조 노트로 http://blogs.msdn.com/ericlippert/archive/2008/09/08/high-maintenance.aspx

+0

에릭, 정교하고 탄탄한 조언을 해주신 것에 대해 많은 감사를드립니다! –

3

두 개의 throw 문을 연속으로 사용하면 첫 번째 문구 만 실행되고 예외 처리기로 전달되고 결코 두 번째 문단에 전달되지 않습니다. throw.

내 의견으로는 "보낸 사람 전자 메일이 유효하지 않습니다."와 같은 단순한 말로 충분합니다. 전자 메일은 매우 간단하고 짧기 때문에 사용자는 추가 지침없이이 문제를 해결할 수 있습니다.

나는 또한 모든 전달 된 값을 확인한 다음 작업을 시작하는 것이 더 좋을 것이라고 생각합니다. 유효하지 않은 매개 변수 값이 발생하여 예외를 throw하여이 작업을 완료 할 수없는 경우 작업을 부분적으로 수행하는 것이 무엇입니까? 가능하다면 가능한 한 빨리 오류를 표시하십시오.

+0

그래서 메소드의 시작 부분에서 모든 매개 변수의 유효성을 세 가지 방법으로 확인하는 것과 같은 의미 일 수 있습니다. 부울 플래그를 들고 일종의 "isMsgOk = true"형식으로 구성한 다음 모든 구성 작업을 수행하는 것 그곳에? –

+0

아니요, 예외가있을 때 플래그를 사용해야하는 이유는 무엇입니까? 각 매개 변수를 확인할 수 있으며 처음 잘못된 값을 발견하면 예외를 throw합니다. – sharptooth

1

그리고 :

사용

string.IsNullOrEmpty(subject) 

보다는 당신의 문자열이 비어있는 경우 확인하기위한

subject == null 

.

+0

Jason에게 감사드립니다. 나는 그것을 포함하고있다. –