# 代码质量控制和代码质量相关工具说明
Posted 爱码代码的喵
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了# 代码质量控制和代码质量相关工具说明相关的知识,希望对你有一定的参考价值。
代码质量检测工具及检测说明
代码质量与规范
高质量代码的优势
- 易读性、可维护性高
- 安全性、可测试性高
- 高内聚低耦合方便功能扩展
代码质量目标
代码质量管控
- 规范化 : 建立代码规范与
Code Review
制度 - 自动化 :使用工具自动检查代码质量
- 流程化 :将代码质量检查与代码流动过程绑定
- 中心化 :以团队整体为视角,集中管理代码规范,并实现质量状况透明化
SonarQube
- 它是一个持续代码质量(
Continuous Code Quality
)分析工具,包括静态分析和动态分析; - 支持
20
多种语言; - 它能够发现代码中可能隐含的
bug
、安全隐患(vulnerability
)、不规范代码(Code Smells
); - 可以对开发代码进行持续分析,能够查看各种数值的历史走向;
- 具有极高的可定制性,可以通过插件扩展分析能力,可以定制更严格或宽松的质量阀门(
Quality Gate
)及Quality Profile
;
SonarQube 使用手册 https://guide.daocloud.io/dcs25/sonarqube-22385147.html
SonarQube
质量规则页面
代码检测工具
SonarLint
SonarLint
是一个免费的开源IDE
扩展,可识别并帮助您在编写代码时解决质量和安全问题。像拼写检查器一样,SonarLint
会显示缺陷并提供实时反馈和清晰的修复指导,以便从一开始就提供干净的代码。- 官网:https://www.sonarlint.org/
Idea SonarLint
插件使用
Alibaba代码规约插件
- 阿里代码规范检测插件:着重检查代码书写规范
Idea
使用 插件如下
Idea 自带的代码检查工具
- 检查代码的规范
SonarLint 所有检测结果修复示例
- 所有规则可以在这个文档中查找,以缺陷的方式定义了所有代码检查规则
- 包含规则描述、以及正反示例。
SonarLint 检测结果说明、示例
SonarLint: Use the built-in formatting to construct this argument.
-
翻译:将连接字符串传递给日志记录方法也可能导致不必要的性能损失,因为每次调用该方法时都会执行连接,无论日志级别是否低到足以显示消息。应该使用内置的字符串格式而不是字符串连接,如果消息是方法调用的结果,则应该完全跳过前置条件,而应该有条件地抛出相关异常。
-
反例
String message = "Hellow World!";
logger.info("Test Info message:"+message);
- 正例
String message = "Hellow World!";
String format = String.format("Test Info message:%s", message);
logger.info(format);
SonarLint: Replace this use of System.out or System.err by a logger.
- 翻译:使用专门的日志框架操作日志
- 反例
System.out.printf("Hellow");
- 正例
private static final Logger logger = Logger.getLogger(String.valueOf(Demo.class));
logger.info("Hellow");
SonarLint: Invoke method(s) only conditionally.
- 翻译:构建代码,将静态或预先计算的值传递给前置条件、条件检查和记录调用。方法中参数直接是计算之后的结果,而不是计算并得到结果。
- 反例
logger.info(String.valueOf((char)c));
- 正例
String s2 = String.valueOf((char) c);
logger.info(s2);
SonarLint: Define and throw a dedicated exception instead of using a generic one.
- 翻译:使用自己定义的异常类进行抛出异常错误等,不要使用原始的
Exception
等。 - 反例
throw new Exception("Test");
- 正例
public class MyException extends RuntimeException
public MyException()
public MyException(String message)
super(message);
throw new MyException("Hellow");
SonarLint: String contains no format specifiers.
- 翻译:字符串不包含格式说明符。
- 反例
String message = "Hellow Test!";
logger.info(String.format("method error: ",message));
- 正例
String message = "Hellow Test!";
logger.info(String.format("method error: %s",message));
SonarLint: Either re-interrupt this method or rethrow the “InterruptedException”.
- 翻译:绝不应该在代码中忽略
interruptedexception
,在这种情况下,简单地将异常计数记录为“忽略”。InterruptedException
的抛出将清除线程的中断状态,因此,如果异常没有得到正确的处理,那么线程被中断的事实就会丢失。相反,interruptedexception
应该被重新抛出——立即或在清除方法的状态之后——或者应该通过调用thread .interrupt()
重新中断线程,即使这是一个单线程的应用程序。任何其他操作都有延迟线程关闭的风险,并丢失线程被中断的信息——可能没有完成其任务。 - 反例
private void dealAddNum()
try
num++;
Thread.sleep(100);
catch (InterruptedException e)
log.info(e.getMessage());
- 正例:
private void dealAddNum()
try
num++;
Thread.sleep(100);
catch (InterruptedException e)
log.info(e.getMessage());
Thread.currentThread().interrupt();
SonarLint: Add a nested comment explaining why this method is empty, throw an UnsupportedOperationException or complete the implementation.
-
翻译:方法没有方法主体有以下几个原因:这是一个无意的疏忽,应该加以修正,以防止生产中出现意外的行为。它还没有得到支持,或者永远不会得到支持。在这种情况下,应该抛出
UnsupportedOperationException
。该方法是一个故意为空的覆盖。在这种情况下,一个嵌套的注释应该解释空白覆盖的原因。 -
反例:
@Override
public void setProperties(Properties properties)
- 正例:
@Override
public void setProperties(Properties properties)
throw new UnsupportedOperationException();
SonarLint: “ThreadLocal” variables should be cleaned up when no longer used
- 翻译:定义的线程局部变量在使用完之后,需要销毁。一旦持有线程不再活着,
ThreadLocal
变量就会被垃圾收集。在重用持有的线程时(在使用线程池的应用服务器上就是这种情况)可能会发生内存泄漏。 - 反例:使用后没有销毁。
private static final ThreadLocal<SimpleDateFormat> DATETIME_FORMATTER = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
- 正例
private static final ThreadLocal<SimpleDateFormat> DATETIME_FORMATTER = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
public void test1()
try
// do something
catch(Exception e)
// do something
finally
DATETIME_FORMATTER.remove();
SonarLint: Extract this nested try block into a separate method.
- 翻译:嵌套的
try/catch
块严重影响了源代码的可读性,因为它使理解哪个块捕获哪个异常变得非常困难。 - 反例:
@Test
public void test1()
try
try
catch (NullPointerException e)
logger.info(e.getMessage());
catch (Exception e)
logger.info(e.getMessage());
- 正例:
@Test
public void test1()
try
logger.info("test messages!");
catch (Exception e)
logger.info(e.getMessage());
SonarLint: Replace the usage of the “instanceof” operator by a catch block.
- 翻译:应该使用适当类型的多个
catch
块,而不是捕获一般异常,然后对类型进行测试。 - 反例:
try
// do somethings
catch (Exception e)
if (e instanceof InvocationTargetException)
logger.error(LogConstant.LOG_FAILURE_PREFIX + (((InvocationTargetException) e).getTargetException()).getMessage());
else
logger.error(LogConstant.LOG_FAILURE_PREFIX + e.getMessage());
return result;
- 正例:
try
logger.info("test!");
catch (NullPointerException nullPointerException)
logger.info(nullPointerException.getMessage());
catch (IllegalArgumentException illegalArgumentException)
logger.info(illegalArgumentException.getMessage());
SonarLint: Use “java.util.Random.nextInt()” instead.
- 翻译:没有必要将
Random
的nextDouble
方法的输出乘以一个随机整数。使用nextt
方法代替。当随机的任何返回浮点值的方法的返回值被转换为整数时,该规则会引发一个问题。 - 反例:
user.setGender(((int)(10 * Math.random())) % 2 );
- 正例:
Random random = new Random();
user.setGender(random.nextInt(10) % 2 );
SonarLint: Mutable fields should not be “public static”
-
可变字段不应该是
public static
-
不合规
public interface MyInterface
public static String [] strings; // Noncompliant
public class A
public static String [] strings1 = "first","second"; // Noncompliant
public static String [] strings2 = "first","second"; // Noncompliant
public static List<String> strings3 = new ArrayList<>(); // Noncompliant
// ...
- 合规
private static final String [] COLUMN_NAMES = new String[]"date","customerNumber","customerName",
"account","emailAdress","mobilePhoneNumber","emailStatus";
public static List<String> getColumnNames()
return Collections.unmodifiableList(Arrays.asList(COLUMN_NAMES));
- 问题分析:请注意,使可变字段(例如数组)为
final
将阻止重新分配变量,但这样做不会影响数组内部状态的可变性。可以改变的类型如果非常有必要声明为‘public static’
可以通过上述Collections.unmodifiableList
方式实现。
代码示例:https://blog.csdn.net/qq_37248504/article/details/115266913
以上是关于# 代码质量控制和代码质量相关工具说明的主要内容,如果未能解决你的问题,请参考以下文章