[英]How to avoid code duplication?
在这种情况下是否可以避免代码重复? (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 不支持的不同中断(没有 hack)并且具有重复的check()
和各种不同的循环退出/重复代码向我表明这是一个庞大而复杂的方法。 这里有一些想法供您思考:
some code here
每个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 的回答:重写你的代码! 为此,状态设计模式可能会有所帮助。 我还要说,以这种方式使用 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() 硬编码在 distinct() 中。 但是,distinct() 只能被 f() 使用。 对于 Java <=7,您需要使用带有方法 invoke() 的接口,以及代码块 1 到代码块 4 的 4 个实现。 当然,这种方法根本不可读,但非常通用,它适用于 codeBlocks 中的任何业务逻辑,甚至任何中断/返回/继续狂欢。
并不真地。 第二个 continue 是多余的(您的代码无论如何都会继续)。 尝试使用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;
}
您可能需要考虑将您的逻辑重新制定为状态机。 它可能会简化事情,并且可能会使逻辑更容易遵循。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.