缩进应该总是最小化吗?

Should indentation always be minimized?

我想听听您对尽量减少缩进是否有益的看法。

我通常是这样处理问题的:

int foo_a() {
    if (!check_value(x)) {
        // error
        return false;
    }
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    return true;
}

另一方面,我也看到了这样的代码:

int foo_b() {
    if (!check_value(x)) {
        // error
        return false;
    } else {
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        return true;
    }
}

int foo_c() {
    if (check_value(x)) {
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        return true;
    } else {
        // error
        return false;
    }
}

但这可能会适得其反,因为如果每次检查都会创建一个新的 else 分支,idents 会变得非常大。

另一方面,对于决策,例如蔬菜或肉类,我通常这样做:

int foo_d(FOOD food) {
    if (food.isVegetable) {
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        return;
    } else {
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        return;
    }
    // assume here is NO shared code which is always executed for both food types.
}

但是像 foo_a() 那样做,它应该是这样的:

int foo_e(FOOD food) {
    if (food.isVegetable) {
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        // do stuff
        return;
    }

    // do stuff
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    // do stuff
    return;
}

这只是风格问题,但我会选择代码更少、缩进更少的方式。

如果您通过提取函数来保持函数简短,那么无论您选择什么,它都应该保持可读性。例如:

int foo_e(FOOD food) {
    if (food.isVegetable)
        return foo_vegetable(food);

    return foo_meat(food);
}

我个人认为

if(flag) {
    //long computation
    return;
} else {
    //long computation
    return;
}

以及

if(flag) {
    //long computation
    return;
}
//long computation
return;

是反模式,因为它们使推断程序流和可能的 return 值变得更加困难。它们也更有可能在重构过程中导致错误 - 或者通常在以后的修改过程中,因为人们可能会忽略第一个 return 语句。

出于这个原因,一些编码指南只允许每个函数一个 return 语句。在这种情况下,您将始终必须使用 ifelse:

int foo(int param) {
    int retval = 0;
    if (param > 0) {
        //computation
        retval = 5;
    } else {
        //computation
        retval = -1;
    }
    return retval;
} 

我个人通常允许两个 areas 其中允许 return 语句: 就在异常或琐碎的 returns 的开头(例如 foo_a() -示例中的参数检查)和最后,常规 return 值为 return编辑。请注意,在这两个区域中可以有多个 return 语句,尽管对于我的函数来说,具有多个 "regular" 退出点并不常见。

int foo2(int param1, int param2) {
    if (!precondition1(param1)) return -1;//error
    if (!precondition2(param2)) return -2;//error
    if (param1==param2) return 0; // no error, but answer can be determined trivially       

    //computation

    return local_variable; //return regular result
}

此处开头的前两个 return 语句也可能是断言或异常。

如果我根据标志或参数的值进行两种不同的计算(如 food.isVegetable),我总是像第一个示例一样在两者之后使用 if-else 和单个 return 语句以上。

此外,如果意图级别变得太高,您可能需要考虑编写一个单独的函数。这并不总是可能的,但比您想象的更频繁。例如。对于错误检查,您可以围绕检查错误输入的实际函数编写一个包装器:

int fooChecked(int param) {
    int retVal;
    if (param > 0 && param < 200) {
        retval = foo(param);
    } else {
        retVal = -1;            
    }
    return retVal;
}