정적 및 런타임 검사를 사용하여 C# 코드 계약을 사용하기 시작합니다. 문제는 일부 코드 계약 점검이 메소드마다 중복 될 수 있으므로이를 방지 할 좋은 방법이 없다는 것입니다.코드 계약 명세서의 코드 중복을 피하는 방법
내 생각에 정적 분석기 경고를 피하고 가능한 경우 억제하지 않는 것이 좋습니다.
는 예를 살펴 수 있습니다 :
다음의 간단한 클래스가 있습니다. 우리가 모델 속성에 대한 공공의 기본 생성자 및 공공 세터를 제공해야합니다 (MVC, 데이터베이스 매핑 바인딩 모델 같은) 일부 반사 기반 기술에 대한
class Category
{
public string Name { get; set; }
}
class Article
{
public string Title { get; set; }
public string Content { get; set; }
public Category Category { get; set; }
}
: 이것은 일반적인 비즈니스 로직 모델 클래스의 예이다. 따라서 Category에 대한 Contract.Invariant (! string.IsNullOrEmpty (Name))가 항상 true라는 것을 보장 할 수는 없습니다.
그런 다음 내부 CategoryRepository 클래스에서 다음 메소드를 만듭니다. 모든 유효성 검사가 이전에 통과되었고 유효한 범주 만 허용한다고 가정합니다.
public void Add(Category category)
{
Contract.Requires(category != null);
Contract.Requires(!string.IsNullOrEmpty(category.Name));
...
}
지금까지는 그렇게 좋았습니다. 그런 다음 우리는 ArticleRepository 유사한 방법을 추가
public void Add(Article article)
{
Contract.Requires(article != null);
Contract.Requires(!string.IsNullOrEmpty(article.Title));
Contract.Requires(!string.IsNullOrEmpty(article.Content));
Contract.Requires(article.Category != null);
Contract.Requires(!string.IsNullOrEmpty(article.Category.Name));
...
}
을 문제점은 다음과 같습니다
1) 우리는 우리가 같은 검사 중복 할 필요가 계약에 유효한 카테고리 기대 모든 장소에서 :
Contract.Requires(category != null);
Contract.Requires(!string.IsNullOrEmpty(category.Name));
을
때로는 Contract.Assume 메소드에서 이러한 확인을 수행해야 할 수도 있습니다.
2) 외부 클래스 (예 : Article)는 Category 클래스의 계약을 확인해야합니다. LoW 위반 및 기본 캡슐화 원칙과 같습니다.
1)과 같이 분류 클래스의 순수한 방법으로 중복 된 코드를 추출 :이 방법
[Pure]
public static bool Valid(Category category)
{
if (category == null)
return false;
return !string.IsNullOrEmpty(category.Name);
}
을하고 이용 계약 :
Contract.Requires(Category.Valid(category));
을
나는 다음 솔루션을 시도 별로 좋은 해결책이 아니며 작동하지 않습니다. 정적 분석기가 만족스럽지 않습니다.
2) 범주에 대한 불변의 정의 :
[ContractInvariantMethod]
void Invariant()
{
Contract.Invariant(!string.IsNullOrEmpty(Name));
}
이 솔루션은 꽤 좋은 및 Category 클래스에서 불필요한 검사를 제거 할 수 있지만, 실제로 불변는 더 유효하지 않습니다 (예를 들어, 기본 생성자에서). 그리고 정적 분석기는이 위반을 정확하게 감지합니다.
내가 잘못하고 있으며 정적 분석기와 함께 코드 계약을 사용하는 더 편리한 방법이 있습니까?
감사합니다. Matthew에게 감사드립니다. 가능한 타협처럼 보입니다. –
또 다른 옵션은, 생성 된 후에 객체를 변경할 필요가없는 경우 변경 가능한 객체에서 복사 생성 될 수 있고 생성시 유효성 검사를 수행 할 수있는 새로운 불변 클래스를 만드는 것입니다. 그렇게하면 외부에서 유효성을 검사 할 필요가 없습니다. 하나를 통과하고 null이 아닌 경우 유효 함이 보장됩니다. –