哪个是首选:嵌套If或退出子/功能?

时间:2012-07-09 12:03:20

标签: .net vb.net

最近我一直致力于传统的vb.net代码,在代码同行评审期间,建议不要使用Exit Sub / Function,而是将所有功能嵌套在IF语句中。

当我最初开始开发时,我习惯性地这样做(嵌入IF),不仅看起来更合乎逻辑,它似乎不那么令人困惑。

然而,在某些时候,我曾与一个将嵌套的IF视为“邪恶”的团队合作,因此我被告知退出子/函数是首选。我很确定他们制作了一些MS最佳实践材料来支持这一点。

所以这个问题适合经验丰富的开发人员,哪种方式真的首选?如果你给出答案,你也可以请说明你的消息来源,或者只是提到这是你的团队/公司/个人首选的偏好并给出理由。

提前致谢。

按要求编辑:代码示例

退出Sub:

Private Sub DoSomeWork()
 if not conditionMetFromAnotherFunction() then
      exit Sub 
 end if

 'Method work starts here
End Sub

嵌套IF:

Private Sub DoSomeWork()
 if conditionMetFromAnotherFunction() then
     'Method work starts here
 end if
End Sub

6 个答案:

答案 0 :(得分:22)

如果您没有提前退出功能,您将达到代码如下所示的位置:

stumble on code

没有人能告诉我这是一种比从功能早期返回更好的风格。

答案 1 :(得分:6)

  

在代码同行评审期间,建议不要使用Exit Sub / Function,而是将所有功能嵌套在IF语句中。

这是一个可怕的建议。就这么简单。忽略它。事实上,相反的情况通常是正确的,特别是在需要嵌套缩进的情况下,或者您检查参数的有效性并可能提前退出的情况:您问题中的代码就是一个很好的例子。 在这里使用提前退出。

没有“官方”来源(官方会是什么?)但是在优秀程序员中几乎达成共识,只有极少数人反对这一点。有关此内容的更多讨论,请参阅discussion on Programmers

但是,我建议使用Return代替Exit {Sub|Function}

答案 2 :(得分:4)

正如David在他的评论中指出的那样,嵌套if语句会增加代码的复杂性。

想象一下以下(简化)代码:

Private Sub DoSomeWork()
    if conditionMetFromAnotherFunction() then
        if conditionDependantUponPreviousCondition then
            ' Do the work
        end if
    end if
End Sub

或以下

Private Sub DoSomeWork()
    if not conditionMetFromAnotherFunction()
        return
    else if not conditionDependantUponPreviousCondition 
        return
    end if


    ' If we're here, everything's all good
    ' Do the work...
End Sub

如果您的条件变得更复杂,那么返回会让您更容易理解,在某些情况下,您的代码没有做任何事情,并使您的代码更具可读性。

否则,您必须阅读所有函数并在心理上解析嵌套的if,以确保没有做任何事情。

答案 3 :(得分:3)

与任何事情一样,"它取决于。"如果在错误的环境中使用,任何一方都会感到厌恶。

例如,什么是conditionMetFromAnotherFunction()检查?如果它正在检查DoSomeWork()所需的某种先决条件,那么我甚至可以通过异常而不是只是安静地退出该函数。例如,ArgumentException在检查传递给函数的参数的有效性时会很有用。如果系统中的某些东西确实是错误的,那么静静地退出似乎并不正确。

对于嵌套条件,肯定凌乱。请记住一个函数应该做一件事的经验法则。" 检查这个条件是一回事。因此,在这种情况下,'Method work starts here应该只是对另一个实际完成工作的方法的调用。它应该包含在一个大条件中的许多代码行。 函数名称应该准确反映它们正在做什么。所以这个是DoWorkIfConditional(在人为的例子中),另一个方法是DoWork

在工作之前检查前置条件的功能是可以的。如果没有满足前提条件,我会考虑抛出异常。但这取决于应用程序的实际逻辑,在这个例子中并没有真正传达。

答案 4 :(得分:2)

我建议您阅读答案here,以便对此主题进行详尽的综述。

总结:单一录入/单退出以您可以拥有多个功能入口点的语言开发,您还可以在代码中返回不同的位置。它被误解为只允许代码中的一个点,您可以从返回

在子程序中仅使用一个返回/退出语句的“最佳实践”来自具有显式堆管理的语言,其中子程序的资源在子程序结束时被释放,因此控制流需要通过通过那里。这不适用于基于.NET或JVM的语言。

总的来说,当您被允许使用多个返回时,代码通常更具可读性。

答案 5 :(得分:1)

IMO嵌套,如果是一个非常快速的溃败意大利面条代码。一般来说,如果您深度嵌套您的代码,那么您尝试在您的方法中做很多工作,并且很可能将从重构到较小的部分中受益。

话虽如此,有时候无法避免,所以没有一个答案适合所有人。