2013-06-21 66 views
3

我现在被困在一些非常奇怪的类中,它们混淆了逻辑。下面是生成一个数据库查询代码的例子:降低代码的复杂性

if(realTraffic.getPvkp() != null) { 
    //Admission point 
    if(BeanUtils.isGuidEntity(realTraffic.getPvkp())) { 
     findParameters += 
     " and (" + staticTableName() + ".guidPvkp = '" + realTraffic.getPvkp().getGuid() 
     + "' or (" + staticTableName() + ".guidPvkpOut = '" + realTraffic.getPvkp().getGuid() 
     + "' and " + staticTableName() + ".requestType = " + RequestBean.TRANSIT_TYPE 
     + ")"; 
     if (companyType == CompanyBean.PP_TYPE && !realTraffic.isSkipOther()) { 
     // TODO - add non-formed 
     findParameters += " or (" + staticTableName() + ".guidPvkpOut is null " 
     + " and " + staticTableName() + ".requestType = " + RequestBean.TRANSIT_TYPE 
     + ")"; 
     } 
     findParameters += ") "; 
    } else { 
    // Territorial department 
     if(BeanUtils.isGuidEntity(realTraffic.getPvkp().getTerritorialDepartment())) { 
     findParameters += 
      " and (Pvkp.guidTerritorialDepartment = '" + realTraffic.getPvkp().getTerritorialDepartment().getGuid() 
      + "' or Pvkp.guidFtsDepartment = '" + realTraffic.getPvkp().getTerritorialDepartment().getGuid() 
      + "') "; 
     } 
    } 
} 

这仅仅是一个巨大的一套复杂的检查,我有方法的一部分。问题是 - 如何处理这样的代码 - 它有很多嵌套的if和检查。为了使代码更简单和更优雅,常见的方法是什么?

UPD:我知道在编写新项目时如何避免这种代码,但是如何处理现有的遗留代码?

+0

您已将您的答案作为标记:通过重构。 –

+1

开始将块提取到私有方法中,它将压缩原始方法并使其更容易跟随并查看可以改进的方面 – Infested

+3

婴儿步骤,只需一次一步重构。在这种情况下,你可以使用'StringBuilder'而不是'+'来处理所有这些字符串。 –

回答

7

处理这些事情的一个很好的指南是来自Bob叔叔的书,名为“Clean Code”。 在你的情况我会说:

  • 把字符串连接成一个方法(使用StringBuilder
  • 转换的else { if (condition) }else if (condition)
  • 考虑把companyType == CompanyBean.PP_TYPE && !realTraffic.isSkipOther()在一个单独的方法,因为这似乎是某种商业逻辑的,如果被放在一个叫if (isCompanySkippedOver(companyType, realTraffic)
  • 考虑到反转if(realTraffic.getPvkp() != null)

    方法可能让读者更清晰
    if(realTraffic.getPvkp() == null) {return;} 
    

减少块缩进。

2

我不想看到所有的字符串连接用于生成SQL查询。你可能有一个可数集,即使它很大。我会让他们静态最终字符串,并使用PreparedStatement和绑定变量。你的方式太容易出错,可能会冒SQL注入的风险。

我会保持代码在基于接口的持久性/存储库/ DAO类。我想让它变成多态的,这样我就可以根据传递的参数挑选出版本。

它确实很复杂,请考虑状态机或决策树或决策表。这些可以是驯服复杂性的好方法。

可以说OOP就是要摆脱这样复杂的逻辑。看看你是否可以使用多态和封装来消除它。

0

貌似我必须在每天上班的代码...

如果我遇到一大束的,如果是这样的我做出判断呼叫我是否认为条件将在未来发生变化,我需要多少钱才能提高代码的清晰度。

如果if的主体会改变,但是我不会试图将条件分解到返回布尔值的方法。然后,该方法在单位寿命内进行单位测试。我意识到这不是一个理想的重构,但它是一个务实的解决方案,可以提高该部分的代码清晰度。可能值得指出的是,我在这里讨论的代码目前还没有任何单元测试,因此大范围的重构很困难 - 我猜测你处于类似的位置。

0

开始写特征测试,即单元测试,将修复系统的当前行为。您至少需要4次测试来覆盖所有可能的路径。

只有当你受到测试的保护时,你才能重构。

如何重构取决于你的技术技能和倾向。作为一个面向对象的人,我可能会推向封装的WHERE条件的增量建设的对象:

condition.add("foo = ?", x); 
condition.add("bar <> ?", y); 
... 
condition.toSql(); // returns the sql code 
condition.getObjects(); // returns a list of x, y... 

其他方法可能工作。

关键的想法是分离抽象层次;在一个层次上,您有从数据库中选择内容的业务规则;在更具体的层面上,你有字符串连接。你不想混合这些水平。