我们正在重构一个很长的方法; 它包含一个包含for许多continue语句的长循环.我想使用Extract Method重构,但Eclipse的自动化重构不知道如何处理条件分支.我也没有.
我们当前的策略是引入一个keepGoing标志(一个实例变量,因为我们想要提取方法),在循环顶部将它设置为false,并将每个continue替换为将标志设置为true,然后包装所有在if (keepGoing)子句中跟随东西(在不同的嵌套级别).然后执行各种提取,然后用keepGoing提取的方法中的早期返回替换赋值,然后去除该标志.
有没有更好的办法?
更新:回应评论 - 我无法分享代码,但这是一个匿名的摘录:
private static void foo(C1 a, C2 b, C3 c, List<C2> list, boolean flag1) throws Exception {
for (int i = 0; i < 1; i++) {
C4 d = null;
Integer e = null;
boolean flag2 = false;
boolean flag3 = findFlag3(a, c);
blahblahblah();
if (e == null) {
if (flag1) {
if (test1(c)) {
if (test2(a, c)) {
Integer f = getF1(b, c);
if (f != null)
e = getE1(a, f);
if (e == null) {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
}
} else {
Integer f = getF2(b, c);
if (f != null)
e = getE2(a, f);
if (e == null) {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
}
flag2 = true;
}
} else {
if (test3(a, c)) {
Integer f = getF2(b, c);
if (f != null)
e = getE2(a, f);
if (e == null) {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
}
flag2 = true;
} else {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
flag2 = true;
}
}
}
if (!flag1) {
if (d == null) {
list.add(b);
continue;
}
e = findE(d);
}
}
if (e == null) {
list.add(b);
continue;
}
List<C2> list2 = blahblahblah(b, list, flag1);
if (list2.size() != 0 && flag1) {
blahblahblah();
if (!otherTest()) {
if (yetAnotherTest()) {
list.add(b);
continue;
}
blahblahblah();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个有趣的,没有单一的模式可以让你到那里.
我会迭代地工作.
首先,我试着看看我是否能够使用早期继续删除其中一个ifs级别.检查条件并提前返回(或者在你的情况下继续)比使用深度嵌套ifs更清晰的代码.
接下来我想我会采取一些内部块,看看它们是否无法被提取到一个单独的方法中.看起来前两个大块(在"if(test2(a,c)){"及其else语句中)非常相似.剪切和粘贴逻辑应该是相同的.
最后,在清理完东西后,您可以开始查看实际问题 - 您需要更多课程.这整个语句可能是3-5个兄弟类中的三线多态方法.
它非常接近抛弃和重写代码,一旦你确定了你的实际类,这整个方法就会消失,并被一些如此简单的东西所取代.事实上它是一个静态实用方法应该告诉你一些事情 - 你不需要这类代码中的一个.
编辑(看了一会儿之后):这里有很多东西,通过它真的很有趣.请记住,当你完成后你不需要代码重复 - 而且我很确定整个事情可以写成没有单一的if - 我认为所有你的ifs都是可以/应该很容易被多态处理的情况.
哦,作为你不想做的日食问题的答案 - 甚至不要尝试自动重构这个,只需手动完成.第一个if()中的东西需要被拉出到一个方法中,因为它实际上与else()中的子句相同!
当我做这样的事情时,我通常会创建一个新方法,将代码从if移动到新方法中(只在if中调用新方法),然后运行测试并确保没有破坏任何东西.
然后逐行进行并检查以确保if和其他代码之间没有区别.如果存在,则通过将差值作为新变量传递给方法来补偿它.在确定所有内容完全相同后,使用调用替换else子句.再次测试.在这一点上可能会有一些额外的优化变得明显,如果将它的逻辑与你传递的变量结合起来区分这两个调用,你很可能会失去整个.
继续做这样的事情并迭代.重构的诀窍是使用非常小的步骤并在每个步骤之间进行测试以确保没有任何改变.