【问题标题】:What's the best way to perform a 1 line functionality in java 8 based on a boolean flag?基于布尔标志在 java 8 中执行 1 行功能的最佳方法是什么?
【发布时间】:2021-04-11 05:05:07
【问题描述】:

我有一个布尔标志,基于它我想执行 1 行功能,比如增加变量或调用对象的方法等。在 java 中使用 min cognitive complex 做到这一点的最佳方法是什么8?

// Objects a is initialized;
// int x, y;
// boolean flag;
if (flag) {
    a.doSomething1();
} else {
    a.doSomethingElse1();
}

// want to check multiple times like this
if (flag) {
    a.doSomething2();
} else {
    a.doSomethingElse2();
}

if (flag) {
    x++;
} else {
    y++;
}

在 java 8 中是否有一种更简单的方法可以通过降低认知复杂性来做到这些?因为我遇到了这个 sonarlint 规则的问题:方法的认知复杂性不应该太高如果有太多的 if else 语句

--------- 编辑 ------

我的代码看起来像这样:

void myMethod(List<SomeClass> list) {
    for (SomeClass a : list) {
        SomeClass a;
        String name = a.getName();
        boolean flag = a.getFlag();
        switch(name) {
            case "name1":
                if (flag) a.doSomething1() else a.doSomethingElse1();
                break;
            case "name2":
                if (flag) a.doSomething2() else a.doSomethingElse2();
                break;
            //.... similar otherCases
        }
    }
} 

所有这些都在增加认知复杂性

【问题讨论】:

  • 只需将所有内容放在同一个ifelse 中。还是你在问别的?
  • 我不确定我是否理解您想要在此处简化的内容。 if(a) b else c 已经很短了。
  • 如果你的意思是这样做 if (flag) x++ else y++ 不会解决我的问题,因为它仍然会通过任何嵌套因素增加声纳 lint 认知复杂性 - rules.sonarsource.com/java?search=cognitive%20complexity
  • 一般来说,如果有一个包含非平凡逻辑的循环,则将主体提取到不同的函数。这也有助于遵守其他规则,例如有限的嵌套级别。如果您有多个布尔标志,您可能能够提取相等的部分和不同的部分,并使用模板方法或策略模式等模式。但选择哪一种取决于多种因素,不能一概而论。
  • 跟进@Hulk 的评论 - 请注意您编辑的示例如何从a 中提取数据,然后使用这些数据来决定要做什么。此行为应在 SomeClass 本身内。另见:告诉,不要问

标签: java java-8 sonarqube sonarlint


【解决方案1】:

回答你的具体例子:

由于一切都只取决于SomeClass 的成员,因此逻辑也应该是此类的一部分。一种方法是:

abstract class SomeClass {               

    public void doIt() {
        String name = this.getName();
        switch (name) {
        case "name1":
            this.doName1();
            break;
        case "name2":
            this.doName2();
            break;
        }
    }
    
    private void doName1() {
        if (this.getFlag())
            this.doSomething1();
        else
            this.doSomethingElse1();
    }

    private void doName2() {
        if (this.getFlag())
            this.doSomething2();
        else
            this.doSomethingElse2();
    }
    
    abstract protected String getName();

    abstract protected boolean getFlag();

    abstract protected void doSomething1();

    abstract protected void doSomething2();

    abstract protected void doSomethingElse1();

    abstract protected void doSomethingElse2();
}

myMethod 可以是任一

void myMethod(List<SomeClass> list) {
    for (SomeClass a : list) {
        a.doIt();
    }
}

或者改写为

void myMethod(List<SomeClass> list) {
    list.forEach(SomeClass::doIt);
}

如果您愿意,但这主要取决于风格/个人偏好。


从那时起,您可以开始考虑将以12 结尾的方法拆分为单独的策略对象。

还要注意我们是如何突然只使用一种来自外部的方法——这可以用来减少SomeClass 的公共接口,对于具体的例子,我们只需要doIt() 是公共的。这是通常被称为“告诉,不要问”的原则的应用。避免向对象询问其字段的内容,以根据这些值做出决策。相反,告诉他们你想要发生什么,并将细节留给他们。

【讨论】:

    猜你喜欢
    • 2014-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    • 2012-04-17
    • 1970-01-01
    相关资源
    最近更新 更多