【问题标题】:Not using IF, FOR, CASE (...) for making decisions不使用 IF、FOR、CASE (...) 进行决策
【发布时间】:2016-01-24 06:57:14
【问题描述】:

我正在尝试编写一个类似于以下不使用任何这些表达式的过程:

if | while | for | case | default | continue | goto | && | || | catch 
| ternary operator ?: | ?? 

原因是当像度量(eclipse)这样的插件计算圈复杂度时,每个表达式都会根据路径的数量将圈复杂度增加一。

String getWeekday (int order) {
        switch (order) {
                case 0: return "Monday";
                case 1: return "Tuesday";
                case 2: return "Wednesday";
                case 3: return "Thursday";
                case 4: return "Friday";
                case 5: return "Saturday";
                case 6: return "Sunday"
                default: throw new IllegalArgumentException();
        }
}

对于这个简单的过程,由于案例语句的数量,圈复杂度实际上会很高,即使对于人脑来说并不复杂。

作为实践,我很好奇是否有可能创建一个包含尽可能多的决策的程序,主要使用这些或其他表达式(同时不要过度使用上述表达式——一两个就可以了)?

else | do | switch | try | using | throw | finally | return 
| object creation | method call | field access 

这会“愚弄”插件,使其认为 CC 低于应有的水平,因为路径更多,但它会忽略这些表达式。

【问题讨论】:

  • 如果可能的话,你为什么要通过制作最有可能由高度不可读的代码来欺骗插件
  • 该代码归结为map.get(order)
  • 如果没有casedefault,您如何使用switch,这是什么usingelse 也一样,没有 if 就不是合法关键字
  • 仅仅因为你对欺骗插件感到好奇并不会降低代码的圈复杂度。
  • 编译器不会优化大部分内容吗?

标签: java cyclomatic-complexity


【解决方案1】:

如果没有枚举,并且如果没有给定的“坏”关键字之一,IndexOutOfBoundsException(或 NegativeIndex...)也可以。

public class Day {
    String[] days = { "Monday" , /*...*/ "Sunday" };

    public String getDay(int i){
         try{
             return days[i];
         } catch(Exception e) {
             throw new IllegalArgumentException();
         }
   }

   public static void main(String... args){
       System.out.println(new Day().getDay(2));
  }
}

【讨论】:

    【解决方案2】:

    如果您对ArrayIndexOutOfBoundsException 而不是您的感到满意,那么例如以下内容会这样做

    enum Foo {
        Monday,
        Tuesday,
        Wednesdey,
        Thursday,
        Friday,
         Saturday,
        Sunday
    }
    
    String getWeekday (int order) {
        return Foo.values()[order].name();
    }
    

    它的圈复杂度可能是相同的。

    【讨论】:

    • 上述getWeekday()方法的圈复杂度是1,因为没有控制流语句,只有数组查找。
    【解决方案3】:

    第一个解决方案

    您可以为此使用enum

    public enum WeekDay {
        MONDAY,
        TUESDAY,
        WEDNESDAY,
        THURSDAY,
        FRIDAY,
        SATURDAY,
        SUNDAY;
    
        public static String getWeekday(int order) {
            return values()[order].name();
        }
    }
    

    如果你只需要第一个字母大写,你可以这样改变getWeekday方法:

    public static String getWeekday(int order) {
        String name = values()[order].name();
        return name.substring(0, 1) + name.substring(1).toLowerCase();
    }
    

    或者您可以像这样创建常量String 值:

    public enum WeekDay {
        MONDAY("Monday"),
        TUESDAY("Tuesday"),
        WEDNESDAY("Wednesday"),
        THURSDAY("Thursday"),
        FRIDAY("Friday"),
        SATURDAY("Saturday"),
        SUNDAY("Sunday");
    
        private String name;
    
        WeekDay(String name) {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    
        public static String getWeekday(int order) {
            return values()[order].getName();
        }
    }
    

    第二种解决方案

    您也可以定义 Map,正如 Kayaman 在他的评论中建议的那样,或 Guava BiMap(取决于您的需要)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-09-20
      • 2012-10-15
      • 1970-01-01
      • 1970-01-01
      • 2015-12-25
      • 2016-03-31
      • 2020-04-07
      相关资源
      最近更新 更多