退出=意大利面条代码?

时间:2010-12-10 22:04:51

标签: vb.net coding-style

我一直被教导要从函数中退出并编写不会跳到那里的代码,是下面的错误代码还是有更好的方法来编写for循环而不需要“退出” ?

dim dt as datatable = FillDataTableFunction()
dim bWrite as boolean = false
for each row as datarow in dt.rows
  if row.item("somecolumn") <> string.empty then 
    bWrite = true
    exit for
  end if 
next

if bWrite then 
  'do stuff
end if

我想我只是认为这会通过for循环减少不必要的迭代但是由于某种原因它似乎是一个糟糕的编码实践。

10 个答案:

答案 0 :(得分:20)

“我一直被教导” - 在生活的某个阶段,人们开始学习而不是被教导: - )

不要将任何视为福音(即使是来自我 - 如果你不同意,请自己动手)。查看指南背后的为什么存在。

你被告知多个退出点不好的原因是因为它们经常导致难以遵循的代码。换句话说,用return语句填充的400行函数很难根据其行为进行分析。

您的小代码段不会受此影响。我遵循的准则是:如果您可以在编辑器中的单个屏幕上看到控制流,那就没问题了。而且,由于12行适用于我在过去二十年中使用的任何编辑器,因此您的代码非常易读。

事实上,我已经看到了“永远不会使用多个退出点”的人的代码,这些代码的可读性远远低于违反规则所产生的代码。它通常涉及多条件while语句,因此它们必须在多行中分解,并且仍然很难分析。

追求可读性。如果指南有帮助,请使用它们。如果没有,把它们扔出窗外。

答案 1 :(得分:8)

你所说的“意大利面条代码”是使用过去大量使用的旧关键字“goto”。 (例如:集会,GwBasic等)。

使用中断来退出循环结构和决策结构是非常自然的。

答案 2 :(得分:4)

您的代码段没有太大问题。

这可能更多的是品味问题,但我会把它放在一个单独的功能中:

Public Function ShouldWrite(ByVal dt As DataTable)
    For Each row As DataRow In dt.Rows
        If row.Item("somecolumn") <> String.Empty Then
            Return True
        End If
    Next
    Return False
End Function

或者,使用LINQ:

    Dim bWrite As Boolean = dt.AsEnumerable().Any(Function(row) row.Item("somecolumn") <> String.Empty)

答案 3 :(得分:2)

我明白这也被认为是一种不好的做法。但是,我认为不再认为这是不好的做法。事实上,我可以很容易地阅读你的代码:这是编写良好的程序的结束,我猜......

然而,还有一个步骤,任何人都可以更改以增强他/她的代码:在循环中,您试图找到具有匹配某些条件的项目的第一行。如果您编写更多“功能”方式(我不确切知道VB在这方面有什么设施,但它仍然是一个很好的设计考虑因素),请说:

bWrite = rows.exist(r | r.item("somecolumn") <> string.empty)

请注意整个循环如何在您要查找的内容的示意图中进行浓缩。这种“思维方式”我认为它比使用退出或复杂条件更重要...

答案 4 :(得分:2)

只有一个退出你的功能更多的是指导而不是硬性和快速的规则 - 做你喜欢的任何事情。我个人喜欢尽快归还。

你粘贴的代码对我来说看起来很好,而不是像意大利面一样 - 你的循环很短路,以避免在前100个中找到答案时必须循环100,000行。在这种情况下,我会说你的退出是完全合理的。

答案 5 :(得分:2)

除了特定命令的好坏之外,还有很多事情需要考虑。这在很大程度上取决于具体情况。

在一个像你的例子这样的简单代码中,使用exit可能比尝试将它放在循环逻辑中更具可读性。由于退出循环的代码非常接近它最终的位置,因此意大利面具有如此小的影响,以至于循环必须做多少更复杂的事情才能超越它。

如果有更多代码,可能很难跟随退出实际结束的位置以及对其余代码会产生什么影响,因此在这种情况下可能有一点需要保持一个出口点。

像exit这样的指令对它们有继承意义,因为它们会跳转到代码中的不同点,但如果跳转接近,它将不会比例如if语句更多地破坏流程。

需要考虑的另一件事是使用特定命令的频率。如果经常使用特定的构造,则更有可能理解它。

答案 6 :(得分:2)

Goto considered harmfull 在现代代码中看起来如此。

def func:

  while stuff:
    ...
    return False
    ...
  end
  return true

end

在上面你将这个函数全部放在循环之外 - 所以有两个退出点,一个不是你认为应该的位置。返回被“隐藏”在循环的其他行中,并且读者可能会错过。

答案 7 :(得分:2)

退出For是社会可接受的,因为它有效地将for循环留在底部。重要的是让代码易于理解,尤其是在您忘记今天所做的事情的几个月内。如果您养成使用Exit For的习惯,那么一眼就可以比任何其他离开循环的方法更容易识别。

答案 8 :(得分:2)

语言的许多“规则”(无论是人类语言还是计算机语言)都存在,因为那些对某些看起来很好而且看起来很蹩脚的人想要帮助别人写得好,并因此试图找出什么是“好”的东西不同于'icky'的东西。对于使某事好(或坏)的规则,不是坚持(或缺乏)。相反,事实上遵循规则的事情(希望)通常比那些不遵守规则的事情更好,这导致首先编写规则。

我不是非常热衷于“退出”;我倾向于认为在大多数情况下,for-next循环会提前退出,其他类型的循环会更好。尽管如此,有些地方早期退出For-Next循环“感觉”正确,所以我会使用它。如果期望循环将运行完成,我最倾向于提前退出for-next循环,但是为早期退出情况抛出异常会感觉不对。

答案 9 :(得分:2)

这是我开始工作的代码

bool someboolean = dt.AsEnumerable().Any(row => row.Field<string>("RowName") != "")