2012-03-29 120 views
2

我们有应用程序A作为主要应用程序。现在我们从App B开始构建使用App A功能子集的应用程序B。如何用许多if构造来重构一个大函数?

应用一个停留喜欢它,而应用B只使用的

一个子集所以我想重构功能没有或尽可能少dublication地和最大的可读性。

因此函数看起来像这样(它实际上较长,这是一个摘录):

class SomeClass { 

    Data prepareData() { 

    if (this.bothId==1 || this.appAid=2 /*or only relevant for appA*/) {  
     if(this.data==null) { /*appA*/ 
      appAdoSmth(); /*appA*/ 
     } 
     boolean merge=false; /*appA*/ 
     if (this.data==null) { /*appA*/ 
      merge=appAanalyze(data); /*appA*/ 
     } 
     bothPrepare(merge); 
    } else if (bothIsRelevant()) { 
     if(appArelevant()) { /*appA*/ 
     data=appAprepare(); /*appA*/ 
     } else { 
     data=prepareBoth(); 
     }  
     bothUpdateSomeValue(); 
    } 

    } 

那你怎么办呢?

+1

使用Eclipse.It有一个选项来重构method.It会自动提出新的方法,包括它的参数。但是你必须考虑应该重构多少代码。 – vikiiii 2012-03-29 11:11:06

回答

2

其他答案解决了如何重构代码的一般问题。他们提供了很好的建议,但我不认为这是你所要求的。

我想你在问你可能的代码重构问题。

很难给出一般适用或甚至特别适用的答案。 (示例代码不是真正的代码,它有点难以理解它实际“意味着什么”)。

  • AndreasD给出了一种方法:将大复杂的嵌套if分解为单独的方法。

  • 另一种方法是使用Stragegy设计模式。将特定于每个应用程序的代码分解为战略类。例如:

    interface Strategy { 
        Data prepareData(); 
    } 
    
    class GeneralStrategy implements Strategy { 
        Data prepareData() { 
         // do general preparation 
        } 
    } 
    
    class App1Strategy extends GeneralStrategy { 
        Data prepareData() { 
         // do app1-specific preparation 
         super.prepareData(); 
         // do more app1-specific preparation 
        } 
    } 
    

等。

+0

我正在考虑使用带有函数prepareData()的抽象类。在那个抽象类的prepareData()中,我用抽象函数替换了所有的Appspecific事物,并在扩展类中实现它们。换句话说,在一种情况下,这些函数将是空的,因为在App B中没有任何事情发生。我用我的代码的主要问题是有很多次if(){...} if(){...} if (){...}。第一个如果能够或不能对第二个产生影响,那么它又会对第三个产生影响。这是非我自己写的丑陋代码。但是:并非一切都很好地重构 – Toskan 2012-03-29 12:02:40

+0

*“但是:并非一切都很好地重构” - 这是正确的。 DRY有时是一种无法实现的理想。 – 2012-03-29 12:16:04

1

我理想的世界发展单元测试,验证您的功能现有的实施工作。

然后开始逐步更改代码并在每次更改后运行您的测试。 如果不知道代码结构,很难给出正式的建议。但通常会尝试查找重复的代码片段,编写使用参数实现此逻辑的方法,并将重复的片段替换为新的方法。等等。

祝你好运。

0

如果我是你,我会运行这个课程的报道报告。 (例如http://ecobertura.johoop.de/http://www.eclemma.org/)通过这种方式,Eclipse可以将遮盖的线条显示为绿色,这有助于识别案例。借助这种帮助,分离绿线并将其拉入方法将变得更加容易。

0

通过在单独的方法中提取某些逻辑可以提高可读性。这是一种重构方法。

Data prepareData() { 
    if (this.bothId==1 || this.appAid=2) { 
    handleCase1(); // <- you'll find better names for the methods  
    } else if (bothIsRelevant()) { 
    handleCase2(); 
    } 
} 

private void handleCase1() { 
    if(this.data==null) { 
    appAdoSmth(); 
    } 
    boolean merge=false; 
    if (this.data==null) { 
    merge=appAanalyze(data); 
    } 
    bothPrepare(merge); 
} 

private handleCase2() { 
    if(appArelevant()) { 
    data=appAprepare(); 
    } else { 
    data=prepareBoth(); 
    }  
    bothUpdateSomeValue(); 
} 

当然,这并不减少if/else的数量,但它使“main”方法保持简单。

+0

问题是:这不会简化功能。例如。对于应用程序B,我将拥有所有对应用程序B中从未使用过的内容的调用。所以我必须维护应用程序B的人将不得不查看一切,但我知道我从来没有在那里使用appAprepare。 – Toskan 2012-03-29 12:25:00