例如,当我在我的代码上运行ReSharper时:
if (some condition)
{
Some code...
}
ReSharper给了我上面的警告(反转“if”语句以减少嵌套),并建议以下更正:
if (!some condition) return;
Some code...
我想知道为什么这样更好。我一直认为在方法中间使用“return”是有问题的,有点像“goto”。
例如,当我在我的代码上运行ReSharper时:
if (some condition)
{
Some code...
}
ReSharper给了我上面的警告(反转“if”语句以减少嵌套),并建议以下更正:
if (!some condition) return;
Some code...
我想知道为什么这样更好。我一直认为在方法中间使用“return”是有问题的,有点像“goto”。
当前回答
只在函数结束时返回的想法来自语言支持异常之前的时代。它使程序能够依赖于能够将清理代码放在方法的末尾,然后确保它会被调用,而其他程序员不会在方法中隐藏导致跳过清理代码的返回值。跳过清理代码可能导致内存或资源泄漏。
然而,在支持异常的语言中,它不提供这样的保证。在支持异常的语言中,任何语句或表达式的执行都可能导致导致方法结束的控制流。这意味着清理必须通过使用finally或使用关键字来完成。
不管怎样,我想说的是,我认为很多人引用了“只在方法末尾返回”的指导原则,却不理解为什么它是一件好事,而减少嵌套以提高可读性可能是一个更好的目标。
其他回答
在我看来,如果你只是返回void(或一些你永远不会检查的无用的返回代码),那么早期返回是很好的,它可能会提高可读性,因为你避免了嵌套,同时你显式地表明你的函数已经完成。
如果你实际上返回一个returnValue,嵌套通常是一个更好的方式,因为你只在一个地方返回你的returnValue(在末尾),它可能会使你的代码在很多情况下更易于维护。
这是意见的问题。
我通常的方法是避免单行if,并在方法中间返回。
你不希望在你的方法中到处都是这样的行,但是在你的方法顶部检查一堆假设是有意义的,只有在它们都通过时才做实际的工作。
我想补充的是,这些倒置的if是有名称的-保护条款。我一有机会就用它。
我讨厌阅读一开始只有两屏代码的代码。只要求if的倒数,然后返回。这样就没人会浪费时间刷屏幕了。
http://c2.com/cgi/wiki?GuardClause
这里已经有很多有见地的答案,但是,我仍然想要指向一个稍微不同的情况:而不是前置条件,它实际上应该放在函数的顶部,考虑一步一步的初始化,在那里你必须检查每一步是否成功,然后继续下一步。在这种情况下,您不能检查顶部的所有内容。
当我使用Steinberg的ASIOSDK编写ASIO主机应用程序时,我发现我的代码真的难以阅读,因为我遵循了嵌套范式。它有8层深,我看不出有什么设计缺陷,正如Andrew Bullock上面提到的那样。当然,我可以将一些内部代码打包到另一个函数中,然后在那里嵌套剩余的级别以使其更具可读性,但对我来说这似乎相当随机。
通过用保护子句替换嵌套,我甚至发现了自己的一个误解,即一部分清理代码应该在函数的早期出现,而不是在函数的末尾。对于嵌套分支,我从来没有看到过,你甚至可以说它们导致了我的误解。
所以这可能是另一种情况,反向if可以有助于更清晰的代码。
我的想法是“在函数中间”的返回不应该那么“主观”。 原因很简单,以下面的代码为例:
function do_something( data ){ if (!is_valid_data( data )) return false; do_something_that_take_an_hour( data ); istance = new object_with_very_painful_constructor( data ); if ( istance is not valid ) { error_message( ); return ; } connect_to_database ( ); get_some_other_data( ); return; }
也许第一个“回报”不是那么直观,但这是真正的储蓄。 有太多关于干净代码的“想法”,只是需要更多的实践来摆脱他们“主观的”坏想法。