寻找以下两个选项中的哪一个被认为是良好的编程习惯?
这是两个选项: 复制代码,但不创建新的变量/对象
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);
答案 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)
我觉得这些答案都没有提到问题:重复代码或花费内存创建新变量以避免重复是否更好?
嗯,我们实际上可以将它用于测试,我们可以。
我写了一个类来运行你的两个示例,其随机值为a
和b
(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)
。
但作为更一般的规则,如果提高可读性,我不怕创建新变量。它通常不会对速度产生太大影响。