如何减少 if-else 的深度?

How to reduce the if-else depth?

我有这个示例代码

public static ActionProcessable getActionProcessor(TaskType currentTaskType, UserAction userAction){
    String actionKey;
    if(userAction != null){
        if(currentTaskType != null){
            actionKey = buildKey(currentTaskType, userAction);
            if(dossierActions.containsKey(actionKey)){
                return dossierActions.get(actionKey);
            }
        }

        actionKey = buildKey(anyTaskType(), userAction);
        if(dossierActions.containsKey(actionKey)){
            return dossierActions.get(actionKey);
        }
    }

    return new NullActionProcessor();
}

在这个逻辑中,我有一个映射来通过组合键 TaskType 和 UserAction 存储 ActionProcessable。此方法将 return ActionProcessable 与输入 taskType 和操作。 TaskType 可以为空,所以在这种情况下我们只需要通过 userAction.

当我用声纳检查这段代码时,它说第三个 if 是 "Nested if-else depth is 2 (max allowed is 1)"

但我不知道如何让它变得更好。 有人给我建议吗?

您可以将 "if containsKey" 部分移出条件以删除代码重复:

public static ActionProcessable getActionProcessor(TaskType currentTaskType, UserAction userAction){
    if (userAction != null) {
        String actionKey = currentTaskType != null
            ? buildKey(currentTaskType, userAction)
            : buildKey(anyTaskType(), userAction);

        if (dossierActions.containsKey(actionKey)){
            return dossierActions.get(actionKey);
        }
    }

    return new NullActionProcessor();
}

现在,代码的意图看起来更清晰了(至少对我而言)

您还可以使第一个条件短路 and\or 使用三元 if 对于 containsKey,它会删除更多的 ifs,但会使代码更复杂一些人们。

public static ActionProcessable getActionProcessor(TaskType currentTaskType, UserAction userAction){
    if (userAction == null) { 
        return new NullActionProcessor();
    }

    String actionKey = currentTaskType != null
        ? buildKey(currentTaskType, userAction)
        : buildKey(anyTaskType(), userAction);

    return dossierActions.containsKey(actionKey)
        ? dossierActions.get(actionKey);
        : new NullActionProcessor();
}

选择你喜欢的,它们在技术上是相似的。

由于您没有指定具体的编程语言,还有一点要说:您的代码是空合并运算符用例的一个很好的例子。可悲的是,据我所知,Java 中有 none。在 C# 中,代码可能如下所示:

public static ActionProcessable GetActionProcessor(TaskType currentTaskType, UserAction userAction) {
    if (userAction == null) { 
        return new NullActionProcessor();
    }

    var actionKey = BuildKey(currentTaskType ?? anyTaskType(), userAction);
    return dossierActions[actionKey] ?? new NullActionProcessor();
}