sonarqube代码质量审核建议理解

最近开始着手组内开发规范的制定和执行,先从项目基础平台代码规范开始,从各个老项目中提取出公共功能模块代码搭建新的项目基础平台,后面的项目都基于该基础平台进行开发。

平台搭建完成后用SonarQube做代码静态检测,不出所料,有很多问题,而且有的问题还很低级,可以看出之前代码的编写和review是多么的不规范,和同事慢慢整理吧,同时我也边整理边把对代码规范的理解整理成文。


**- 1 -**

Throwable.printStackTrace(…) should not be called (AND) Standard outputs should not be used directly to log anything

打印日志应该使用专门的日志工具,比如Slf4j或Log4j来打印日志,因为使用Throwable.printStackTrace(…)或者System.Err或者System.out打印日志可能会无意间暴露敏感信息。

打印日志需要注意以下4点,如果不满足这4点则对于日志获取或保存存在隐患:

  1. 用户要能获取到打印的日志,如果使用控制台打印(writes to the standard outputs)(Syterm.out.print)将无法再次获取。
  2. 日志数据必须被真正的记录,如果打印到控制台是无法再次获取日志的。
  3. 日志格式需要统一,方便阅读。
  4. 注意不要暴露敏感信息,比如将密码原文打印到日志等。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 不建议使用
try {
// 不要使用标准输出到控制台的方式打印信息
System.out.println("My Message");
} catch(Exception e) {
// 不要使用printStackTrace打印错误日志
e.printStackTrace();
}

// 建议使用
try {
logger.log("My Message");
} catch(Exception e) {
logger.log("context", e);
}

**- 2 -**

Static non-final field names should comply with a naming convention

变量名命名应该按照规范编写,有利于团队协作开发:

  1. 常量使用大写字母+下划线格式
  2. 变量使用首字母小写+驼峰式格式
1
2
3
4
5
6
7
8
9
10
// 不建议使用
public final class MyClass {
private static String foo_bar;
}

// 建议使用
class MyClass {
private static String fooBar;
private static final String FOO_BAR;
}

**- 3 -**

Utility classes should not have public constructors

工具类或常量类(所有成员属性或方法均为静态,即不需要实列化)应该声明私有无参构造器覆盖默认的公开无参构造器,就算是抽象类,也应该声明私有无参构造方法。
因为当没有构造方法时,Java会隐含的定义一个公开的无参构造方法,而调用工具类的静态属性或方法时不需要实例化,所以,需要定义私有无参构造器防止工具类被无意的实例化。

不使用实例对象调用类的静态属性和方法的原因有以下2点:

  1. 不符合规范
  2. 使用实例对象会浪费资源(需要分配内存给实例对象)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 不建议使用
class StringUtils {
/*
* StringUtils是工具类,不需要实例化,
* 但是当前状态Java会默认隐含的定义一个公开的无参构造方法,
* 是不建议的
*/

// StringUtils只包含这个静态方法
public static String concatenate(String s1, String s2) {
return s1 + s2;
}
}

// 建议使用
class StringUtils {
// 增加私有的无参构造方法
private StringUtils() {
throw new IllegalStateException("Utility class");
}

public static String concatenate(String s1, String s2) {
return s1 + s2;
}
}

**- 4 -**

Composed “@RequestMapping” variants should be preferred

Spring4.3开始引入了更符合语义的ReqeustMapping的变型注解,即@GetMapping@PostMapping@PutMapping@PatchMapping@DeleteMapping,建议使用新的注解,比旧注解(@RequestMapping(method = RequestMethod.XYZ))在语义表达上更容易理解。

1
2
3
4
5
6
7
8
9
10
11
// 不建议使用
@RequestMapping(path = "/greeting", method = RequestMethod.GET)
public Greeting greeting(String name) {
...
}

// 建议使用
@GetMapping(path = "/greeting")
public Greeting greeting(String name) {
...
}

**- 5 -**

The diamond operator (“<>”) should be used

Java7引入了让泛型表达式更简洁的菱形符号,建议使用。旧代码需要在赋值符号(=)两端的表达式同时声明泛型类型,Java7之后Java可以使用类型推测机制推测出右边表达式的泛型类型,因此可以省略右边的泛型类型声明,仅使用<>即可,使得代码更简洁。

1
2
3
4
5
6
7
// 不建议使用
List<String> strings = new ArrayList<String>();
Map<String,List<Integer>> map = new HashMap<String,List<Integer>>();

// 建议使用
List<String> strings = new ArrayList<>();
Map<String,List<Integer>> map = new HashMap<>();

待续…