深入探讨Java项目中最常见的错误,这些错误来自涵盖该言语的600多条规矩,同时考虑了质量和安全性。
译自7 Java Mistakes to Conquer,作者 Jonathan Vila 是 Sonar 的开发者倡导者。他是 Java 大师和西班牙 JBCNConf 和 DevBcn 会议的一起创始人,巴塞罗那 Java 用户组 (JUG) 的组织者,以及 BarcelonaJUG 的成员。
无可否认,整洁的代码是必不可少的 —— 共同、有目的、可适应和负责任的代码。询问任何开发人员,他们都会同意,在创建项目时,这应该是首要考虑的事项。但是,代码只会像它最单薄的环节一样好,正如SonarLint的遥测数据所显现的,在经过分析的很多项目中,仍然存在很多问题。
即便某些问题看起来微乎其微,但当涉及到软件的安全性、功用和保护时,它们可能会对软件产生严重影响。这就是为什么我编制了一份Java 项目中咱们发现的最常见错误的清单,涵盖了该言语的600 多条规矩,并考虑了质量和安全性。记住这些,你能够更好地为自己发明连续共同、有目的、可适应和负责任的代码 —— 全部以巨大的利益和低劳动强度。
一、已注释代码
已注释的代码只是对其可读性的挑战,因而应该删去以进步清晰度。这消除了读者的不确认性,由于读者很难判断代码是临时注释掉的还是应该直接删去。对此有一个有用的提示: 假如它不适用于提交的功用,请将其删去或取消注释(假如是临时禁用)。
下面是一个例子:
public void println(String x) {
if (getClass() == PrintStream.class) {
writeln(String.valueOf(x));
} else {
synchronized (this) {
print(x);
//newLine();
}
}
}
好消息是,假如今后需求注释的代码,你能够简单地从版别控制系统中检索出来。
二、疏忽的“TODO”符号
在源代码中留下这些注释,而源代码可能有很长的寿数,会导致不完整的代码,可能在多个方面影响软件。例如,在团队内进行协作时,一些成员可能不知道哪些功用将包含在最终发布中。这些符号还可能使人看起来似乎能够在今后处理,而不是现在实施这些部分,从而减少未来呈现错误的机会。此外,TODO块可能导致未来功用走漏。
这里有一个名为Apache Camel的项目的实践例子,其中引入了一个几乎十年前的TODO行。
SslHandler sslHandler = configureClientSSLOnDemand();
if (sslHandler != null) {
//TODO must close on SSL exception
//sslHandler.setCloseOnSSLException(true);
LOG.debug("Client SSL handler configured and added to the ChannelPipeline: {}", sslHandler);
addToPipeline("ssl", channelPipeline, sslHandler);
}
为防止这些问题,请不要添加新的待办事项块。相反,在提交最终代码前完成该功用 —— 或将这些任务记载到任务管理器中,以便清楚如安在未来处理它们。
三、重复的字符串字面量
重复的字符串会导致在有必要更改这些值以适应新条件时呈现额外工作或遗漏更改。相反,运用常量来存储字符串字面量。这使重构更简单,并进步了代码库的共同性。
如何做到这一点的示例:
// Compliant
private static final String ACTION = "action1";
public void run() {
prepare(ACTION);
execute(ACTION);
release(ACTION);
}
四、函数的高认知复杂度
更常见的是,咱们听说循环复杂度,它测量代码中运用的途径数量,并协助确认给定代码部分的阅览复杂度。但这个概念无法协助确认需求比条件句子或循环数量更多考虑的实践可保护性水平。
下降代码复杂性是使重构、修正和演进更简单的关键,由于开发人员花在阅览代码上的时刻远远多于编写代码的时刻。项目通常很难阅览或了解,这个问题使得难以了解其目的并处理保护和开展。开发人员应该出资于重构具有高认知复杂度的代码,以便代码库在长期内更简单了解和保护。
关于新代码,最好参考复杂性指标,并投入时刻将其下降到配置的阈值,该阈值应该满足低。
五. 未运用的元素
关于开发人员来说,在编写新功用时,很简单创建最终没有用处的代码元素。这些元素不会导致运行时错误或测试失败,因而即便它们需求被移除,也可能很难识别。但在最坏的情况下,它们可能迫使咱们重新考虑整个代码。
这些未运用的元素下降了代码的可读性,这使得更难精确找出代码的目的,并可能导致对其完成短少决心。将它们移除。查看未运用的代码,并删去不再有用的部分,或许考虑它们是否短少可能运用这些元素的代码。看一下:
public class MyClass {
private int foo = 42; //private field not used
public int compute(int a, int b) { //b argument not used
int c = 10; //local variable not used
return a * 42;
}
public int run() {
int value=10; //assignment not used
value=compute(2, 5);
}
}
六. 原始类型
在Java中,不要运用没有类型参数的泛型类型——这会防止在编译过程中进行类型查看和捕获不安全的代码,使全部在运行时可见。相反,运用具体的类型,让那些运用这些变量的用户能够了解真实期望的是什么,并在运行时消除意外。拜见下文:
// Compliant solution
List<String> myList;
Set<? extends Number> mySet;
七、抛出泛型异常
运用泛型异常会阻挠调用办法处理不同的系统生成异常和应用程序生成错误。为防止这种情况,创建一个自定义的异常系统,为调用者提供满足的信息,以便他们能够决定如何操作,并具有具体和差异化的缓存列表。
// Compliant
public void fooException(String bar) {
if (bar.isEmpty()) {
throw new EmpyValueException();
}
if (bar == "jello") {
throw new InvalidArgumentException();
}
System.out.println("This is bar: " + bar);
}
防止错误导致更好的软件
一切开发人员在编程时都希望最终产出高质量、牢靠、可适应和安全的产品。但是,这些看似细小的日常错误很简单阻碍完成这个方针。注意这些问题的产生,并尽最大努力防止它们,将只会为你发明一种洁净的代码软件,这种软件能够支持企业的昌盛开展。
本文在云云众生(yylives.cc/)首发,欢迎大家拜访。