2013-10-18 2 views
2

다른 사람 asked a similar question하지만 대답은 나에게 명확하지 않습니다.코드 유효성 검사를 코드 계약으로 대체 할 수 있습니까?

우리 프로젝트에는 많은 매개 변수 유효성 검사 코드가 있습니다. 공용 메서드에서만 주로 null 매개 변수 검사입니다.

if (param == null) 
{ 
    throw new ArgumentNullException("param"); 
} 

이러한 검사는 사양의 일부가 아닙니다. 그들의 주요 유틸리티는 프로그래밍 오류의 경우 saner 스택 덤프를 얻는 것입니다. 그렇게 간단한 점검이 수행되지 않으면 더미의 한쪽 끝에서 무작위로 10 레벨까지 올라갈 수 있습니다. 다른 라이브러리의 중간 부분에는 NullReferenceException이 있습니다. 이렇게하면 근본 원인에 대한 전체 백 트레이닝 프로세스가 더 길어집니다. 유효성 검사는 의미 론적으로 명확하며 이전에 문제를 파악할 수 있습니다.

우리는 그 일을 많이하고 있기 때문에, 우리는 그러한 점검을하는 더 짧은 방법을 찾고있었습니다. 예 :

ArgumentHelper.ThrowIfNull(param, "param"); 

또는 이와 유사한 구문. 기본적으로 오버 헤드를 피하고 싶습니다. if-throw 구문을 사용하면 코드가 불필요하게 길어집니다.

그런 구문을 실험하면서 어설 션 및 코드 계약과 같은 유사한 구문으로 수렴한다는 것을 알았습니다. 코드 분석은 정적 분석의 가능성과 개발주기 초반에 버그를 잡기 때문에 매우 매력적입니다.

그러나 코드 계약이 "입력 유효성 검사"문제 또는 유효성 검사 문제의 모든 종류를 해결하도록 설계되지 않았 음을 이해합니다. Because the exceptions raised by it are not meant to be caught. 기본 동작은 릴리스 빌드에서 이러한 검사의 코드를 제거하기 때문에 디버깅을 쉽게하기위한 것이 아닙니다. The rewriter just seems like a hack around it and it's not very performant either.

"정적 검증"과 "매개 변수 유효성 검사"에서 모두 이해할 수있는 것은 서로 다른 목표를 가지고 있으므로 상호 교환 할 수 없습니다. 그러나 내 프롤로그에 Code.Contracts을 사용하여 if-then-throw 초반에 자연스럽게 들렸습니다. 뭔가 잘못 됐는지 궁금합니다.

제 질문은 : 매개 변수 유효성 검사를위한 코드 계약을 사용하고 있습니까? 어떤 인증 코드에 대해서도 질문 할 수있는 분명한 질문이 있습니까? "예. 코드 계약을 사용하여 이것을 확인할 수 있습니다"와 "아니오. 코드 계약을 사용하여 확인할 수 없습니다"와 같은 대답을 제시하십시오. 어떻게 구별합니까?

"계약서를 삭제해도 기능이 올바르게 작동합니까?"라는 생각이 들었습니다. 이것이 올바른 접근 방법입니까?

+0

이 또한 매우 깨끗한 방법으로 코드 계약을 예외를 던져 제공 내 확장 방법을 확인하십시오 http://blog.rsuter.com/elegant-method-parameter-validation- with-code-contracts-support/ –

+0

@RicoSuter 귀하의 apprach는 여전히 코드 계약에 대한 런타임 검사를 활성화해야합니다. 왜 그게 나쁜지에 대한 내 대답을 참조하십시오 : http://stackoverflow.com/a/25700857/54937 –

+0

아니요, 런타임 유효성 검사가 비활성화 된 경우에도 예외가 던져 지더라도 예외가 던져 질 수 있습니다. –

답변

4

흠. 나는 명확하지 않은 해답을 쓴 사람이다 : - /. 나는 그것을 다른 방식으로 표현하는 것에 찔림을 가질 것이다.

귀하의 접근 방법은 정확하지만 합병증이 있습니다. 사용자 입력 유효성 검사의 관점에서이를 살펴 보는 것이 도움이 될 수 있습니다. 다음 코드를 사용하십시오 :

사용자가 새 사용자 이름을 입력하는 것을 잊을 수는 없습니다. 빈 문자열은이 메소드가 수신 할 것으로 예상되는 입력 중 하나이며이를 처리하도록 설계되었습니다.

이제 우리는 사용자의 입력을 처리하는 방법을 추가 말할 수 :

public string DoSomethingToUserName(string userInput) 
{ 
    return userInput.ToLower(); 
} 

이 방법은 UserInput 사용자가 null이 아닌 것으로 가정을; 네가 말했듯이, 그것이 사실이 아니라면 효과가 없을 것이다. 의 null 값이이면 누군가 프로그래밍 오류가 발생했습니다. 그래서 우리는 명시 할 수있는 방법의 인터페이스의 일부, 그리고 누군가가 놓 쳤어 않다면 우리에게 경고하는 정적 검증을 얻을 :

public string DoSomethingToUserName(string userInput) 
{ 
    Contract.Requires(userInput != null); 

    return userInput.ToLower(); 
} 

이 사람이 프로그래밍 오류를 했는가 의미뿐만 아니라, 런타임에 발생하면, 정적 검증기는 Reflection 사용 또는 유사한 이유로 또는 버그가 있음으로 인해 문제를 감지하지 못했습니다. 따라서 적어도 공공 계약에 대해서는 계약 재 작성을 사용하는 것이 좋습니다.

따라서 계약을 사용하여 메소드가없는 경우에만 매개 변수를 검사합니다. 그들은 방법의 성공적인 운영을위한 전제 조건이다. 전제 조건이 실패하면 누군가가 실패하고 버그를 드러내 기 때문에 예외를 catch하고 싶지 않습니다. DoSomethingToUserName 실제로 사용자 이름 자체가 조작하지 않는 경우

합병증 온다 : 사용자 이름이 null의 경우 지금

public string DoSomethingToUserName(string userInput) 
{ 
    return DoFirstThingToUserName(userInput); 
} 

private string DoFirstThingToUserName(string userInput) 
{ 
    Contract.Requires(userInput != null); 

    return userInput.ToLower(); 
} 

이 DoFirstThingToUserName이 실패를; DoSomethingToUserName은 그것이 존재하는지 여부에 상관하지 않습니다. 그러나 아무도 public 인터페이스를 통해 userInput을 사전 검증해야한다는 사실을 알 수 없습니다. 따라서 우리는 외부 세계와 계약을 발표해야합니다.

public string DoSomethingToUserName(string userInput) 
{ 
    Contract.Requires(userInput != null); 

    return DoFirstThingToUserName(userInput); 
} 

private string DoFirstThingToUserName(string userInput) 
{ 
    Contract.Requires(userInput != null); 

    return userInput.ToLower(); 
} 
1

빠른 대답은 아니오입니다. 코드 계약으로 입력 유효성 검사를 대체 할 수 없습니다. 가장 큰 차이점은 예외적 인 상황이 아니므로 입력 유효성 검사는 잘못된 데이터가 들어오는 경우 예외를 throw해서는 안된다는 것입니다. 다른 한편, 계약 위반은 항상 시스템의 버그를 신호로 나타내므로 예외를 던지거나 앱을 파쇄해야합니다 (패스트 패스트 원칙에 따라).

내 블로그 게시물을 확인하십시오 Code contracts vs input validation

관련 문제