代码重复与新变量创建

时间:2014-07-17 21:50:58

标签: java if-statement

寻找以下两个选项中的哪一个被认为是良好的编程习惯?

这是两个选项: 复制代码,但不创建新的变量/对象

if (a > b) {
  calcSum (a, b) + calcDiff(a, b);
} else {
   calcSum (b, a) + calcDiff(b, a);
}

VS

不会复制代码,但会创建新的变量/对象

int big;
int small

if (a > b) {
    big = a;
    small = b;
} else {
    big = a;
    small = b;
} 

calcSum (big, small) + calcDiff(big, small);

7 个答案:

答案 0 :(得分:2)

尽管其他人已经说过,我认为第二种选择是首选。重复业务逻辑会使测试难以维护,因此您应该寻找避免重复的方法。

另一种方法是将其作为辅助方法(calculateSumPlusDifference(int max, int min)),然后使用它:

if (a > b) {
  calculateSumPlusDifference(a, b);
} else {
  calculateSumPlusDifference(b, a);
}

这样你仍然可以在a和b周围获得紧凑的逻辑,但是你可以避免重复你的业务逻辑。

答案 1 :(得分:0)

我会说第一个选项更可取,因为它更紧凑并且不会创建新变量(虽然这不是一个很大的问题,但它可能会被优化掉)。

如果您愿意,也可以使用数学库的min和max方法在一行中完成所有操作。

答案 2 :(得分:0)

他们都工作。但是,你真的要知道什么更重要。可读性或效率?例如,有些人建议使用Math.max确定,这是有效的。但是,效率非常低。做任何类型的Math.都会产生许多额外的不必要的电话。但是,它更具可读性。所以我们回去问同样的问题。可读性或效率。

权衡您的选项,了解可维护,可读和高效的内容。最后,他们显然都会根据项目使用您的判断。

TDLR:如果需要在1毫秒内运行100次以上的代码行,那么如果只有一次实际线性运行代码,那么第二种方法就是可读性。

答案 3 :(得分:0)

我觉得这些答案都没有提到问题:重复代码或花费内存创建新变量以避免重复是否更好?

嗯,我们实际上可以将它用于测试,我们可以。

我写了一个类来运行你的两个示例,其随机值为ab(1到10之间),每次为100,000,000次。结果实际上非常有启发性:

//trial 1
Without Creating Variables: 2.220987762 seconds
vs With Creating Variables: 2.218305816 seconds

//trial 2
Without Creating Variables: 2.215427479 seconds
vs With Creating Variables: 2.220663639 seconds

//trial 3
Without Creating Variables: 2.345803733 seconds
vs With Creating Variables: 2.347936366 seconds

基本上,这两个选项在速度方面几乎没有差别 - 即使在运行它们一亿次时也是如此。

因此,在建立之后,代表最佳实践的选项变为使代码更易读和可理解的选项,这绝对是第二个。


如果您想亲自检查,请参加考试课程:

import java.util.Random;

public class Test {
    public static void main(String[] args) {
        int testLoops = 100000000;
        Random rand = new Random();

        //first test
        long startTime1 = System.nanoTime();

        for(int i=0;i<testLoops;i++) {
            int a = rand.nextInt(10)+1;
            int b = rand.nextInt(10)+1;
            int answer;

            if (a > b) {
                answer = calcSum (a, b) + calcDiff(a, b);
            } else {
                answer = calcSum (b, a) + calcDiff(b, a);
            }
        }

        double seconds1 = (double)(System.nanoTime() - startTime1) / 1000000000.0;
        System.out.println("Without Creating Variables: " + seconds1 + " seconds");

        //second test
        long startTime2 = System.nanoTime();

        for(int i=0;i<testLoops;i++) {
            int big;
            int small;
            int a = rand.nextInt(10)+1;
            int b = rand.nextInt(10)+1;
            int answer;

            if (a > b) {
                big = a;
                small = b;
            } else {
                big = a;
                small = b;
            } 
            answer = calcSum (big, small) + calcDiff(big, small);
        }

        double seconds2 = (double)(System.nanoTime() - startTime2) / 1000000000.0;
        System.out.println("   With Creating Variables: " + seconds2 + " seconds");
    }

    public static int calcSum(int a, int b) {
        return a+b;
    }

    public static int calcDiff(int a, int b) {
        return a-b;
    }
}

答案 4 :(得分:0)

在您提供的示例中,差异可以忽略不计,指的是速度和可读性。

显然是“伪”代码,否则我会建议像

这样的方法
void calcBoth(int a, int b) { 
    calcSum(a,b)+calcDiff(a,b); 
}

// Call:
if (a < b) calcBoth(a,b);
else       calcBoth(b,a);

也许这样的事情也适用于你的情况。

答案 5 :(得分:0)

我的功能程序员纯粹主义者可能会建议:

public int calc(int a, int b) {
    return (a >= b)
            ? calcSum(a, b) + calcDiff(a, b)
            : calc(b, a);
}

以一次递增为代价,您已经消除了所有临时变量并简明扼要地陈述了您的意图。

高效的编译器甚至可以识别尾递归并替换正确的尾递归避免机制。

答案 6 :(得分:0)

我更喜欢第二种,因为它更容易看到你的意图,但我会重写calcDiff,以便参数的顺序无关紧要。

public int calcDiff(int a, into b) {
    if (a > b)
        return a - b;
    else
        return b - a;
}

据推测,calcSum中的顺序无关紧要。

public int calcSum(int a, int b) {
    return a + b;
}

然后您需要的只是calcSum(a, b) + calcDiff(a, b)

但作为更一般的规则,如果提高可读性,我不怕创建新变量。它通常不会对速度产生太大影响。