我是一名研究计算机科学的初学程序员,我多次被告知在循环中使用return语句不是一个好的编程习惯,应该避免。现在,我在Java库中阅读了很多代码来了解一切是如何工作的,我很惊讶地发现循环中的return语句无处不在。
有没有人可以解释为什么应该避免在循环中使用return语句?
谢谢!
答案 0 :(得分:7)
大多数人都喜欢看一个方法并假设一个退出点。当你在循环中间插入返回时,它会稍微分解一下流量,然后判断这个假设。这就是为什么许多人会提出“不干净”的论点。关于它真的没什么好看的,但它迫使程序的“人”读者深入挖掘方法,以更清楚地了解它的流程。你可以采取任何措施来减少精神演绎的人数,以理解你的逻辑流程,这是件好事。
如果我能够在没有阅读其内部结构的情况下浏览一种方法,同时全面了解它的作用以及它的存在,那么作者就做得很好。当一种方法最初意味着随着时间的推移而增长并迫使维护者在练习中精神上处理多个状态以理解它时,就会出现麻烦。
一个很好的例子是经典的保护条款,被一些人认为是好的做法。这是一种在继续之前检查状态或参数有效性的方法。如果给出了错误的方法,那么我们不想继续。看到这个假代码:
public void doSomethingCool(Object stuff) {
if(weWereNotExpectingThis(stuff)) return; //guard clause
while(somethingHappens()) {
doSomethingCool();
}
return;
}
有人过来说,“太酷了!我们可以在方法中使用return语句!”他们做出改变,然后变成:
public void doSomethingCool(Object stuff) {
if(weWereNotExpectingThis(stuff)) return; //guard clause
while(somethingHappens()) {
if(somthingHasChanged()) return; //because my team likes early exits, Yay!
else {
doSomethingCool();
}
}
return;
}
仍然不是太破旧,但是越来越多的变化进入并且你最终得到了这个:
public void doSomethingCool(Object stuff) {
if(weWereNotExpectingThis(stuff)) return; //guard clause
while(somethingHappens()) {
if(somthingHasChanged()) return;
else if(weDetectNewInput()) {
doSomethingCool();
} else {
doSomethingBoring();
if(weDetectCoolInput()) {
doSomethingCool();
continue;
}
return;
}
}
return;
}
现在你看到这是怎么回事。我们很难理解我们在哪里跳跃或者一眼就能发生什么。
答案 1 :(得分:6)
这一切都归结为“清洁代码”。这句话对不同的人意味着不同的东西。在方法的底部有一个return语句被认为是干净的;这是主观的。
也就是说,方法可以有多个return语句,但仍然被认为是干净的。这一切都取决于你和你的团队的宽容,更重要的是,你的高级开发人员认为干净。
当您跨越可接受的返回习惯和不可读/容易出错的代码之间的界限时,很难量化。一种安排如下的方法
method {
if(!x) return;
for(...) {
if (x && y) return
for(...) {
if (z) return;
}
}
if (a) return;
...
return;
}
无论你怎么看,都非常干净。
换句话说,太多的返回语句是代码气味,可能有问题的代码需要另外看
答案 2 :(得分:2)
长期以来不鼓励循环中的return语句是因为一个名为structured programming的范例,这基本上意味着程序中的执行流程应该简单,并且可以从任何地方轻松地执行。当时,GOTO仍然被广泛使用,并且正在制造代码可读性的噩梦;作为反对它的反对的一部分,经常说每个代码块应该只有一个出口点,唯一的跳转应该是条件分支,循环和函数调用。许多人仍然相信这一点,因此不喜欢循环中的break语句,异常和return语句。
我自己的观点是,能够理解所做的特定代码比能够遵循其确切的执行流程更重要。 (我经常使用functional语言编程,并尝试以函数式编写代码,即使我不是。)因此,我认为循环中的return语句很好。这最终只是品味问题。
答案 3 :(得分:2)
由于我还不能评论其他答案,我不得不发布一个新答案。我会非常小心地说任何哲学都“永远”正确。这都是权衡利弊。如果添加第二个return语句可以帮助您避免不必要地使用break语句和布尔标志来管理程序流,那么这可能是正确的做法。
然而,其他评论者在建议返回声明,中断和标志网是“代码味道”时是正确的 - 看看您的方法是否可以分解为更小,更模块化的部分。
答案 4 :(得分:1)
那些坚持“单一回归”宗教的人将竭尽全力彻底摆脱循环,设置标志以表明是时候回归了。
采取这种警告的最佳方法是考虑是否有充分的理由提前返回,或者是否表示考虑如何构建代码时的邋iness。
答案 5 :(得分:1)
如果目标是干净的代码和可读性,恕我直言最好的方法是在现场退出一个函数,即return
在满足条件的任何地方,而不是最后只有一个return
。
这在函数的简单例子中可能并不明显,但对于我来说真正复杂的函数,1)它更容易理解正在发生的事情2)它更容易阅读3)IMO它更少错误倾向 - 多次检测到错误并且需要尽快修复。如果最后保留一个return
,我已经多次看到“快速而肮脏”的修复可能会破坏代码。
但这是我个人的意见。
答案 6 :(得分:0)
在过去的日子里,它可能会使编译器和虚拟机混淆,而不再是这样,所以它通常是一种安全的做法。我认为人们也会做出一般性的“糟糕的做法”,即如果你是一个真正优秀的程序员,你会找到一种更优雅的方式去做同样的事情。
干杯
答案 7 :(得分:0)
我认为很多人认为它更清洁(和更安全的风格)的原因是;随着函数变得越来越复杂(它们经常在应用程序增长时执行),函数中间的退出点可能更难以跟踪,可能会变得混乱并且可能导致细微的错误。
与所有“规则”一样,有一些例外情况,其中函数中间的返回比等待到结束时可能导致的if(!error)块更清晰。