2011-07-29 135 views
4

我有以下几种方法:什么是避免这种重复代码的最佳方式

public int CountProperty1 
    { 
     get 
     { 
      int count = 0; 
      foreach (var row in Data) 
      { 
       count = count + row.Property1; 
      } 
      return count ; 
     } 
    } 

    public int CountProperty2 
    { 
     get 
     { 
      int count = 0; 
      foreach (var row in Data) 
      { 
       count = count + row.Property2; 
      } 
      return count ; 
     } 
    } 

什么是为了避免重复,这里和共享的代码量可能

+1

您可以使用LINQ吗? – oleksii

+0

值得一提的是,您的实现是Sum()而不是Count()? –

回答

10

如何用最好的方式LINQ和Sum扩展方法?

public int CountProperty1 
{ 
    get { return Data.Sum(r => r.Property1); } 
} 

如果这不是一个选项,你可以重构出逻辑到自己和方法:

public int CountProperty1 
{ 
    get 
    { 
     return CountProperty(r => r.Property1); 
    } 
} 

public int CountProperty2 
{ 
    get 
    { 
     return CountProperty(r => r.Property2); 
    } 
} 

private int CountProperty(Func<Row,int> countSelector) 
{ 
    int count = 0; 
    foreach (var row in Data) 
    { 
     count = count + countSelector(row); 
    } 
    return count ; 
} 

备注最后一个例子:我做了“行”类型,如从你的例子中看不出来。用适当的类型替代。

+1

这具有减少代码的优点,因此重复不是一个问题。 –

+1

快速计数,您会发现重构后的代码与原始代码具有完全相同的行数,更复杂且执行速度更慢。这不是重构好处的好例子! (不包括Data.Sum()优秀的推荐) –

+0

@Steve,我也赞成Sum()解决方案,我只是想提供一个例子,说明它如何以更一般的术语来重构这样的问题 - 也,他的代码库中的两个示例属性可能不止两个看起来相同。 – driis

2

不要打扰。

您可以缩短代码,但如果您尝试重构它以消除重复,则只会使代码更复杂。

将您的重构工作集中在更复杂和值得的案例上。人生太短...

几个字节的磁盘空间是极其便宜的,复制/粘贴是开发人员最好的朋友。另外,如果我们正在对它进行纯化,请考虑重构的运行时间开销。

+3

我强烈反对。虽然你的观点在某些情况下可能是有效的,但这是非常明显的代码重复,可以很容易地分解给一个简单的帮助者,它肯定值得对付重复。 – driis

+1

我的观点是,代码重复时很重要。你的CountProperty方法是更复杂的一个数量级,只有少数几行代码。简单性和冗长性之间的折衷并不总是直截了当的。 –

+1

@Steve - 我同意你100% - 但是,我会补充说,这些应该是方法而不是属性。 –

-2

给它说的输入参数,其参数

public int CountProperty (int whichProperty) 
    { 
     get 
     { 
      int count = 0; 
      foreach (var row in Data) 
      { 
       if(whichProperty = 1) 
        count = count + row.Property1; 
       if(whichProperty = 2) 
        count = count + row.Property2; 
      } 
      return count ; 
     } 
    } 
+0

似乎更像你是移动问题,而不是解决它...不是我的投票,虽然 – musefan

-2
public int CountProperty1 
{ 
    get 
    { 
     return GetCount(row.Property1); 
    } 
} 

public int CountProperty2 
{ 
    get 
    { 
     return GetCount(row.Property2); 
    } 
} 

private int GetCount(object property) 
{ 
    int count = 0; 
    foreach (var row in Data) 
    { 
     if(property == row.Property1) 
     { 
      count = count + row.Property1; 
     } 
     else if (property == row.Property2) 
     { 
      count = count + row.Property2; 
     } 
    } 
    return count ; 
} 
在i的签名时所使用的对象的pribvate方法

- 直到我有需要的属性的类型的更好knowelege

2

可能不是你正在寻找的答案,但这不一定是重复。有时候会有一种误解,如果两个不同的函数看起来是一样的,那么它们应该被重构以去除重复。在我的愚见中,这是错误的。

这只是重复,如果他们是真正的复制和identicial或近乎相同的概念。因为它是重复的(至少应该删除重复),它不仅仅是它们碰巧使用相同的代码,而是出于同样的原因使用相同的代码。

这可能只是因为你发布的样本,但它很简单。尽管这两个属性的实现是相同的,但必须有一些有效的商业原因,即您拥有这两个属性,否则最简单的答案就是一起删除第二个属性。然而,如果你真的有两个属性,而且他们看起来现在看起来一样,那并不意味着他们在未来的功能性上不会出现分歧(这是可以的)。

这个想法是尽量减少复杂性和维护成本。只有当你的代码有意义并且模型是现实的时候,你才能做到这一点,但是如果通过将看起来相似的事情汇集在一起​​,引入了错误的比较,那么就不能这样做。

http://mooneyblog.mmdbsolutions.com/index.php/2010/07/30/reusable-code-is-bad/

1

我不会理会的属性个人,只是直接调用超出使用LINQ

myObject.Data.Sum(x=>x.Property1) 
+0

这正是,你应该用Data.Sum(x => x.Property1)替换CountProperty1 属性的每个调用。 –

0

这是相当干净。如果我知道行的类型,我会倾向于把PropertyN()放到它的类中,而不是在这里,但缺乏这方面的知识:

public int CountPropertyN(int n) 
{ 
    int count = 0; 
    foreach (var row in Data) 
    { 
     count = count + PropertyN(row, n) 
    } 
    return count ; 
} 

private int PropertyN(var row, int n) 
{ 
    if (n == 1) return row.Property1; 
    else return row.Property2; 
}