这是一个次要的样式问题,但是您添加到代码中的每一点可读性都很重要。
所以,如果你有:
if (condition) then
{
// do stuff
}
else
{
// do other stuff
}
你如何决定它是否更好,或者像这样:
if (!condition) then
{
// do other stuff
{
else
{
// do stuff
}
我的启发式是:
答案 0 :(得分:18)
我更喜欢把最常见的路径放在第一位,而且我坚信减少筑巢,所以我会在任何可能的情况下打破,继续或返回,而不是消磨。我通常更倾向于测试正面条件,或者将[和名称]负面条件反转为正面。
if (condition)
return;
DoSomething();
我发现通过大幅减少else的使用,我的代码更具可读性和可维护性,当我必须使用else时,它几乎总是一个更好的候选者,用于更结构化的switch语句。
答案 1 :(得分:4)
两个(矛盾的)教科书引用:
添加if / else的最短子句 在顶部
- 艾伦·霍洛布,“足够的绳索射击自己的脚”,p52
将正常情况放在if之后而不是在else
之后
- Steve McConnell,“Code Complete,2nd ed。”,p356
答案 2 :(得分:3)
这取决于你的流量。对于许多函数,我将使用前置条件:
bool MyFunc(variable) {
if (variable != something_i_want)
return false;
// a large block of code
// ...
return true;
}
如果我需要做每种情况,我会使用if (positive_clause) {} else {}
格式。
答案 3 :(得分:3)
如果代码是检查错误条件,我更喜欢先放置该代码,然后将“成功”代码放在第二位;从概念上讲,这将函数调用及其错误检查代码保持在一起,这对我来说是有意义的,因为它们是相关的。例如:
if (!some_function_that_could_fail())
{
// Error handling code
}
else
{
// Success code
}
答案 4 :(得分:3)
我同意Oli在可能的情况下使用积极的if条款。
请永远不要这样做:
if (somePositiveCondition)
else {
//stuff
}
我曾经在我工作的一个地方经常看到这个,并且常常想知道其中一个程序员是否不理解它是如何工作的......
答案 5 :(得分:3)
我更喜欢第一个。条件应该尽可能简单,并且应该是相当明显的,这更简单,条件和条件
答案 6 :(得分:3)
当我在查看数据验证时,我尝试将条件设为“白名单” - 也就是说,我会测试我接受的内容:
if DataIsGood() then
DoMyNormalStuff
else
TakeEvasiveAction
而不是反过来,往往会退化为:
if SomeErrorTest then
TakeSomeEvasiveAction
else if SomeOtherErrorCondition then
CorrectMoreStupidUserProblems
else if YetAnotherErrorThatNoOneThoughtOf then
DoMoreErrorHandling
else
DoMyNormalStuff
答案 7 :(得分:2)
我知道这并不是你想要的,但是......很多开发人员都使用了一个“保护条款”,即一个消极的“if”语句,它尽快打破了方法可能。那时,真的没有“别的”。
示例:
if (blah == false)
{
return; // perhaps with a message
}
// do rest of code here...
有一些硬核c / c ++ /汇编人员会告诉你,你正在摧毁你的CPU! (在许多情况下,处理器偏爱“真实”语句并尝试“预取”下一件事......所以理论上任何“假”条件都会刷新管道并且会慢几微秒。)
在我看来,我们正处于“更好”(更易理解)的代码胜过超过几秒的CPU时间。
答案 8 :(得分:2)
我认为对于单个变量,not运算符非常简单,命名问题开始变得更具相关性。
永远不要将变量not_X命名,如果需要使用同义词库并找到相反的变量。我见过很多可怕的代码,比如
if (not_dead) {
} else {
}
而不是显而易见的
if (alive) {
} else {
}
然后你可以理智地使用(非常易读,不需要反转代码块)
if (!alive) {
} else {
}
如果我们谈论更多变量,我认为最好的规则是简化条件。一段时间后项目往往会得到如下条件:
if (dead || (!dead && sleeping)) {
} else {
}
转换为
if (dead || sleeping) {
} else {
}
始终注意什么条件以及如何简化它们。
答案 9 :(得分:2)
软件是知识捕获。你正在编码某人对如何做某事的知识。
软件应该适合问题的“自然”。如有疑问,请询问其他人并查看人们的实际说法和行为。
“普通”案件什么都不做的情况怎么样?那么
if( common ) {
// pass
}
else {
// great big block of exception-handling folderol
}
或者你这样做?
if( ! common ) {
// great big block of except-handling folderol
}
“永远积极”的规则并不是你想要的。您想要查看更像以下规则。
答案 10 :(得分:2)
如果两条路径中的一条很短(1到10行左右)而另一条路径很长,我会按照Holub rule mentioned here并将较短的代码放在if中。这使得在查看代码时更容易在一个屏幕上看到if / else流。
如果那是不可能的,那么我构造使条件尽可能简单。
答案 11 :(得分:1)
对我来说,这取决于条件,例如:
if (!PreserveData.Checked)
{ resetfields();}
我倾向于用我想要的逻辑与自己交谈,并将其编码为我脑子里的小声音。
答案 12 :(得分:1)
首先,让我们暂时放弃最好避免首先使用“其他”的情况(我希望每个人都同意这种情况确实存在并且确定此类情况可能应该是一个单独的主题)。
所以,我们假设必须有一个“else”子句。
我认为可读性/可理解性至少强加了三个关键要求或规则,不幸的是它们经常相互竞争:
第一个块(“if”块)越短,就越容易掌握整个“if-else”结构。当“if”块足够长时,很容易忽视“else”块的存在。
当“if”和“else”路径在逻辑上不对称时(例如“正常处理”与“错误处理”),在独立“if-else”构建它并不重要的是哪条路是第一条,哪条是第二条。但是,当多个“if-else”构造彼此接近时(包括嵌套),并且当所有那些“if-else”构造具有相同类型的不对称时 - 那就是当它是一致地安排那些不对称路径非常重要。
同样,对于所有人来说,它可以是“如果...正常路径......其他......异常路径”,或者“如果......异常路径......其他......正常路径”,但是它不应该是这两种变体的混合。
在所有其他条件相同的情况下,将正常路径放在第一位对大多数人来说可能更自然(我认为这更多是关于心理学而不是美学: - )。
一个以否定开头的表达式通常比没有否定的表达式更难阅读/理解。
因此,我们有三个相互竞争的要求/规则,真正的问题是:哪一个比其他更重要。对于Allen Holub来说,规则#1可能是最重要的规则。史蒂夫麦康奈尔 - 这是规则#2。但我认为你不能真正选择其中一条作为单一的准则。
我打赌你已经猜到了我的个人优先事项(从我订购上述规则的方式:-)。
我的理由很简单:
规则#1是无条件的,不可能规避。如果其中一个块太长而无法在屏幕上运行 - 它必须成为“其他”块。 (不,机械地创建函数/方法只是为了减少“if”或“else”块中的行数并不是一个好主意!我假设每个块已经具有逻辑上合理的强>最小线数。)
规则#2涉及很多条件:多个“if-else”结构,都具有相同类型的不对称性等等。所以它在许多情况下都不适用。
此外,我经常观察到以下有趣的现象:当规则#2适用时以及正确使用时,它实际上与规则#1不冲突!例如,每当我有一堆“if-else”语句具有“正常与异常”不对称时,所有“异常”路径都比“正常”路径短(反之亦然)。我无法解释这种现象,但我认为这只是良好代码组织的标志。换句话说,每当我看到规则#1和#2发生冲突的情况时,我就开始寻找“代码味道”,而且我经常会找到一些;重构后 - tada!规则#1和规则#2之间没有更痛苦的选择,:-)
最后,规则#3具有最小的范围,因此是最不重要的。
此外,正如其他同事所说的那样,通常很容易“欺骗”这条规则(例如,写“if(disabled),,,”而不是“if(!enabled)... “)。
我希望有人能对这一作品有所了解......
答案 13 :(得分:1)
如果您同时拥有真假条件,那么我会选择积极的条件 - 这可以减少混淆,一般来说我相信会让您的代码更容易阅读。
另一方面,如果您使用的是Perl等语言,特别是如果您的错误条件是错误条件或最常见的条件,您可以使用执行代码块的'unless'结构除非条件为真(即与if相反):
unless ($foo) {
$bar;
}
答案 14 :(得分:1)
英特尔奔腾分支预测预取“if”情况的指令。如果它跟在“else”分支之后:它具有刷新指令管道,导致停顿。
如果你非常关心表现:把最有可能的结果放在'if'条款中。
我个人把它写成
if (expected)
{
//expected path
}
else
{
//fallback other odd case
}
答案 15 :(得分:1)
您通常可以在不切换if / else块的情况下使条件为正。
更改
if (!widget.enabled()) {
// more common
} else {
// less common
}
到
if (widget.disabled()) {
// more common
} else {
// less common
}
答案 16 :(得分:0)
如果您必须有多个退出点,请先将它们放在一起并清除它们:
if TerminatingCondition1 then
Exit
if TerminatingCondition2 then
Exit
现在我们可以继续使用通常的东西了:
if NormalThing then
DoNormalThing
else
DoAbnormalThing
答案 17 :(得分:0)
我总是最有可能保持第一。
在Perl中,我有一个额外的控制结构来帮助它。 if的反转。
unless (alive) {
go_to_heaven;
} else {
say "MEDIC";
}
答案 18 :(得分:0)
!full == empty
)答案 19 :(得分:0)
你应该始终把最可能的案例放在首位。除了更具可读性之外,它更快。这也适用于switch语句。
答案 20 :(得分:0)
关于我如何设置if语句,我很可怕。基本上,我根据我正在寻找的东西进行设置,这导致一切都不同
if(userinput = null){
explodeViolently();
其他{
实际做的东西;
}
或许像是一样的东西
if(1 + 1 = 2){
做的事;
其他{
explodeViolently();
}
if / else语句的哪一部分实际上对我有用,这是我的坏习惯。
答案 21 :(得分:0)
作为一般规则,如果一个明显大于另一个,我将较大的一个放在if
块中。
答案 22 :(得分:0)
我通常把积极的结果(所以方法)放在开头,所以:
if(condition)
{
doSomething();
}
else
{
System.out.println("condition not true")
}
但是如果要使用的方法的条件必须为false,我会这样做:
if(!condition)
{
doSomething();
}
else
{
System.out.println("condition true");
}