编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Sonar代码规范分析(sonar代码检查原理)

wxchong 2024-09-22 16:54:02 开源技术 23 ℃ 0 评论

写代码很多年, 自认为还算是个干净的人, 写的代码也是整整齐齐的, 但自从引入Sonar静态扫描后, 越来越觉得这基本功还得多练练。

项目中的代码,并不是出现问题无法执行, 而是出现问题后,需要调整感觉一顿乱码, 重构又感觉成本较大, 不处理补丁越打越多, 错误越来越多。

从现在起养成一个好习惯,在编码的时候就注意编写规范和业务逻辑,做好分层控制处理。


SonarQube支持连续检查实践。

在构建SonarQube平台时,我们从一开始就考虑了持续检查。因此,它附带了支持该实践所需的一切,质量门,泄漏管理,分支分析,并行报告处理,治理功能,高可用性,较短的反馈循环等。


一、问题集合

1、返回一个空集合而不是null

避免没有判断导致NPE, NPE会导致大量的Bug

// 反例
public static List<Result> getResults() {
  return null;                          
}


public static Result[] getResults() {
  return null;                          
}


// 正例
public static List<Result> getResults() {
  return Collections.emptyList();      
}
public static Result[] getResults() {
  return new Result[0];

2、集合判断是否为空

// 反例
 if (baseOrderViews.size() > 0) {
 }
// 正例
if (baseOrderViews.isEmpty()) {
 }
 
//最好用这个,直接用baseOrderViews.isEmpty()会有空指针的情况
 if (CollectionUtils.isEmpty(baseOrderViews)) {
 }

3、equals对象比较错误

反例:
DepSourceEnum.VIRTUAL.equals(lastDept.getSource())


正例:
DepSourceEnum.VIRTUAL.getKey().equals(lastDept.getSource())

4、InterruptedException异常处理不当

反例:
try {
    while (true) {
      // do stuff
    }
  }catch (InterruptedException e) { // Noncompliant; logging is not enough
    LOGGER.log(Level.WARN, "Interrupted!", e);
  }
  
正例:
try {
    while (true) {
      // do stuff
    }
  }catch (InterruptedException e) {
    LOGGER.log(Level.WARN, "Interrupted!", e);
    // Restore interrupted state...
    Thread.currentThread().interrupt();
  }

5、合并if判断表达式

反例:
if (behaviorPlanNum == 0 && deptDayPlanNum1 != 0 && deptDayExeNum1 == deptDayPlanNum1) {
  //每日凌晨3点之后才可同步微信日统计数据,不然可能出现无数据情况
  if (DateUtil.getCurrentHour(new Date()) >= 3) {
  
正例:
if (behaviorPlanNum == 0 && deptDayPlanNum1 != 0 && deptDayExeNum1 == deptDayPlanNum1 && DateUtil.getCurrentHour(new Date()) >= 3) {

6、关于public static固定变量定义问题

反例:
public static int STAT_SCALE = 4;


正例:
public static final int STAT_SCALE = 4;

7、重复try-catch

8、Boxing and unboxing should not be immediately reversed

避免连续装箱(创建int/Integer类型值的对象)和拆箱(将对象中原始值解出来)

反例:
staff.setCurReceptionNum(Long.valueOf(curChatNum).intValue());


正例:
Long receptionNum = Long.valueOf(curChatNum);
staff.setCurReceptionNum(receptionNum .intValue());

9、"BigDecimal(double)" should not be used

反例:
new BigDecimal(0.1)


正例:
BigDecimal.valueOf(d);
new BigDecimal("0.1");

10、Sections of code should not be commented out

不要在注释中出现大量的代码段,会使代码可读性变差

11、String literals should not be duplicated

字符串不应该重复

反例:(注意当前类中“createTime”字符串出现了4次)
sqlFilter.addSQLExpression("createTime", SQLExpression.between, new Object[]{startDate, endDate});
正例:
private static final String CREATE_TIME= "createTime";
sqlFilter.addSQLExpression("CREATE_TIME", SQLExpression.between, new Object[]{startDate, endDate});

12、Local variables should not be declared and then immediately returned or thrown

如果赋值变量直接return,那么直接return,不需要赋值

反例:
Long count = this.getCount(sqlFilter);
return count;


正例:
return this.getCount(sqlFilter);

13、Modifiers should be declared in the correct order

修饰词的顺序

反例:public final static String FAILED = "failed";


正例:public static final String FAILED = "failed";

14、不可变List和Map初始化方式不正确

  • Mutable fields should not be "public static"

可变字段不应该是public static

反例:

反例:
// 定义常量数组, 且会被轻易改变
public static final Integer[] GD_BALANCE_STATUS_SUCCESS = {1000, 5000};


正例: 
// 使用Collections.unmodifiableList禁止修改list
private static final Integer[] GD_BALANCE_STATUS_SUCCESS = new Integer[]{1000,5000};
public static List<Integer> getGdBalanceStatusSuccess() {
    return Collections.unmodifiableList(Arrays.asList(GD_BALANCE_STATUS_SUCCESS));
}
  • Double Brace Initialization should not be used

不应该使用双括号初始化

使用final修饰变量的目的是避免被修改,对于基本类型、String等普通类型变量用final修饰之后确实不可以被修改,但是List和Map被修饰之后虽然不能使用“=”重新赋值,但是可以使用add、remove、put等方法改变其中的元素,这就违背了我们使用final的初衷了。

反例:
public static final Map<String, String> map = new HashMap<String, String>(){{
	put("K1", "V1");
	put("K2", "V2");
	put("K3", "V3");
}};


正例:
	/**
	 * 声明常量List
	 */
	private static final List<String> ES_KEY_LIST = getEsKeyList();


	/**
	 * 声明常量Map
	 */
	private static final Map<String,String> TOTAL_COMPUTE_MAP = getTotalComputeMap();


	/**
	 * 初始化常量Map
	 */
	public static Map<String,String> getTotalComputeMap(){
		Map<String,String> map = new HashMap<>();
		map.put(ES_KEY_TOTAL_ORDER_ACTIVATE_RATE,ES_FORMULA_TOTAL_ORDER_ACTIVATE_RATE);
		return Collections.unmodifiableMap(map);
	}


	/**
	 * 初始化常量List
	 */
	public static List<String> getEsKeyList(){
		List<String> list = new ArrayList<>();
		list.add(ES_KEY_KEY);
		list.add(ES_KEY_COUNT);
		return Collections.unmodifiableList(list);
	}

15、去除无意义的 TODO标记

反例:

正例:

TODO是个快捷索引,快速定位待办项,需要跟踪问题并及时完成,然后清理TODO。

可以使用单行TODO, 也可以使用多行FIXME来的定义。

// TODO XX业务待实现,注意与XX业务影响

反例:

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表