此方法:
boolean containsSmiley(String s) {
if (s == null) {
return false;
}
else {
return s.contains(":)");
}
}
可以等同地写成:
boolean containsSmiley(String s) {
if (s == null) {
return false;
}
return s.contains(":)");
}
根据我的经验,第二种形式更常见,特别是在更复杂的方法中(可能有几个这样的退出点),“throw”和“return”也是如此。然而,第一种形式可以说使代码的条件结构更加明确。是否有理由更喜欢一个而不是另一个?
答案 0 :(得分:87)
在这种情况下else
将是多余的,并为函数的主代码创建不必要的额外缩进。
答案 1 :(得分:66)
根据我的经验,这取决于代码。如果我'防范'某事,我会做:
if (inputVar.isBad()) {
return;
}
doThings();
重点很明确:如果该陈述为假,我不希望该函数继续。
另一方面,有一些函数有多个选项,在这种情况下我会这样写:
if (inputVar == thingOne) {
doFirstThing();
} else if (inputVar == secondThing) {
doSecondThing();
} else {
doThirdThing();
}
即使它可以写成:
if (inputVar == thingOne) {
doFirstThing();
return;
}
if (inputVar == thingTwo) {
doSecondThing();
return;
}
doThingThree();
return;
这真的归结为哪种方式最清楚地显示代码正在做什么(不一定代码的哪一部分最短或压痕最少)。
答案 2 :(得分:32)
这是一种名为Guard Clause的模式。我们的想法是预先进行所有检查,以减少嵌套条件,从而提高可读性。
从链接:
double getPayAmount() {
double result;
if (_isDead) {
result = deadAmount();
} else {
if (_isSeparated) {
result = separatedAmount();
} else {
if (_isRetired) {
result = retiredAmount();
} else {
result = normalPayAmount();
}
}
}
return result;
}
使用Guard子句,您将看到此结果:
double getPayAmount() {
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired) return retiredAmount();
return normalPayAmount();
};
答案 3 :(得分:8)
你会看到这一切:
if (condition) {
return var;
}
// by nature, when execution reaches this point, condition can only be false,
// therefore, the else is unnecessary
return other_var;
大多数情况下,在这种情况下添加else子句不仅是不必要的,而且很多时候,它会被编译器优化。
想想计算机如何看待这个代码(就机器代码而言,为了演示目的简化为伪代码):
0x00: test [condition]
0x01: if result of test was not true, goto [0x04]
0x02: push [var] onto stack
0x03: goto [0x05]
0x04: push [other_var] onto stack
0x05: return from subroutine
代码(再次,这是一个伪代码而不是汇编)对if/then/else
条件的行为完全相同。
return (condition) ? var : other_var;
这简化了代码,并且不会创建任何新的退出点。
答案 4 :(得分:7)
我更喜欢这样写:
boolean containsSmiley(String s) {
return s != null && s.contains(":)");
}
答案 5 :(得分:4)
我更喜欢第一种选择,因为它更具人性化。
作为类比,比较接下来的两句话:“如果今天下雨,那就带伞,否则带上太阳镜。”并且“如果今天下雨,那就带伞,带上太阳镜”。第一个句子对应于问题的第一个代码块,第二个句子对应于第二个。第一个更清晰可读,不是吗?
答案 6 :(得分:4)
与任何关于编码风格的“讨论”一样,没有正确的答案。我更愿意应用这些考虑因素:
代码是否在所有情况下都按预期工作。 (最少惊讶的原则)
下一位开发人员(我本人或其他人)可以了解它的作用和原因。
关于变更的代码有多么脆弱。
很简单,因为它需要而且不再存在。即没有超过或低于工程。
一旦我很高兴我对上述事情感到满意,其余的一般都会落到一线。
答案 7 :(得分:3)
其他人可能已经注意到了这一点,但我建议不要在通常需要字符串的地方使用空值。如果您确实需要检查以防止有人传递空值,您可以使用断言(在开发时)或单元测试(部署):
boolean containsSmiley(String s) {
assert s != null : "Quit passing null values, you moron.";
return s.contains(":)");
}
我已经改为一般的经验法则:从不。永远。传递空值,除非外部API调用明确要求它。第二:如果外部方法可能返回空值,请将其替换为合理的非空值(例如空字符串)或添加一个整齐的检查。我厌倦了重复的if (thing == null)
检查。
但这有点偏僻。我喜欢把短条件放在顶部和保护条款上,如果程序流程规定它永远不会到达那里,那么就删除它们。
答案 8 :(得分:2)
if
语句正在检查/强制执行您未收到空值的合同/期望。出于这个原因,我宁愿把它与函数的其余部分分开,因为它与你想要完成的事情的实际逻辑没有任何关系(虽然这种情况非常简单)。
但在大多数情况下,我更喜欢代码在其意图中尽可能明确。如果您可以对某些功能进行重组以使其对其他人更具可读性,那就去做吧。作为一名专业程序员,您的目标应该是为那些必须在您之后维护代码的人(包括2年后的自己......)进行编程。你能做些什么来帮助他们是值得的。
答案 9 :(得分:2)
因为它更好。你知道你也可以使用'{''}'来创建几个级别的嵌套,但是没有人真正做到这一点。
答案 10 :(得分:2)
Occam's Razor的原则是“实体不得超越必要性。”
答案 11 :(得分:2)
这是宗教争论,在一天结束时并不重要。我甚至认为第一种形式在某些情况下更具可读性。如果您在if-elseif-elseif-else
中有大量代码,乍看之下就更容易看到默认返回值。
if (s == null) {
return false;
}
else if (s.Contains(":))")) {
return true;
}
else if (s.Contains(":-(")) {
return false;
}
return s.contains(":)");
答案 12 :(得分:2)
else
是多余的。此外,一些IDE(Eclipse)和分析工具(可能是FindBugs)可能会将其标记为警告或错误,因此在这种情况下,程序员可能会将其删除。
答案 13 :(得分:0)
如您所见,不同的人对可读性有不同的看法。有些人认为较少的代码行会使代码更具可读性。其他人则认为第二种形式的对称性使其更具可读性。
我的看法可能是,两种观点都是正确的......对于持有它们的人来说。结果是你不能编写每个人都发现最佳可读性的代码。因此,最好的建议是遵循您的强制编码标准所要做的事情(如果它对此有所说明)并且通常使用您的常识。 (如果你背负着一些强烈的吵闹声,坚持认为他的方式是“正确的”......只需顺其自然。)
答案 14 :(得分:0)
虽然有一个else是正确的,并且在逻辑和运行性方面没有任何问题,但是当函数在if / else范围之外没有return语句时,我喜欢避免最初的WTF时刻。
答案 15 :(得分:0)
因为在这种情况下使用了else,所以在eclipse中有一个可选的(默认关闭)警告;)。
答案 16 :(得分:0)
嗯,有些原因只是惯例,但上面的表格有一个优点......
在编写return语句时,通常会将最后一个语句设为默认返回值。这主要有助于重构 - 否则子句往往会被包裹在其他结构中,或者可能会意外地被移动到树中更深处。
答案 17 :(得分:0)
从维护角度来看,我更喜欢一个退出点。最终结果可以在一个出口点而不是n个出口点进行修改(或修饰)。
答案 18 :(得分:0)
第二种形式,如果更简单/更短。这并不总是意味着更清楚。我建议你做你觉得最清楚的事。我个人会写。
static boolean containsSmiley(String s) {
return s != null && s.contains(":)");
}
答案 19 :(得分:0)
在我看来,第二个更有意义。它更像是一个“默认”动作,就像一个开关。如果它与任何其他退出点都不匹配,那么就这样做。那里你真的不需要别的东西。我会说如果整个函数只是if和elseif,那么其他就有意义,因为它是一个巨大的条件。如果有多个条件和其他函数在其中运行,那么将使用最后的默认返回。
答案 20 :(得分:0)
因为它与编写以下内容之一相同,它带来了程序员意图的证据:
boolean containsSmiley(String s) {
if (s == null) // The curly braces are not even necessary as the if contains only one instruction.
return false;
return s.contains(":)");
}
甚至这个:
boolean constainsSMiley(String s) {
return string.IsNullOrEmpty(s) ? false : s.Contains(":)");
}
这两种形式是:
答案 21 :(得分:0)
我认为可读性。如果您正在扫描代码屏幕以试图弄清楚代码的作用,那么这对开发人员来说是一个视觉提示。
...但它并不是真的需要,因为我们都很好地评论我们的代码,对吧? :)
答案 22 :(得分:0)
第一种形式只是不那么冗长 - 当你返回一个值时,你自动离开你所在函数的范围并返回给调用者,因此其后的任何代码只有在IF语句不能执行时才会执行评估为真,然后返回任何内容。