[英]Can high cyclomatic complexity (warnings) be avoided when using switch-case on a large enum?
假设一个方法根据相当大的枚举值选择一个动作。 我们的声纳现在抱怨这种方法具有很高的圈复杂度(当然是关于案例陈述的数量)。
我知道,大型switch case语句在OOP中并不是最好的样式,但有时使用它们(在我的情况下是一个评估运算符标记的解析器)而不是构建复杂的对象树。
我现在关注如何处理? 是否有任何设计模式可以有意义地拆分这种开关盒? 或者我(并且应该)将该类排除在测量CC之外(因为可能有其他方法可以轻松避免高CC)?
这不是一件非常重要的事情; 我只是不喜欢我的项目有警告,我无法删除; o)
编辑:代码示例
String process()
String fieldName = this.getField() != null ? this.getField().getSchemaName() : null;
String result = "";
switch (op) {
case PHRASE:
result = "";
if(!value.isEmpty() && value.get(0) != null) {
result = value.get(0).toString();
}
break;
case EQUALS:
case GT:
case GTE:
case LT:
case LTE:
case NOT_EQUALS:
result = prepareSingleParameterStatement(fieldName);
break;
case BETWEEN_EXC:
case BETWEEN_INC:
result = prepareDoubleParameterStatement(fieldName);
break;
case IN:
case NOT_IN:
case ALL_IN:
result = prepareCollectionStatement(fieldName);
break;
case AND:
case OR:
result = prepareLogicalStatement();
break;
case NOT:
result = prepareNotStatement();
break;
default:
break;
}
return result;
}
您可以使用枚举来构建状态机,而不是使用大型switch语句。 你要做的是让代码解析每个case块中的文本,并将其放在每个枚举状态的方法中。
从例子
enum States implements State {
XML {
public boolean process(Context context) {
if (context.buffer().remaining() < 16) return false;
// read header
if(headerComplete)
context.state(States.ROOT);
return true;
}
}, ROOT {
public boolean process(Context context) {
if (context.buffer().remaining() < 8) return false;
// read root tag
if(rootComplete)
context.state(States.IN_ROOT);
return true;
}
}
}
public void process(Context context) {
socket.read(context.buffer());
while(context.state().process(context));
}
我建议用hashmap / dictionary和命令对象替换一个大的开关:
Map<Op, Command> ops = new EnumMap<op>{{
//initialize with different command objects implementing same interface
}};
command = ops.get(result);
result = command.prepare();
您可以将逻辑移动到具有共享接口的命令类(在exammple中使用MyCommandInterface),并在枚举值和枚举中的命令之间进行映射。
MyCommand实现MyCommandInterface(已编辑)
public enum MyEnum {
MyVALUE(new MyCommand()), MyVALUE2(new MyCommand());
private MyCommandInterface command;
public MyCommandInterface getCommand() {
return command;
}
private MyEnum(MyCommandInterface command) {
this.command = command;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.