减少圈复杂度,多个if语句

时间:2015-10-01 10:03:23

标签: java sonarqube cyclomatic-complexity

我有以下代码:

private Facility updateFacility(Facility newFacility, Facility oldFacility) {
    if (newFacility.getCity() != null)
        oldFacility.setCity(newFacility.getCity());
    if (newFacility.getContactEmail() != null) 
        oldFacility.setContactEmail(newFacility.getContactEmail());
    if (newFacility.getContactFax() != null) 
        oldFacility.setContactFax(newFacility.getContactFax());
    if (newFacility.getContactName() != null) 
        oldFacility.setContactName(newFacility.getContactName());
    // ......
}

大约有14个这样的检查和作业。也就是说,除了少数,我需要修改oldFacility对象的所有字段。我得到了这个代码14的圈复杂度,根据SonarQube,它是“超过10个授权”。关于如何降低圈复杂度的任何想法?

6 个答案:

答案 0 :(得分:4)

在程序中的某个时刻,您必须实现逻辑:

  • 如果新设施已定义属性,则相应地更新旧设施
  • 如果没有,请不要覆盖旧设施中的先前值。

如果没有对项目进行全局审视,您可以做的是将逻辑移到每个属性的setter中:

public class Facility {

    public void setSomething(String something) {
        if (something != null) {
            this.something = something;
        }
    }

}

这样,您的update方法就是:

private Facility updateFacility(Facility newFacility, Facility oldFacility) {
    oldFacility.setSomething(newFacility.getSomething());
    // etc for the rest
}

答案 1 :(得分:1)

我认为您可以应用Builder Pattern来解决问题,它可以帮助您消除if语句循环中的挫败感。有关更多详情,请参阅this link

答案 2 :(得分:0)

您可以在Facility类中覆盖hashCode和equals方法,并执行以下操作:

if(!newFacility.equals(oldFacility))
 {
    //only when something is changed in newFacility, this condition will be excecuted
    oldFacility = newFacility;
 }
 return oldFacility;
 //This is just and example, you can return newFacility directly

注意:您可以包括所有参数或仅包含决定唯一性的参数。由你决定。
希望这有帮助!

答案 3 :(得分:0)

您可以将您不想修改的oldFacility对象的字段复制到其他一些变量,然后更新整个oldFacility对象,只需替换您所做的字段即可。 #39; t想要改变存储在其他变量中的内容。即。

private Facility updateFacility(Facility newFacility, Facility oldFacility){
    String contentNotToBeModified; // or whatever variable type
    contentNotToBeModified = oldFacility.getCity();
    // Do the same for all data that you want to keep

    oldFacility = newFacility;
    newFacility.setCity(contentNotToBeModified);
}

因此,首先将要保留的数据从oldFacility复制出来,然后将oldFacility替换为newFacility,并将newFacility的必需属性替换为来自oldFacility的数据。 nullptr

答案 4 :(得分:0)

非空检查对我来说似乎没有意义,因为如果您稍微修改一下这样的示例,NullPointerException将不会被抛出:

private Facility updateFacility(Facility newFacility, Facility oldFacility) {

if (newFacility != null) {

    oldFacility.setCity(newFacility.getCity());
    oldFacility.setContactEmail(newFacility.getContactEmail());
    oldFacility.setContactFax(newFacility.getContactFax());
    oldFacility.setContactName(newFacility.getContactName());
    ...
}

这将为引用无效的引用分配空值,并且不会引起任何问题。

假设您正在执行newFacility.getCity().toString()之类的操作,那么检查将非常有用。

答案 5 :(得分:-1)

您可以使用Java Reflection来避免复制/粘贴/写入相同问题:

public Facility updateFacility(Facility newFacility, Facility oldFacility)
{
    String[] properties = {"City", "ContactEmail", "ContactFax", "ContactName"};
    for(String prop : properties) {
        try {
            Method getter = Facility.class.getMethod("get"+prop);
            Method setter = Facility.class.getMethod("set"+prop, getter.getReturnType());
            Object newValue = getter.invoke(newFacility);
            if (newValue != null)
                setter.invoke(oldFacility, newValue);
        } catch (NoSuchMethodException | 
                SecurityException | 
                IllegalAccessException | 
                InvocationTargetException ex) {
             throw new RuntimeException(ex);
        }
    }
    ...
}

现在,当您希望以这种方式更新Facility类中的新属性时,您可以简单地更改properties []数组。

编辑:如果使用getter方法的返回类型来查找setter方法,则不必假设Facility的属性都是相同的类型。

CAVEATS:在方法重命名时要小心!如果从Facility类重命名或删除方法,此代码将导致运行时错误。如果您必须更改Facility类的代码,则应考虑使用注释来指示应更新哪些属性。

相关问题