一、代码复杂度问题
1、类的复杂度过高。
说明:Split this class into smaller and more specialized ones to reduce its dependencies on other classes from 24 to the maximum authorized 20 or less.
原因:类之间的耦合度过高,引用了太多其他的类,
错误示例:
class Foo { // Noncompliant - Foo depends on too many classes: T1, T2, T3, T4, T5, T6 and T7
T1 a1; // Foo is coupled to T1
T2 a2; // Foo is coupled to T2
T3 a3; // Foo is coupled to T3
public T4 compute(T5 a, T6 b) { // Foo is coupled to T4, T5 and T6
T7 result = a.getResult(b); // Foo is coupled to T7
return result;
}
public static class Bar { // Compliant - Bar depends on 2 classes: T8 and T9
T8 a8;
T9 a9;
}
}
修改建议:根据面向对象的单一职责进行设计,进行降耦。
2、多重循环嵌套
说明:代码块中包含多个if、for、while、switch,影响阅读,难以维护
原因:Nested if
, for
, while
, switch
andtry
statements is a key ingredient for making what's known as "Spaghetti code".Such code is hard to read, refactor and therefore maintain.
错误示例:
public void process() {
if (condition1) { // Compliant - depth = 1
/* ... */
if (condition2) { // Compliant - depth = 2
/* ... */
for(int i = 0; i < 10; i++) { // Compliant - depth = 3, not exceeding the limit
/* ... */
if (condition4) { // Non-Compliant - depth = 4
if (condition5) { // Depth = 5, exceeding the limit, but issues are only reported on depth = 4
/* ... */
}
return;
}
}
}
}
}
二、BUG风险
1、声明应该使用Java集合接口,而不是具体的实现类,如“LinkedList”
说明:声明应该使用Java集合接口,而不是具体的实现类,如“LinkedList”
原因:定义良好的接口来隐藏实现细节。
错误示例:
public class Employees {
private HashSet<Employee> employees = new HashSet<Employee>(); // Noncompliant - "employees" should have type "Set" rather than "HashSet"
public HashSet<Employee> getEmployees() { // Noncompliant
return employees;
}
}
解决建议:
public class Employees {
private Set<Employee> employees = new HashSet<Employee>(); // Compliant
public Set<Employee> getEmployees() { // Compliant
return employees;
}
}
2、实体工具类应当隐藏其构造器
说明:实用工具类,静态成员的集合,其目的并非要实例化。应该没有公共构造函数。
错误示例:
class StringUtils { // Non-Compliant
public static String concatenate(String s1, String s2) {
return s1 + s2;
}
}
修改建议:
class StringUtils { // Non-Compliant
privte StringUtils(){
}
public static String concatenate(String s1, String s2) {
return s1 + s2;
}
}
3、字符创比较上应该防止空指针异常
说明:字符创比较上应该考虑到空指针异常的情况,一个变量在与字符串比较时,应当把字符串放在左边。
错误示例:
String myString = null;
System.out.println("Equal? " + myString.equals("foo")); // Non-Compliant - will raise a NPE
System.out.println("Equal? " + (myString != null && myString.equals("foo"))); // Non-Compliant - null check could be removed
正确示例:
System.out.println("Equal?" + "foo".equals(myString)); // Compliant - properly deals with the null case
三、可读性问题
1、用isEmpty()去做容器的空或者非空判断。
说明:Use isEmpty() to check whether the collection is empty or not.
原因:增加可读性。
错误示例:
if (myCollection.size() == 0) { // Non-Compliant
/* ... */
}
修改建议:
if (myCollection.isEmpty()) { // Compliant
/* ... */
}
2、删除没有用的import、field、class、method。
说明:If a private field is declared but not used in the program, it can be considered dead code and should therefore be removed.This will improve maintainability because developers will not wonder what the variable is used for.
原因:增加可维护性。
修改建议:删除无用代码块、申明、方法和引用。
3、if语句被拆分不利于可读
说明:Merging collapsible if
statements increases the code's readability.
错误示例:
if (file != null) {
if (file.isFile() || file.isDirectory()) {
/* ... */
}
}
修改建议:
if (file != null && isFileOrDirectory(file)) {
/* ... */
}
private static boolean isFileOrDirectory(File file) {
return file.isFile() || file.isDirectory();
}
3、方法内多个return出口
说明:Having too many return statements in a method increases the method's essential complexity because the flow of execution is broken each time a return statement is encountered. This makes it harder to read and understand the logic of the [method|function].
错误示例:
public boolean myMethod() { // Non-Compliant as there are 4 return statements
if (condition1) {
return true;
} else {
if (condition2) {
return false;
} else {
return true;
}
}
return false;
}
解决建议:定义一个return,赋值,统一返回。
4、修改了入参
说明:修改了入参降低了代码的可读性,丢失了原始参数的值。
原因:参数应当是final的
错误示例:
class MyClass {
public String name;
public MyClass(String name) {
name = name; // Noncompliant - useless identity assignment
}
public int add(int a, int b) {
a = a + b; // Noncompliant
/* additional logic */
return a; // Seems like the parameter is returned as is, what is the point?
}
public static void main(String[] args) {
MyClass foo = new MyClass();
int a = 40;
int b = 2;
foo.add(a, b); // Variable "a" will still hold 40 after this call
}
}
5、用equalsIgnoreCase()方法替代字符串的无视大小写比较。
说明:Replace these toUpperCase()/toLowerCase() and equals() calls with a single equalsIgnoreCase() call.
错误示例:
boolean result1 = foo.toUpperCase().equals(bar); // Non-Compliant
boolean result2 = foo.equals(bar.toUpperCase()); // Non-Compliant
boolean result3 = foo.toLowerCase().equals(bar.LowerCase()); // Non-Compliant
正确示例:
boolean result = foo.equalsIgnoreCase(bar); // Compliant
解决建议,利用一个临时变量充当需要变动的参数。
四、异常处理
1、定义一个专门的异常用于异常处理
说明:Using such generic exceptions as Error
, RuntimeException
,Throwable
, andException
prevents calling methods from handling true, system-generated exceptions differently than application-generated errors.
错误示例:
public void foo(String bar) throws Throwable { // Non-Compliant
throw new RuntimeException("My Message"); // Non-Compliant
}
修改建议:定义一个自己的异常类继承Exception用于包装RuntimeException。
2、单个方法不要跑出多个未处理的异常