在这种情况下是否可以避免代码重复? (Java代码)
void f()
{
int r;
boolean condition = true;
while(condition)
{
// some code here (1)
r = check();
if(r == 0)
break ;
else if(r == 1)
return ;
else if(r == 2)
continue ;
else if(r == 3)
condition = false;
// some code here (2)
r = check();
if(r == 0)
break ;
else if(r == 1)
return ;
else if(r == 2)
continue ;
else if(r == 3)
condition = false;
// some code here (3)
}
// some code here (4)
}
int check()
{
// check a condition and return something
}
可能的解决方案可能是使用异常,但这似乎不是一个好习惯。在这种情况下,是否存在所谓的良好程序流控制模式?例如,一种从break ;
函数内部调用check()
的方法。(可能是其他编程语言)
对于一个棘手的问题,有一些好的答案(特别是@Garrett的问题,但我将为后代添加$ 0.02。
这里没有关于如何重构此块而没有看到实际代码的简单答案,但我对此的反应是,需要重新设计它。
例如,调用break的方法;从check()函数内部。 (可能是其他编程语言)
[如果您要请求Java不支持的其他中断(没有技巧),并且具有重复的check()
和各种不同的循环退出/重复代码,则对我来说,这是一个庞大而复杂的方法。以下是一些您可以考虑的想法:
some code here
的每个块都在做某事。如果将它们拉出自己的方法,那将如何改变循环?
也许将循环分解为一系列注释。不要深入研究代码,而是从概念上进行思考,以查看是否有其他配置退出。
您的组织中是否有其他开发人员不参与此代码的研究?如果您详细解释了某人的代码工作方式,他们可能会看到某些模式,因为您处于杂草状态。
[我也认为@aix的有限状态机是个好主意,但我在编程过程中很少需要使用这种机制,主要是在模式识别期间。我怀疑重新设计代码,将较小的代码块放入方法中就足以改善代码。
如果您确实想实现状态机,这里有更多详细信息。您可能有一个循环,该循环仅运行一个称为方法的单个switch语句。每个方法将为开关返回下一个值。这与您的代码不完全匹配,但类似于:
int state = 0;
WHILE: while(true) {
switch (state) {
case 0:
// 1st some code here
state = 1;
break;
case 1:
state = check();
break;
case 2:
return;
case 3:
break WHILE;
case 4:
// 2nd some code
state = 1;
break;
...
}
}
希望其中一些帮助和好运。
避免这种重复的最佳方法是,不要通过使方法小型化和集中化而让它首先发生。
如果// some code here
块不是独立的,那么您需要发布所有代码,然后其他人才能帮助您重构它。如果它们是独立的,则有一些方法可以对其进行重构。
首先,我第二个aix的答案:重写您的代码!为此,state design pattern可能会有所帮助。我还要说的是,以这种方式使用break,continue和return就像代码重复本身一样具有代码异味。
private int r;
void f()
{
distinction({void => codeBlock1()}, {void => codeBlock4()}, {void => f()},
{void => distinction( {void => codeBlock2()},{void => codeBlock4()},
{void => f()}, {void => codeBlock3()} )
});
}
void distinction( {void=>void} startingBlock, {void=>void} r0Block, {void=>void} r2Block, {void=>void} r3Block){
startingBlock.invoke();
r = check();
if(r == 0)
r0Block.invoke();
else if(r == 1)
{}
else if(r == 2)
r2Block.invoke();
else if(r == 3)
// if condition might be changed in some codeBlock, you still
// would need the variable condition and set it to false here.
r3Block.invoke();
}
这使用闭包。当然,可以省略参数r0Block和r2Block,而将codeBlock4()和f()硬编码在difference()中。但是,则只有f()可以使用discprise()。在Java <= 7的情况下,您需要将Interface与方法invoke()结合使用,并使用4种实现codeBlock1至codeBlock4。当然,这种方法根本不可读,但是它是如此笼统,以至于它适用于codeBlocks中的任何业务逻辑,甚至适用于任何break / return / continue-orgy。
不是。第二个继续是多余的(您的代码仍然会继续)。尝试使用Switch语句。这将使您的代码更具可读性。
一种更好的方法是使用switch语句,如下所示:
void f()
{
int r;
boolean condition = true;
while(condition)
{
outerloop:
r = check();
switch(r){
case 0: break outerloop;
case 1: return;
case 2: continue;
case 3: condition = false;
}
您可能想考虑将逻辑重新构造为状态机。它可以简化事情,并且可能使逻辑更容易遵循。