Java 降低代码的复杂性
我现在被一些非常奇怪的类卡住了,它们的逻辑混淆了。以下是生成数据库查询的代码示例:Java 降低代码的复杂性,java,refactoring,anti-patterns,Java,Refactoring,Anti Patterns,我现在被一些非常奇怪的类卡住了,它们的逻辑混淆了。以下是生成数据库查询的代码示例: if(realTraffic.getPvkp() != null) { //Admission point if(BeanUtils.isGuidEntity(realTraffic.getPvkp())) { findParameters += " and (" + staticTableName() + ".guidPvkp = '" + realTraffic.ge
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和check。为了使代码更简单、更优雅,有哪些常用方法
UPD:我知道在编写新项目时如何避免此类代码,但如何处理现有的遗留代码?Bob叔叔的《干净代码》一书中提供了处理此类问题的良好指南。 就你而言,我会说:
- 将字符串连接放入方法中(并使用
)StringBuilder
- 将
转换为else{if(条件)}
else-if(条件)
- 考虑将
companyType==CompanyBean.PP\u类型&!realTraffic.isSkipOther()在一个单独的方法中,因为它似乎是某种业务逻辑,如果放在一个名为
if(isCompanySkippedOver(companyType,realTraffic))的方法中,读者可能会更清楚
- 考虑将
转换为if(realTraffic.getPvkp()!=null)
if(realTraffic.getPvkp() == null) {return;}
减少块缩进。我不希望看到所有的字符串串联来动态生成SQL查询。您可能有一个可计数集,即使它很大。我会将它们设置为静态最终字符串,并使用
PreparedStatement
和绑定变量。您的方法太容易出错,可能会有SQL注入的风险
我会将代码保存在一个基于接口的持久性/存储库/DAO类中,我会考虑使其具有多态性,以便根据传递的参数选择版本
它真的很复杂,想想状态机、决策树或决策表。这些都是驯服复杂性的好方法
可以说OOP是为了摆脱这样的复杂逻辑。看看你是否可以使用多态性和封装来消除它。看起来像是我每天都要处理的代码 如果我遇到一大堆类似这样的If,我会做出判断,判断未来的条件是否会改变,以及我需要在多大程度上提高代码的清晰度 如果If的主体会改变,但条件不会改变,我已经尝试将条件分解为一个返回布尔值的方法。然后,该方法将在其生命周期的一英寸内进行单元测试。我意识到这不是一个理想的重构,但它是一个实用的解决方案,可以提高该部分代码的清晰度。这可能是可行的需要指出的是,我在这里讨论的代码目前没有任何单元测试,因此大规模重构很困难-我猜你也处于类似的位置。从编写特性测试开始,即,单元测试将修复系统的当前行为。你至少需要4个测试来覆盖所有可能的路径 只有这样,当您受到测试的保护时,您才能重构 如何重构取决于您的技术技能和倾向。作为一个面向对象的人,我可能会向封装where条件的增量构建的对象推进:
condition.add("foo = ?", x);
condition.add("bar <> ?", y);
...
condition.toSql(); // returns the sql code
condition.getObjects(); // returns a list of x, y...
condition.add(“foo=?”,x);
条件。添加(“条?”,y);
...
condition.toSql();//返回sql代码
condition.getObjects();//返回x,y。。。
其他方法也可能奏效
关键思想是分离抽象级别;在一个级别上,您有从数据库中选择内容的业务规则;在更具体的级别上,您有字符串连接。您不想混合这些级别。您已经有了一个标签:通过重构。开始将块提取到私有方法中,它将压缩基本方法,并使其更易于遵循和查看可以改进的小步骤,只需一步一步地重构它。在这种情况下,您可能可以对所有这些字符串使用
StringBuilder
,而不是+
。+1表示“小步骤”:只要对你注意到的每一件小事继续进行小而无脑的重构。我这样做不仅仅是为了清理代码,而是在我试图理解它之前。你调用getStaticTableName()
多次。使用Extract Local vVariable
将其减少为仅一个调用。但是,这种情况会发生变化吗?也许它应该显示为SELECT语句的teh FROM子句?