编程首选项 - 使用具有多个return语句的else ifs?

时间:2010-08-26 22:04:48

标签: java language-agnostic preferences

代码:

public String getTemperatureMessage(double temp)
{
    if(temp < 32)
        return "Freezing";
    else if(temp < 60)
        return "Brr";
    else if(temp < 80)
        return "Comfortable";
    else
        return "Too hot";
}

关于上面的代码片段,else ifs在技术上是多余的,并且根本不会改变行为。但是,我倾向于把它们放在那里强调条件是排他性的。你的想法是什么?不必要或更清楚?

16 个答案:

答案 0 :(得分:10)

特殊情况中唯一可行的替代方法是获取条件运算符?:

public String getTemperatureMessage(double temp) {
    return temp < 32 ? "Freezing"
         : temp < 60 ? "Brr"
         : temp < 80 ? "Comfortable"
         : "Too hot";
}

留下问题,这对初学者来说是多么可读。

参考

相关问题

答案 1 :(得分:9)

这取决于许多事情,比如你的代码有多复杂。通过这样一个简单的例子,我将返回与ifs放在同一行,而不是使用elses。结构和行为很明确:

public String getTemperatureMessage(double temp)
{
    if(temp < 32) return "Freezing";
    if(temp < 60) return "Brr";
    if(temp < 80) return "Comfortable";
    return "Too hot";
}

当我有更复杂的代码时,我发现不使用return或continue / break从嵌套中分离,而是分配给状态或结果变量是有用的。然后,我将包括{},即使该块是单个语句,主要是为了保持结构在代码中的表示方式的一致性,还要稍微降低后续编辑将忘记将语句更改为块的风险。

如果这个例子比较复杂,我可能会这样编码:

public String getTemperatureMessage(double temp) {
    String result;
    if(temp < 32) {
        result = "Freezing";
    } else {
        if(temp < 60) {
            result = "Brr";
        } else {
            if(temp < 80) {
                result = "Comfortable";
            } else {
                result = "Too hot";
            }
        }
    }
    return result;
}

答案 2 :(得分:8)

如果函数有多个“成功”返回值,我将使用if / else在它们中进行选择。如果一个函数具有正常的返回值,但是一个或多个可能异常退出的方法,我通常不会对正常路径使用“else”。例如,我认为更自然地说:

int do_something(int arg1)
{
  if (arg1 > MAX_ARG1_VALUE)
    return ARG1_ERROR;
  ... main guts of code here
  return 0;
}

而不是说:

int do_something(int arg1)
{
  if (arg1 > MAX_ARG1_VALUE)
    return ARG1_ERROR;
  else
  {
    ... main guts of code here
    return 0;
  }
}

