重构相关条件而不合并

时间:2011-12-01 19:25:49

标签: c# .net refactoring conditional pixel

我有一个像素/位置,我们在图表上称它为4,4。 我试图重构一个函数来检查它周围的像素是否符合某个标准,在所有8个方向(对角线,水平和垂直方向),如果符合该标准,采取一个共同的行动,有一个返回值。

例如:

int weight=0;
if (CheckWeight(new Point(4,4)) == true)
    weight +=100;
if (CheckWeight(new Point(4,5)) == true)
    weight +=10;
if (CheckWeight(new Point(4,3)) == true)
    weight +=10;
if (CheckWeight(new Point(5,5)) == true)
    weight +=10;
if (CheckWeight(new Point(3,3)) == true)
    weight +=10;
if (CheckWeight(new Point(3,4)) == true)
    weight +=10;
if (CheckWeight(new Point(5,4)) == true)
    weight +=10;
if (CheckWeight(new Point(5,3)) == true)
    weight +=10;
if (CheckWeight(new Point(3,5)) == true)
    weight +=10;

有没有一种很好的方法来重构这些,所以如果我必须在这里改变某些东西,比如功能我打电话来检查重量,或者我要检查的条件,或者体重增加,我是没有重复我的努力8次?

我有其他程序员,我知道已经建议在一张支票下合并,我显然不能这样做,因为它可能会满足其中3项检查,并给我一个分量这次是30分,其中5分,下次给我50分的重量。

编辑:此例程将在1920x1080像素地图上运行,因此数百万次;性能可能是重构中涉及的一个真正问题。

3 个答案:

答案 0 :(得分:3)

int weight = 0;
for (int dx = -1 ; dx <= 1 ; dx++) {
    for (int dy = -1 ; dy <= 1 ; dy++) {
        if (CheckWeight(new Point(4+dx, 4+dy))) {
            weight += (dx==0 && dy == 0) ? 100 : 10;
        }
     }
}

为了加快速度,您可以使用一个可爱的小技巧展开一个循环:

// Declare this in your class
static readonly int[] dd = new int{1,-1,-1,0,-1,1,0,1,1};

// Use this code to calculate the weight
int weight = CheckWeight(new Point(4, 4)) ? 100 : 0;
for (int i = 0 ; i != 8 ; i++) {
    if (CheckWeight(new Point(4+dd[i], 4+dd[i+1]))) {
        weight += 10;
    }
}

答案 1 :(得分:2)

for-loops怎么样?

int x = 4;
int y = 4;
int weight = 0; 
for (int dx = -1; dx <= +1; dx++) {
    for (int dy = -1; dy <= +1; dy++) {
        if (CheckWeight(new Point(x+dx, y+dy)))
            weight += 10;
    }
}

答案 2 :(得分:2)

一种可能的方法是将公共代码重构为for循环,迭代遍历目标附近的所有点。示例代码如下:

var target = new Point(4, 4);

int weight = 0;
if (CheckWeight(target) == true)
    weight += 100;

var points = GetNearestPointsFrom(target);

foreach (var p in points)
{
    if (CheckWeight(p) == true)
        weight += 10;
}

您需要实现GetNearestPointsFrom方法才能返回正确的点数。通过这种方式,您还可以封装逻辑,以便在单独的方法中断言最近的点,我发现它更易于维护。


更新: 考虑到您受到性能限制的限制,并且您提到可能需要通过另一个函数更改CheckWeight,我将验证是否将if检查包含在接受{{Predicate<Point>的方法中1}}和权重增量值不会对性能产生太大影响。这样改变CheckWeight方法或增量只执行一次。示例代码:

private static void GetWeight(Predicate<Point> predicate, int weightIncrement)
{
    int weight = 0;
    if (predicate(new Point(4, 4)) == true)
        weight += 100;
    if (predicate(new Point(4, 5)) == true)
        weight += weightIncrement;
    // ... Remaining checks ...
}