2010-04-08 1 views
2

은 주조 약 CA1800 PostSharp 규칙 "로" 및 에 대한 "입니다"이 질문입니다. 나는 내가 생각한 해결책이 가능한 최선인지 또는 내가 볼 수없는 어떤 문제가 있는지 알고 싶다."PostSharp가 CA1800에 대해 불평 함 : DoNotCastUnecessarily"이 수정 사항이 최선입니까?

본인은이 코드 (OriginaL Code라는 이름으로 최소 관련 항목으로 축소)가 있습니다. ValidateSubscriptionLicenceProducts 함수는 캐스팅하고 (// Do Any Whatever) SubscriptionLicence (표준, 신용 및 TimeLimited의 3 가지 유형이 될 수 있음)의 유효성을 검사합니다.

PostSharp는 CA1800에 대해 불평합니다 : DoNotCastUnecessarily. 그 이유는 동일한 객체를 두 번 같은 유형으로 캐스팅하기 때문입니다. 가장 좋은 경우에이 코드는 2 회 (StandardLicence 인 경우) 및 최악의 경우 4 회 (TimeLimited 라이센스 인 경우) 캐스팅됩니다. 나는 여기에 성능에 큰 영향을 미치지 않기 때문에 규칙을 무효화하는 것이 가능하다는 것을 안다. (처음 접근했다.)하지만 나는 최선의 접근 방식을 시도하고있다.

//Version Original Code 
    //Min 2 casts, max 4 casts 
    //PostSharp Complains about CA1800:DoNotCastUnnecessarily 
    private void ValidateSubscriptionLicenceProducts(SubscriptionLicence licence) 
     { 
    if (licence is StandardSubscriptionLicence) 
      {    
       // All products must have the same products purchased 
       List<StandardSubscriptionLicenceProduct> standardProducts = ((StandardSubscriptionLicence)licence).SubscribedProducts; 
       //Do whatever 
      } 
      else if (licence is CreditSubscriptionLicence) 
      {    
       // All products must have a valid Credit entitlement & Credit interval 
       List<CreditSubscriptionLicenceProduct> creditProducts = ((CreditSubscriptionLicence)licence).SubscribedProducts; 
       //Do whatever 
      } 
      else if (licence is TimeLimitedSubscriptionLicence) 
      {     
       // All products must have a valid Time entitlement 
       // All products must have a valid Credit entitlement & Credit interval 
       List<TimeLimitedSubscriptionLicenceProduct> creditProducts = ((TimeLimitedSubscriptionLicence)licence).SubscribedProducts; 
       //Do whatever 
      } 
      else 
       throw new InvalidSubscriptionLicenceException("Invalid Licence type"); 

    //More code... 


     } 

"로"를 사용 Improved1 버전입니다. CA1800에 대해 불평하지만 문제는 항상 3 번을 던져 것입니다 (미래에 우리는 라이센스의 30 ~ 40 종류가 있다면 나쁜 수행 할 수 있습니다)

//Version Improve 1 
    //Minimum 3 casts, maximum 3 casts 
    private void ValidateSubscriptionLicenceProducts(SubscriptionLicence licence) 
     { 
     StandardSubscriptionLicence standardLicence = Slicence as StandardSubscriptionLicence; 
      CreditSubscriptionLicence creditLicence = Clicence as CreditSubscriptionLicence; 
      TimeLimitedSubscriptionLicence timeLicence = Tlicence as TimeLimitedSubscriptionLicence; 

    if (Slicence == null) 
      {    
       // All products must have the same products purchased 
       List<StandardSubscriptionLicenceProduct> standardProducts = Slicence.SubscribedProducts; 
       //Do whatever 
      } 
      else if (Clicence == null) 
      {    
       // All products must have a valid Credit entitlement & Credit interval 
       List<CreditSubscriptionLicenceProduct> creditProducts = Clicence.SubscribedProducts; 
       //Do whatever 
      } 
      else if (Tlicence == null) 
      {     
       // All products must have a valid Time entitlement 
       // All products must have a valid Credit entitlement & Credit interval 
       List<TimeLimitedSubscriptionLicenceProduct> creditProducts = Tlicence.SubscribedProducts; 
       //Do whatever 
      } 
      else 
       throw new InvalidSubscriptionLicenceException("Invalid Licence type"); 

    //More code... 
     } 

을하지만 나중에 내가 최고의 하나에 생각하지 마십시오. 이것이 내가 사용하고있는 최종 버전입니다.

//Version Improve 2 
// Min 1 cast, Max 3 Casts 
// Do not complain about CA1800:DoNotCastUnnecessarily 
private void ValidateSubscriptionLicenceProducts(SubscriptionLicence licence) 
     { 
      StandardSubscriptionLicence standardLicence = null; 
      CreditSubscriptionLicence creditLicence = null; 
      TimeLimitedSubscriptionLicence timeLicence = null; 

      if (StandardSubscriptionLicence.TryParse(licence, out standardLicence)) 
      { 
       // All products must have the same products purchased 
       List<StandardSubscriptionLicenceProduct> standardProducts = standardLicence.SubscribedProducts; 
    //Do whatever 
      } 
      else if (CreditSubscriptionLicence.TryParse(licence, out creditLicence)) 
      { 
       // All products must have a valid Credit entitlement & Credit interval 
       List<CreditSubscriptionLicenceProduct> creditProducts = creditLicence.SubscribedProducts; 
       //Do whatever 
      } 
      else if (TimeLimitedSubscriptionLicence.TryParse(licence, out timeLicence)) 
      { 
       // All products must have a valid Time entitlement 
       List<TimeLimitedSubscriptionLicenceProduct> timeProducts = timeLicence.SubscribedProducts; 
       //Do whatever 
      } 
      else 
       throw new InvalidSubscriptionLicenceException("Invalid Licence type"); 

      //More code... 

     } 


    //Example of TryParse in CreditSubscriptionLicence 
    public static bool TryParse(SubscriptionLicence baseLicence, out CreditSubscriptionLicence creditLicence) 
     { 
      creditLicence = baseLicence as CreditSubscriptionLicence; 
      if (creditLicence != null) 
       return true; 
      else 
       return false; 
     } 

그것은 (코드 이하에 복사)에 "tryparse"방법을 갖는 클래스 StandardSubscriptionLicence, CreditSubscriptionLicence 및 TimeLimitedSubscriptionLicence의 변화를 요구한다. 이 버전에서는 최소한 한 번만 최대 3 번 캐스팅 할 것입니다. 개선 2에 대해 어떻게 생각하십니까? 그것을하는 가장 좋은 방법이 있습니까?

답변

4

3 개의 코드 조각 중 "개선 2"가 가장 좋은 것 같습니다. 그러나 캐스팅의 필요성을 완전히 제거 할 수있는 방법으로 디자인을 개선 할 수 있다고 생각합니다.

ValidateProducts ~ SubscriptionLicence이라는 추상 메서드를 추가하고 각 자식 라이선스가 해당 특정 유형의 라이선스에 특정한 논리를 구현하게합니다. 이렇게하면 비즈니스 로직을 데이터와 함께 배치하므로 anemic domain model을 피할 수 있습니다.

이 방법은, 당신의 방법의 구현은 단지 것 : 당신이 할 수 있도록

private void ValidateSubscriptionLicenceProducts(SubscriptionLicence licence) 
{ 
    if(!licence.ValidateProducts()) 
     throw new Exception("Failed to validate products"); 
} 

또한, 기본 클래스에서의 메소드 추상적함으로써, 당신은 방법을 구현하기 위해 각 "자식 라이센스를"시행 아무것도 확인할 필요가 없습니다. 따라서 나중에 새로운 유형의 라이센스가 추가 되더라도 ValidateSubscriptionLicenceProducts 메소드를 변경할 필요가 없습니다.

희망적입니다.

+0

멋진 아이디어입니다 ... –

0

PostSharp가 불평하지 않는다고 생각합니다. 오히려 FxCop.