Java 降低方法的复杂性

Java 降低方法的复杂性,java,algorithm,Java,Algorithm,我有一个方法可以完成几个任务。它是应用程序业务逻辑的一部分,但可读性较差,因为有许多if-then和try-catch块和许多log调用 public class MyClass { boolean createReport, sendReport, warnIfErrors; public void archiveAll() { if (createReport) { //... ... } if (sendReport) {

我有一个方法可以完成几个任务。它是应用程序业务逻辑的一部分,但可读性较差,因为有许多
if-then
try-catch
块和许多
log
调用

public class MyClass {     

boolean createReport, sendReport, warnIfErrors;

public void archiveAll() {

    if (createReport) {
      //... ...
    }

    if (sendReport) {
      //... ...
    }

    if (warnIfErrors) {
      //... ...
    }

} 
其想法是将任务转移到特殊方法中,并有一个“archiveAll”方法,可以一眼就理解:

public void archiveAll() {

    doCreateReport();

    doSendReport();

    doWarnIfErrors();

} 
但在这样做的过程中,出现了两个问题:

  • 如果所有方法都使用局部变量,我会将其作为类字段移动,但这不是一个好的设计
  • 我还想将测试
    if(createReport)
    移动到方法
    doCreateReport
    中,因为部分复杂度来自已完成的测试。这使得子方法的内聚性很差
  • 您还可以将所需的数据作为参数传递给方法
  • 我会在调用方法之前进行检查。如果一个方法被称为doCreateReport,它实际上应该这样做

  • 如果您有许多在它们之间共享的局部变量,那么创建一个私有类将它们存储在一起可能是有意义的,甚至可以执行以下操作:

    MyReport report = new MyReport(); // or MyReport.doCreateReport(); if it makes more sense
    report.send();
    report.warnIfErrors();
    
    同样,这实际上取决于函数当前是否足够大,以保证这样的事情

    如果您可以将这些公共变量作为参数传递,而不需要大量的参数列表,那么就这样做吧

  • 不要创建变量类字段,只需参数化函数并传递值即可。这还有另一个很大的优势,即您的代码现在将变得更易于单元测试。我总是提倡让每种方法尽可能独立,因为它有助于UT
  • 如果您当时将名称更改为checkAndCreateReport,您还会这样想吗:)

  • 1.是的,但是变量的数量增长越大,它们的重要性就越低。考虑一个有10个参数的方法。。。2.当然我应该这样做,但我更感兴趣的是在正确的名称中更改名称,而不是仅仅为了命名而移动复杂的测试。IMO除非设置了模糊的标志,否则静默不做任何事情的方法比显式的if更令人困惑。或者,您可以将方法重命名为doCreateReportIfRequested(),doSendReportIfRequested()。这样你就会知道方法的行为是有条件的。1.是的,同时也要注意部分之间的相互关系。2.我对checkAndCreateReport之类的方法名称非常感兴趣。我认为在库代码(代理模式、sql访问、低级函数)中,这种方法有点“向下-向上”,你必须找到一个类,该类中的方法执行它们所说的操作,不减少(出错)也不增加(内聚)。但业务代码必须是可读的,可能是自上而下设计的。我首先编写一个流程,要求执行“doA”、“doB”、“doC”等步骤,然后详细说明每件事情的具体执行时间。这样我就可以一眼就知道流程执行的步骤