9

当代码流是这样的时候:

if(check())
{
  ...
  ...
  if(check())
  {
    ...
    ...
    if(check())
    {
      ...
      ...
    }
  }
}

我通常已经看到了这种解决方法,以避免这种混乱的代码流:

do {
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
    if(!check()) break;
    ...
    ...
} while(false);

有哪些更好的方法可以避免这种变通方法/黑客攻击,使其成为更高级别(行业级别)的代码?

是否有来自 Apache commons 或 Google Guava 的构造?

注意:这是C++ 相同问题的副本。最好的答案是真正的函数指针和 GOTO 命令。两者在 Java 中都不存在。对于 Java,我对同样的事情非常感兴趣。

将它放入一个新函数并使用return在我看来不是一个好的解决方案,因为 return 退出了该方法。因此,如果我的班级有 20 个具有这些构造的方法,我将不得不添加 20 个额外的方法来完成这项工作。这就是为什么 GOTO 是 C++ 的最佳答案。

4

4 回答 4

6

这是什么“while(false)”的废话?使用标签!

myLabel: {
    if(!check()) break myLabel;
    ...
    ...
    if(!check()) break myLabel;
    ...
    ...
    if(!check()) break myLabel;
    ...
}

它是核心 Java:http ://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html

于 2013-09-12T19:30:44.007 回答
6

为了降低圈复杂度,您可以将逻辑分成子方法:

public void go() {
    first();
}

public void first() {
    if(check()) {
        // #1
        second();
    }
}

public void second() {
    if(check()) {
        // #2
        third();
    }
}

public void third() {
    if(check()) {
        // #3
    }
}
于 2013-08-30T09:41:02.047 回答
2

因为你可以在一个函数中有这 20 次以通过 20 个连续步骤。如果我这样做,最后的 if 已经向右滑动了 20 个标签,这使得代码不可读。

您的此评论显示了问题:您想象错误的代码结构。

例如你的代码是这样的

if (bool) {
     // do something
     if (anotherBoolean) {
         //do even more
         if (thirdBoolean) {
             // here we go! I spare deeper structure...
         }
     }
}

这可以很容易地重构为:

public void method() {
    if (bool) {
        doSomeStuff();
    }
}

public void doSomeStuff() {
    if (anotherBoolean) {
        doThirdStuff();
    }
}

public void doThirdStuff() {
    if (thirdBoolean) {
        doEvenMore();
    }
}

public void doEvenMore() {
    // deeper structure
}

这种代码结构将是干净代码的一个很好的示例,因为这些方法正在执行它们的“单一目的”的东西,你不会做一个 while-loop hack,而且你甚至可以在某个地方重用这些方法。

于 2013-08-30T09:41:13.177 回答
1

这是个好问题。任何解决方案的语义都必须涉及某种可兴奋的块,无论是字面的还是可以退出的实现隐含的。

其他一些答案非常复杂,以至于当他们实现避免 do-while 循环时,失去了所有的清晰度和可读性,这使得它们成为“糟糕”的代码。

经过一番思考,这就是我的编码方式:

doSomething(); // Replace current code with a method call

private void doSomething() {
    if(!check()) return;
    ...
    ...
    if(!check()) return;
    ...
    ...
    if(!check()) return;
    ...
    ...
}

要点:

  • 方法是一个块,它被干净地退出return
  • 这三个部分显然是一个编程单元,因此它们一起是重构为单独方法的字符串候选
  • 没有“设计”,例如敷衍的 do-while(false) 构造,它的存在只是为了提供一个可退出的块并且可能会混淆其他人
  • 通过使用否定测试然后退出,可以实现两件事:
    • “提前退出”编码范式
    • 更少的缩进/嵌套,从而降低了循环复杂度
  • 没有创建额外的块/类/对象,保持可读性和性能(尽管框架将被压入堆栈以进行方法调用 - 影响可以忽略不计
于 2013-08-31T00:02:50.317 回答