你们中的大多数人可能遇到过这种情况,在应用程序可以继续之前必须检查多个事物并且按照一定的顺序,例如在一个非常简单的情况下创建一个监听套接字(socket,bind,listen,accept)等等。)。至少有两种明显的方法(不要逐字逐句):
if (1st_ok)
{
if (2nd_ok)
{
...
或
if (!1st_ok)
{
return;
}
if (!2nd_ok)
{
return;
}
...
你有没有更聪明的东西,你更喜欢上面的另一个,或者你(如果语言提供)使用例外?
答案 0 :(得分:4)
我更喜欢第二种技术。第一个问题的主要问题是它增加了代码的嵌套深度,这是一个重要的问题,当你有大量的前提条件/资源分配要检查时,因为函数的业务部分最终被埋没了在条件墙后面(并经常循环)。在第二种情况下,您可以将概念逻辑简化为“我们已经到达并且一切正常”,这样更容易使用。将正常情况保持为尽可能直线更容易理解,尤其是在进行维护编码时。
答案 1 :(得分:2)
这取决于语言 - 例如在C ++中,您可能会使用异常,而在C语言中,您可能会使用以下几种策略之一:
if
/ else
阻止goto
(处理的“异常”单个goto
标签可能break
循环do { ... } while (0)
我个人不喜欢函数中的多个return
语句 - 我更喜欢在函数末尾有一个公共的清理块,后跟一个return
语句。
答案 2 :(得分:1)
这往往是一种风格问题。有些人只喜欢在程序结束时返回,有些人更愿意在需要的地方进行。
我是第二种方法的粉丝,因为它允许简洁明了的代码,并且可以轻松添加文档。
// Checking for llama integration
if (!1st_ok)
{
return;
}
// Llama found, loading spitting capacity
if (!2nd_ok)
{
return;
}
// Etc.
答案 3 :(得分:1)
我更喜欢第二个版本。
在正常情况下,检查之间的所有代码都是按顺序执行的,所以我喜欢在同一级别看到它们。通常没有if
分支被执行,所以我希望它们尽可能不引人注目。
答案 4 :(得分:1)
我使用第二,因为我觉得它更好,更容易遵循逻辑。他们还说异常不应该用于流量控制,而是用于异常和意外情况。我想看看专业人士对此有何看法。
答案 5 :(得分:1)
怎么样?
if (1st_ok && 2nd_ok) { }
或者是否必须完成某些工作,例如使用套接字的示例
if (1st_ok() && 2nd_ok()) { }
答案 6 :(得分:0)
我因为嵌套而避免使用第一个解决方案。
我避免使用第二种解决方案,因为公司编码规则禁止在函数体中使用多个return
。
当然,编码规则也禁止goto
。
我的解决方法是使用局部变量:
bool isFailed = false; // or whatever is available for bool/true/false
if (!check1) {
log_error();
try_recovery_action();
isFailed = true;
}
if (!isfailed) {
if (!check2) {
log_error();
try_recovery_action();
isFailed = true;
}
}
...
这并不像我想的那么漂亮,但它是我发现最符合我的约束并编写可读代码的最好的。
答案 7 :(得分:0)
对于它的价值,以下是我对这个问题的一些想法和经验。
就个人而言,我倾向于选择你概述的第二个案例。我发现更容易遵循(和调试)代码。也就是说,随着代码的进展,它变得“更正确”。根据我自己的经验,这似乎是首选方法。
我不知道它在现场有多常见,但我也看到条件测试写成......
error = foo1 ();
if ((error == OK) && test1)) {
error = foo2 ();
}
if ((error == OK) && (test2)) {
error = foo3 ();
}
...
return (error);
虽然可读(在我的书中总是一个加号)并避免深度嵌套,但总是让我感到震惊的是使用了大量不必要的测试来实现这些目的。
第一种方法,我认为使用频率低于第二种方法。在那些时候,绝大多数时间是因为没有好的方法。对于剩下的几个实例,在成功案例中提取更多表现的基础上是合理的。争论的焦点是处理器会预测前向分支未被采用(对应于 else 子句)。这取决于几个因素,包括架构,编译器,语言,需求......显然,大多数项目(以及项目的大多数方面)都不符合这些要求。
希望这有帮助。