Page 215 - 《软件学报》2026年第3期
P. 215

1178                                                       软件学报  2026  年第  37  卷第  3  期


                 推荐方法的适应度函数. 代码质量指标能够评估开发人员所感知的代码质量, 识别设计缺陷并推荐从开发人员的
                 角度来进行有意义的代码重构. 基于现有研究              [58–60] , 我们考虑两种类型的代码质量指标, 用于自动衡量转换前后的
                 代码质量. 接下来, 我们将描述这两类代码质量指标.

                                          表 2 CoDefense 的代码结构归一化规则的描述

                  ID 等价结构转换规则                       描述                     例子 (转换前)        例子 (转换后)
                                                                        for (i=0;i < 9;i++){  i=0;
                  1      Loop s1          for和while循环语句的等价转换
                                                                        Body;}         while (i<9) {Body;i++;}
                                                                        i=0;           i=0;
                  2     Branch s2      if-else和switch-case条件语句的等价转换     if (i==1){     switch(i){
                                                                        Body;          case1:
                                                                        }              Body;}
                                         是否使用条件语句中的逆否表达式                if (a>b){      if(!(a<=b)){
                  3     Branch s3
                                            (>, <, >=, <=, ==, !=, &&, ||)  Body;}     Body;}
                                                                        if (a > b){Body;}  if ((a > b)||(a==b)){
                  4     Brabch s4          是否拆分多条件语句(||, &&)
                                                                        if (a==b){Body;}  Body;}
                  5      Type s5             基础类型转换(int, float)         int a=0;       long a=0;
                                                                        int a;         Body;
                  6     Variable s6  局部变量声明的位置(代码开始处、首次使用处)             Body;          int a;
                                                                        a=c+d;         a=c+d;
                                                                        int a;
                  7     Variable s7     局部变量声明和初始化是否在同一行                               int a=0;
                                                                        a=0;
                                                                        int a=0;
                  8     Variable s8    相同类型的变量定义/声明是否在同一行                              int a, b=0, 1;
                                                                        int b=1;
                                                                                       int c=10;
                  9     Constant s9  常量和变量的等价转换(int, float, double, long, String) int a=b+10;
                                                                                       int a=b+c;
                                                                        a++;           a+=1;
                  10  In/Decrement s10    自增/减操作的等价转换(++,     −−)
                                                                        – –b;          b=b–1;
                                         二元操作符两端的操作数是否交换                if (a > b){Body1;}  if (b < a){Body1;}
                  11    Operand s11
                                          (<, >, >=, <=, ==, !=, &&, ||, +, *)  if (c && d){Body2;} if (d && c){Body2;}
                                               是否使用复合赋值                 a*=10;         a=a*10;
                  12   Combined s12
                                       (+=, −=, *=, /=, %=, <<=, >>=, &=, |=, ^=)  b%=2;  b=b%2;
                  13     Curly s13              是否省略花括号                 if (a > b){    if (a > b)
                                                                        b+=1;}         b+=1;

                    (1) 代码复杂度. 降低代码复杂度是代码重构的主要目标之一                    [60] . 我们使用  WMC (weighted methods per
                 class) [61] 指标来评估类的复杂度. WMC   的计算方式为给定类内所有方法的            McCabe’s cyclomatic complexity [62] 的总
                 和. 具体来说, 给定代码, 我们首先需要获取其控制流图, McCabe’s cyclomatic complexity         的计算公式为     E − N +2,
                 其中,  E  表示控制流图的边的数量,       N  表示控制流图的节点的数量. WMC         越高, 代码复杂度越高.
                    (2) 代码可读性. 代码可读性是软件工程领域比较关注的一个重要代码质量属性, 可读性更高的代码能提高开
                 发人员对于代码的可理解性. 为了测量可读性质量属性, 我们利用了两个最先进的指标. 第                            1  个指标是  B&W  [59] ,
                 它利用代码结构属性        (例如行的长度、分支的数量等) 来衡量代码的可读性. 第                2  个指标是   SRead [63] , 它利用了一
                 组完全基于代码词典分析的特征           (例如变量名的特异性、代码连贯性等) 来衡量代码的可读性.
                    与现有工作保持一致        [15,16] , CoDefense 会依此选择表  2  中定义的代码结构转换规则, 以执行代码结构归一化
                 处理. 针对每一条选定的代码结构转换规则, 源代码中可能存在多个潜在的应用位置, CoDefense 则依据它们在代
                 码中出现的位置顺序进行排序, 并依次对各个代码位置应用当前的代码结构转换规则. 对于每一条给定的代码结
                 构转换规则与特定代码位置, CoDefense          首先会评估转换前的代码质量指标             Quality  = [WMC before ,B&W before ,
                                                                                    before
                 SRead before ], 然后在该代码位置应用特定代码结构归一化规则得到转换后的代码, 并重新计算相应的代码质量指标
                 Quality after  = [WMC after ,B&W after ,SRead after ]. 为了量化代码结构转换对代码质量的影响, CoDefense 采用了一种代码
   210   211   212   213   214   215   216   217   218   219   220