我有一些代码由很多(几百个LOC)的uggly条件组成,即
SomeClass someClass = null;
if("foo".equals(fooBar)) {
// do something possibly involving more if-else statments
// and possibly modify the someClass variable among others...
} else if("bar".equals(fooBar)) {
// Same as above but with some slight variations
} else if("baz".equals(fooBar)) {
// and yet again as above
}
//... lots of more else ifs
} else {
// and if nothing matches it is probably an error...
// so there is some error handling here
}
// Some code that acts on someClass
GenerateOutput(someClass);
现在我有了重构这类代码的想法:
abstract class CheckPerform<S,T,Q> {
private CheckPerform<T> next;
CheckPerform(CheckPerform<T> next) {
this.next = next;
}
protected abstract T perform(S arg);
protected abstract boolean check(Q toCheck);
public T checkPerform(S arg, Q toCheck) {
if(check(toCheck)) {
return perform(arg);
}
// Check if this CheckPerform is the last in the chain...
return next == null ? null : next.checkPerform();
}
}
对于每个if语句生成CheckPerform的子类,例如
class CheckPerformFoo extends CheckPerform<SomeInput, SomeClass, String> {
CheckPerformFoo(CheckPerform<SomeInput, SomeClass, String> next) {
super(next);
}
protected boolean check(String toCheck) {
// same check as in the if-statment with "foo" above"
returs "foo".equals(toCheck);
}
protected SomeClass perform(SomeInput arg) {
// Perform same actions (as in the "foo" if-statment)
// and return a SomeClass instance (that is in the
// same state as in the "foo" if-statment)
}
}
然后我可以将不同的CheckPerforms注入彼此,以便进行相同的检查顺序并采取相应的操作。在原始类中,我只需要注入一个CheckPerform对象。这是解决此类问题的有效方法吗?我项目中的类数可能会爆炸,但至少我将获得更多模块化和可测试的代码。我应该以其他方式这样做吗?
由于这些if-else-if -...- else-if-else语句是我所谓的代码库的重复主题,我想尽可能自动地进行重构。那么我可以用什么工具来自动化呢?
a)一些可自定义的重构功能隐藏在我错过的IDE中(最好是在Eclipse或IDEA中) b)一些外部工具,可以解析Java代码并给我细粒度的转换控制 c)我应该自己使用Scala破解它吗? d)我应该手动浏览每个类并使用我在IDE中熟悉的功能进行重构吗?
理想情况下,重构的输出还应该包括一些我可以运行的基本测试代码模板(最好也可以测试原始代码的案例,这些代码可以作为一种回归测试在新旧上运行......但是我稍后离开。)
感谢您的任何意见和建议!
答案 0 :(得分:2)
你所描述的是Chain of Responsibility Pattern,这听起来对你的重构来说可能是一个不错的选择。可能会有一些缺点。
答案 1 :(得分:1)
对我来说,最简单的方法是涉及Map<String, Action>
,即将各种字符串映射到要执行的特定操作。这样,查找将比CheckPerform*
类中的手动比较更简单,更高效,从而消除了大量重复的代码。
这些操作可以与您的设计类似地实现,作为公共接口的子类,但使用带有重写方法的枚举可能更容易,更紧凑。您可以在an earlier answer of mine中看到此示例。
不幸的是,我不知道任何可以帮助你的自动重构。早些时候,当我做了一些类似的重构时,我编写了单元测试,并使用Move Method等人的自动支持手动逐步进行重构。当然,由于单元测试在结构上彼此非常相似,我可以在那里重用部分代码。
foo -> com.foo.bar.SomeClass.someMethod
biz -> com.foo.bar.SomeOtherClass.someOtherMethod
baz -> com.foo.bar.YetAnotherClass.someMethod
bar -> com.foo.bar.SomeOtherClass.someMethod
biz -> com.foo.bar.DifferentClass.aMethod
baz -> com.foo.bar.AndAnotherClass.anotherMethod
其中缩进行为每个更大的案例配置子条件。
答案 2 :(得分:1)
要回答问题的更一般部分,除了基本的IDE支持之外,我不知道任何自动重构的工具,但是如果你想知道重构的内容,请查看{{3} }。 Refactoring catalog和replace conditional with Polymorphism涵盖了您问题的具体内容。