【问题标题】:Better Java method Syntax? Return early or late? [duplicate]更好的 Java 方法语法?早退还是晚退? [复制]
【发布时间】:2010-10-27 10:23:16
【问题描述】:

重复: Should a function have only one return statement?

通常,您可能有一个方法可以检查多个条件并返回一个状态(现在让我们说布尔值)。定义一个标志,在方法期间设置它,并在最后返回它更好吗:

boolean validate(DomainObject o) {
  boolean valid = false;
  if (o.property == x) {
     valid = true;
  } else if (o.property2 == y) {
     valid = true;
  } ...
  return valid; 
}

或者一旦知道方法的结果后直接返回更好/更正确?

boolean validate(DomainObject o) {

  if (o.property == x) {
     return true;
  } else if (o.property2 == y) {
     return true;
  } ...
  return false; 
}

现在显然可能有 try/catch 块和所有其他类型的条件,但我认为这个概念很清楚。意见?

【问题讨论】:

  • 只有一个属性有效才能使整个事物有效?
  • 这只是一个简单的例子。可能有许多有效属性的组合。但是你是从条件语句内部返回还是设置一个标志变量并且只在方法结束时返回,这是真正的问题。
  • 我同意这是重复的 - 但问题的结束有点矫枉过正,除非出于某种原因它们对社区有害。对于像这样的网站来说,就旧主题进行新的辩论似乎在范围之内。辩论不会转移到旧话题上。当我输入这个问题时,上述线程都没有出现在“可能重复的问题”列表中。

标签: java coding-style return-path


【解决方案1】:

如果这是一个您将调用数千次的方法,那么尽早返回更好地实现[略微]提高的性能。

如果不是,那么我更喜欢延迟返回,因为它提高了可读性。

请记住,程序员通常会花更多时间阅读而不是编写代码,因此您可以采取任何措施来提高可读性。

【讨论】:

  • 延迟返回如何更具可读性?对我来说,迟到是令人费解的。我从中推断,如果该方法没有返回,则该方法没有完成它需要做的事情。
  • 它更具可读性,因为您不会在它的中间切断流程。相反,您保存状态并在方法结束时返回。
  • 我发现标志的可读性较低,因为您必须完全遵循每个条件、方法调用等,才能知道其他人在返回之前是否触摸了标志,而使用另一种选择,您可以确定当 property 等于 x 时,无论那里发生什么,你都会得到 true。
  • 很明显,守卫代码是在 Java 中提前返回的好地方。您没有“在中间切断流程”,因为流程尚未开始,并且您避免将方法的主体包装在 if 块中。当然,有时在保护代码之后抛出异常是合适的。多个嵌套块是可读性的敌人,而不是提前返回(但如果你有多个嵌套块,提前返回会使情况变得更糟)。
【解决方案2】:

我更喜欢早点返回并避免深度嵌套。 尤其是在方法的开始是正确的:测试任何简单的东西,如果可以尽早退出(或抛出异常)。

如果它正好在一个方法的中间,它更像是一个判断调用。

请注意,我会立即重构您的示例以使用单个 if

boolean validate(DomainObject o) {    
  if (o.property == x || o.property2 == y) {
     return true;
  } ...
  return false; 
}

我意识到这只是一个玩具示例,但我的意思是,寻找更多简化代码的方法总是值得的 :)

【讨论】:

    【解决方案3】:

    与大多数编码风格一样,这确实是一个偏好问题,但guard clauses 被许多人认为是最佳实践。

    【讨论】:

    • 这不是保护条款的问题;这是根据参数返回不同值的问题。没有人谈论参数是对还是错,或者需要有先决条件。
    • @Seb:保护子句与前置条件相似,但不同。保护子句也不限于参数验证。在琐碎的情况下可以使用guard子句快速返回,导致多个返回点,这就是问题所在。
    【解决方案4】:

    我要说你绝对不应该提前返回的唯一一次是,如果你不能在一个屏幕上轻松地看到每个返回(无论标准对于使用相同代码库的人来说可能是什么),你应该在最起码要添加 cmets,表明如果有提前返回,函数可以提前返回。

    我要说你绝对应该早点回来的唯一一次是你的代码看起来像......

    boolean valid = true;
    if( condition1 ) {
       valid = false;
    }
    if( valid ) {
       ...
       if( condition2 ) {
          valid = false;
       }
    }
    if( valid ) {
       ...
       if( condition3 ) {
          valid = false;
       }
    }
    ... (etc)
    

    但是,如果您发现自己处于上述任何一种情况……您可能应该重构该函数。

    【讨论】:

    • 最后一行+1;如果函数太长,你确实应该使用更小的方法。
    【解决方案5】:

    对我来说,这是一种没有正确答案的宗教战争话题。反对提前返回的论点基本上归结为这样一个事实,即只有一个函数可以退出的点减少了通过代码的可能路径的数量,因此,至少在理论上,减少了错误的机会。我的个人风格是,在有必要提前返回的情况下,我会这样做。

    【讨论】:

      【解决方案6】:

      有两个因素相互影响。

      第一个因素是易于调试。如果立即返回(如第二个代码 sn-p 所示),有时很难调试大函数,因为很难找到这些返回语句,特别是如果它们被错误地放在那里。

      第二个因素是易于实施。如果您在函数开头检查参数的基本正确性,并且在函数完成之前有一段很长的代码,您可能必须将整个代码放入条件循环中。如果你不这样做,在某些时候,这个参数可能会被用于一些长时间的计算,浪费时间,因为它最终会被拒绝。

      所以,答案可能是这样的:

      If the function is small, 
              save the return status in a variable and return at the end. 
      else 
              return immediately.
      

      【讨论】:

        【解决方案7】:

        如果不包含异常,我宁愿在可能的情况下立即返回。

        标志变量管理不善很容易,我通常反对标志变量。不返回也可能使维护者认为可能会做进一步的工作(如果方法很长)。

        【讨论】:

          【解决方案8】:

          就个人而言,我更喜欢第二种方法。这对我来说直截了当,但我确实知道有些人在函数中必须只有一个返回值。

          【讨论】:

            【解决方案9】:

            老实说,我认为这取决于情况。就我个人而言,我会同时使用这两种方法,我会根据哪一种来使代码更清晰易读。

            如果您有大量嵌套的 if 语句(或任何其他控制结构)并且可能会让人感到困惑,那么我会在语句中返回

            在这种情况下,不要太担心什么是“最佳实践”,因为更重要的是代码清晰易懂。使用适合情况的方法。

            【讨论】:

              【解决方案10】:

              对于这种情况,我更喜欢:

              boolean validate (DomainObject o) {
                  if (o.property == x ||
                      o.property2 == y ||
                      ...) {
                        return true;
                  } else {
                        return false;
              }
              

              一般来说,我喜欢使用提前返回来处理错误情况,并在结束时返回来返回计算结果。

              【讨论】:

                猜你喜欢
                • 2014-11-22
                • 2013-02-23
                • 1970-01-01
                • 2021-10-06
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-02-27
                • 2014-09-30
                相关资源
                最近更新 更多