int do_something(int arg1)
{
  if (arg1 <= MAX_ARG1_VALUE)
  {
    ... main guts of code here
    return 0;
  }
  else
    return ARG1_ERROR;

如果存在多种可能“出错”的事情,例如

,这种区别就变得尤为重要
int do_something(int arg1)
{
  if (arg1 > MAX_ARG1_VALUE)
    return ARG1_ERROR;
  ... some code goes here
  if (something_went_wrong1)
    return SOMETHING1_ERROR;
  ... more code goes here
  if (something_went_wrong2)
    return SOMETHING2_ERROR;
  ... more code goes here
  if (something_went_wrong3)
    return SOMETHING3_ERROR;
  return 0;
}

在这种情况下嵌套的'if / else'语句会变得很难看。这种方法最重要的警告是必须明确给出早期退出的任何清理代码,否则必须使用包装函数来确保清理。

答案 3 :(得分:7)

有人会说多重回报就是问题所在。但这不是我的观点。

对于我的观点,if / else if非常重要,因为即使在你的情况下你会返回一些值,删除elses也意味着你不会把它们放在一边,这意味着完全不同如果回报不在这里的话。

另外,想象有一天有人想要编辑你的代码,并清理它以便一次返回,这个人可能会误解你的代码并犯下这样一个严重的错误:

public String getTemperatureMessage(double temp){
    String message;
    if(temp < 32)
        message = "Freezing";
    if(temp < 60)
        message = "Brr";
    if(temp < 80)
        message = "Comfortable";
    else 
        message = "Too hot";
    return message;
}

为了澄清我的观点,保留其余,它会让您的代码保持清晰。

答案 4 :(得分:2)

对于简单的1-liners,我倾向于忽略else但是如果有更复杂的if块,我倾向于更喜欢else来明确条件是相互排斥的

答案 5 :(得分:1)

public String getTemperatureMessage(double temp)
{
    String retval = null;
    if(temp < 32)
        retval = "Freezing";
    else if(temp < 60)
        retval = "Brr";
    else if(temp < 80)
        retval = "Comfortable";
    else
        retval = "Too hot";
    return retval;
}

答案 6 :(得分:1)

对于一个简单的if语句,没有太多代码行有多个返回是没有问题的。然而,没有什么能让我感到非常愤怒:

function doTemperatureCalculations(double temperature) {
  if (temperature < 20) {
    /* 
      Gazillion lines of code here .....
     */
    return "Very cold!";
  } else if (temperature < 40) {
    /*
      Another gazillion loc .....
     */
    return "Summer in the North Pole.";
  } else {
    /*
      Multiple returns embedded throughout ....
     */
  }
}

答案 7 :(得分:1)

在这种情况下,它更清楚。在一般情况下,您可能希望关闭它们,因为它们可能会导致更多嵌套和代码复杂性。例如:


if (error condition) {  
  do some stuff;
  return;
} else {
  do stuff;
  if (other error condition) {
     do some stuff1;
     return;
  } else {
     do some other stuff;
     return

  }
}

下面的代码可以保持嵌套级别,从而降低代码复杂性:


if (error condition) {
  do some stuff;
  return;
}
do stuff;
if (other error condition) {
  do some stuff1;
  return;
}
do some other stuff;
return;

在你的例子中,这很容易。但在许多情况下,最好使用查找表来处理这类事情并从文件/数据库中读取值。为了提高C的效率,通常将其编码为结构数组。

其他确实增加了一些清晰度,因为它清楚地表明案例是互斥的。然而,像你这样回归的习惯对许多程序员来说是显而易见的,所以无论哪种方式,大多数人都会知道你的意思。

我可以想到其他人的优势。如果你想添加一个新的最后一个案例,如果你想在120或者什么地方添加“Dying”,你可能会忘记将if添加到当前的“Too Hot Condition”。你知道你需要最后的其他人才能在“死亡”面前,所以你更有可能考虑把别人放在“太热”的面前。此外,如果你只是在“死亡”上放一个其他的,你会得到一个编译错误,迫使你思考。

答案 8 :(得分:1)

就个人而言,我认为else是不必要的。由于这个问题被标记为[language-agnostic],我将提供一些如何编写它的例子:

def temperature_message(temp)
  return 'Freezing'    if temp < 32
  return 'Brr'         if temp < 60
  return 'Comfortable' if temp < 80
  'Too hot'
end

这是典型的保护条款风格,我个人和Ruby社区一般都经常使用。

def temperature_message(temp)
  case
  when temp < 32
    'Freezing'
  when temp < 60
    'Brr'
  when temp < 80
    'Comfortable'
  else
    'Too hot'
  end
end

这是一个典型的switch,就像你在一些不那么强大的语言中找到它一样。这可能是我使用的,我会像这样重构它:

def temperature_message(temp)
  case temp
  when (-1.0/0.0)...32
    'Freezing'
  when 32...60
    'Brr'
  when 60...80
    'Comfortable'
  else
    'Too hot'
  end
end

虽然我必须承认我仍然觉得第一个最容易阅读。

由于这基本上是一个映射表,我会尝试将其格式化,以便每个读取代码的人立即看到“table-ness”:

def temperature_message(temp)
  case temp
  when (-1.0/0.0)...32 then 'Freezing'
  when         32...60 then 'Brr'
  when         60...80 then 'Comfortable'
                      else 'Too hot'
  end
end

这也适用于您的原始Java实现:

public String getTemperatureMessage(double temp) {
    if(temp < 32) return "Freezing";
    if(temp < 60) return "Brr";
    if(temp < 80) return "Comfortable";
    else          return "Too hot";
}

当然,因为 基本上是一个映射表,所以你也可以将它作为一个映射来实现:

def temperature_message(temp)
  {
    (-1.0/0.0)...32       => 'Freezing',
            32...60       => 'Brr',
            60...80       => 'Comfortable',
            80..(1.0/0.0) => 'Too hot'
  }.detect {|range, _| range.include?(temp) }.last
end

答案 9 :(得分:1)

多余的瑕疵使我感到畏缩。额外的语法和缩进使我更难阅读。我刚刚从我继承的一些代码中删除了一堆这些。

大多数冗余代码都是错误的,所以即使你故意把它放在那里,多余的'else'对我来说也是一个错误。我得到的印象是最初编写的没有嵌入式返回的代码,然后有人重写它以获得嵌入式返回,但是他们懒得去除其余部分。

单个if / return易于理解;所以是连续四个。这是“那种情况已经完成;让我们继续前进”。一连串的if / elses可能是一种痛苦的阅读;在你发现发生了什么之前,你需要一直读到底部。节省的优点是它允许使用单个返回 - 一个被IMO高估的功能但我承认它确实提供了一些价值。然而,长期的一系列if / elses与收益混合在一起是两个世界中最糟糕的 - 多重回报的所有缺点,并且看起来像一个大的构造,你必须立刻进入你的头脑中。啊。

从理论角度考虑:返回和else之间的区域本质上是无法访问的代码。当然,它只包含空格,但该区域根本不应该存在。

最后,将if / return / else作为其冗余结论的一个例子。我最近见过其中一些。为什么世界上还有其他块呢? else块中的代码在与其后面的代码相同的条件下执行:

...
if (temp < 35)
{
  foo.status = TOO_COLD;
  return;
}
else
{
  foo.status = TEMP_OKAY;
}
launch_the_rocket(now);
return;

答案 10 :(得分:0)

我同意其他人更清楚。最后的其他特别有助于在每个分支都有一个返回的情况和只有一些分支有一个返回的情况(可能是一个气味)之间进行视觉区分。

答案 11 :(得分:0)

没有意义。你正在添加不必要的语义和其他开销,以获得绝对零利益。当你返回时,你返回并控制结束。假装其他任何东西都是多余的,只是让你看起来不知道返回陈述的作用。

答案 12 :(得分:0)

谁可以使用IF / ELSE IF ...何时可以使用SWITCH语句?

我的偏好是单个RETURN语句 - 多个return语句可以使调试变得痛苦......

答案 13 :(得分:0)

我认为我不会首先以这种方式编写,但是与前提一致,我猜测任何编译器都会根据您选择的方法编写相同的代码,因此存在没有任何技术上的理由让我认为会有利于其他人。

因此,参数是Single或Compound语句。

我认为应该使用“最少意外”的规则,在这种情况下会要求包含多余的其他声明。

PS。我会一直发送摄氏温度,哎呀,只是打破了你的功能!

答案 14 :(得分:0)

很好。没有“其他”,这一行

if(temp < 80)
    return "Comfortable";

会令人难以置信。对于“其他”,很明显还有其他先决条件。

答案 15 :(得分:0)

我自己更喜欢案例陈述,但这会使这成为特定于语言的主题,而不是与语言无关的主题。

    Dim Temp As Integer
    Dim Message As String

    Select Case Temp
        Case Is < 32
            Message = "Freezing"
        Case Is < 60
            Message = "Just Right"
        Case Is < 80
            Message = "Too Hot"
        Case Else
            Message = "What was I doing?"
    End Select

我发现这些很容易阅读if..else语句。