是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
是否有充分的理由说明在函数中只有一个return语句是一个更好的实践?
或者在逻辑上正确的情况下,可以从函数中返回,这意味着函数中可能有许多返回语句?
当前回答
为了实现良好的标准和行业最佳实践,我们必须在所有函数中建立正确的返回语句数量。显然,人们一致反对使用一个return语句。所以我建议把它设为2。
如果每个人现在都能检查一下他们的代码,找到任何只有一个出口点的函数,并添加另一个出口点,我将不胜感激。在哪里不重要。
这一变化的结果无疑将是更少的bug,更大的可读性和难以想象的财富从天而降。
其他回答
你知道有句谚语——情人眼里出西施。
有些人信得过NetBeans,有些人信得过IntelliJ IDEA,有些人信得过Python,有些人信得过PHP。
在一些商店,如果你坚持这样做,你可能会丢掉工作:
public void hello()
{
if (....)
{
....
}
}
这个问题完全是关于可见性和可维护性。
I am addicted to using boolean algebra to reduce and simplify logic and use of state machines. However, there were past colleagues who believed my employ of "mathematical techniques" in coding is unsuitable, because it would not be visible and maintainable. And that would be a bad practice. Sorry people, the techniques I employ is very visible and maintainable to me - because when I return to the code six months later, I would understand the code clearly rather seeing a mess of proverbial spaghetti.
嘿,伙计(就像一个前客户曾经说过的),做你想做的,只要你知道如何在我需要你解决它的时候解决它。
I remember 20 years ago, a colleague of mine was fired for employing what today would be called agile development strategy. He had a meticulous incremental plan. But his manager was yelling at him "You can't incrementally release features to users! You must stick with the waterfall." His response to the manager was that incremental development would be more precise to customer's needs. He believed in developing for the customers needs, but the manager believed in coding to "customer's requirement".
我们经常因为打破数据规范化、MVP和MVC边界而感到内疚。我们内联而不是构造函数。我们走捷径。
就我个人而言,我认为PHP是一种糟糕的实践,但我又知道什么呢?所有的理论争论都归结为试图满足一套规则
质量=精度,可维护性 和盈利能力。
所有其他规则都退居幕后。当然,这条规则永远不会消失:
懒惰是一种美德 程序员。
我经常在一个方法的开头有几个语句来返回“简单”的情况。例如,这个:
public void DoStuff(Foo foo)
{
if (foo != null)
{
...
}
}
... (恕我直言)可以像这样变得更具可读性:
public void DoStuff(Foo foo)
{
if (foo == null) return;
...
}
所以,是的,我认为从一个函数/方法中有多个“出口点”是很好的。
这可能是一个不寻常的观点,但我认为任何相信多个return语句是有利的人都从未在只支持4个硬件断点的微处理器上使用过调试器。:-)
虽然“箭头代码”的问题是完全正确的,但当使用多个return语句时,一个问题似乎消失了,那就是在使用调试器的情况下。您没有一个方便的万能位置来放置断点,以保证您将看到退出,从而看到返回条件。
有时出于性能考虑,这是必要的(我不想获取不同的缓存线,就像继续一样;有时)。
如果你不使用RAII分配资源(内存、文件描述符、锁等),那么多次返回很容易出错,而且肯定是重复的,因为释放需要手动执行多次,你必须仔细跟踪。
在这个例子中:
function()
{
HRESULT error = S_OK;
if(SUCCEEDED(Operation1()))
{
if(SUCCEEDED(Operation2()))
{
if(SUCCEEDED(Operation3()))
{
if(SUCCEEDED(Operation4()))
{
}
else
{
error = OPERATION4FAILED;
}
}
else
{
error = OPERATION3FAILED;
}
}
else
{
error = OPERATION2FAILED;
}
}
else
{
error = OPERATION1FAILED;
}
return error;
}
我会把它写成:
function() {
HRESULT error = OPERATION1FAILED;//assume failure
if(SUCCEEDED(Operation1())) {
error = OPERATION2FAILED;//assume failure
if(SUCCEEDED(Operation3())) {
error = OPERATION3FAILED;//assume failure
if(SUCCEEDED(Operation3())) {
error = OPERATION4FAILED; //assume failure
if(SUCCEEDED(Operation4())) {
error = S_OK;
}
}
}
}
return error;
}
这当然看起来更好。
这在手动资源释放的情况下尤其有用,因为在哪里和哪些释放是必要的是相当直接的。如下例所示:
function() {
HRESULT error = OPERATION1FAILED;//assume failure
if(SUCCEEDED(Operation1())) {
//allocate resource for op2;
char* const p2 = new char[1024];
error = OPERATION2FAILED;//assume failure
if(SUCCEEDED(Operation2(p2))) {
//allocate resource for op3;
char* const p3 = new char[1024];
error = OPERATION3FAILED;//assume failure
if(SUCCEEDED(Operation3(p3))) {
error = OPERATION4FAILED; //assume failure
if(SUCCEEDED(Operation4(p2,p3))) {
error = S_OK;
}
}
//free resource for op3;
delete [] p3;
}
//free resource for op2;
delete [] p2;
}
return error;
}
如果在没有RAII(忘记异常问题!)的情况下使用多个出口编写这段代码,则必须多次写入删除。如果你用}else{then 这有点难看。
但是RAII使得多个出口资源问题变得毫无意义。
Well, maybe I'm one of the few people here old enough to remember one of the big reasons why "only one return statement" was pushed so hard. It's so the compiler can emit more efficient code. For each function call, the compiler typically pushes some registers on the stack to preserve their values. This way, the function can use those registers for temporary storage. When the function returns, those saved registers have to be popped off the stack and back into the registers. That's one POP (or MOV -(SP),Rn) instruction per register. If you have a bunch of return statements, then either each one has to pop all the registers (which makes the compiled code bigger) or the compiler has to keep track of which registers might have been modified and only pop those (decreasing code size, but increasing compilation time).
今天仍然坚持使用一个return语句的一个原因是易于自动重构。如果您的IDE支持方法提取重构(选择一系列行并将它们转换为一个方法),那么如果您想提取的行中有一个return语句,特别是如果您正在返回一个值,则很难做到这一点。