在编程的世界中,我们总是不断追求更高的性能,更优雅的设计,以及更复杂的特性。然而,我们不应忽视一个基本且重要的原则——代码的可读性。那么究竟何谓代码的可读性?顾名思义,代码可读性是指代码可理解的程度,是代码作者通过代码这个媒介,将需要表达的信息输出到读者脑中的能力。所以有的人说好的代码必然有清晰完整的注释,也有人说代码即注释,是代码简洁之道的最高境界,后者的观点飞哥持保留意见,毕竟真正能够做到代码即注释的有几人呢?
我们先看个例子:
public StepExitEnum doExecute(StepContext stepContext) throws Exception {
String targetFilePath = this.getOriginFilePath(stepContext.getJobContext());//获取目标路径
File targetDir = new File(targetFilePath);
if (!targetDir.exists()) {
targetDir.mkdirs();//如果不存在目录则创建
}
String encryptedFilePath = this.getEncryptedFilePath(stepContext.getJobContext());//获取加密文件路径
String fileName = this.getFileName(stepContext);//获取文件名
File[] encryptedFiles = new File(encryptedFilePath).listFiles(this.buildFilenameFilter(fileName));//过滤文件
FileEncryptor dencryptor = this.buildFileEncryptor(stepContext);//创建FileEncryptor
Stream.of(encryptedFiles)
.forEach(encryptFile -> {
File targetFile = new File(targetFilePath, encryptFile.getName());
dencryptor.invoke(encryptFile, targetFile);//解密文件
});
return StepExitEnum.CONTINUING;
}
这种代码很常见,耐着性子其实也容易看懂:创建目录->读取加密文件->解密文件,就当前来说其实满足了业务需求也就可以了,但不够优雅;从长期来讲,这会产生bad smell,首先,“如果不存在目录则创建”、“获取文件名”这类注释有何意义?有可能这是coder当时的方案思路,但是否真的需要?它确确实实会影响看到这段代码的程序员的注意力了,但往往却并没有让程序员获取到任何有价值信息;其次,若想要理解doExecute这个方法的目的,必须通读代码,而开发人员也许只是想知道它做了什么事;最后,这个方法如果某一行出问题了,那么影响范围是整个业务流程。如果后期需要改动,大部分人可能会增加条件判断,或是在后面继续追加代码实现,最后会导致越来越难以阅读,这其实也就是“能运行就不要动它”这个梗的根源了,因为没人能读明白它到底做了什么,但又不得不改。
那究竟如何才能提高代码的可读性?毕竟代码可读性作为团队协作开发的前提,是软件可维护性的前提,是代码评审的前提,也是代码评审中的核心关注点之一。
1、 抽象,合理的业务逻辑抽象
“一个方法只应该做一件事”,这依赖coder对业务逻辑、对功能实现的深入理解和合理抽象,这才能清晰的区分出各个功能的边界,或者说是如何定义这件“事”。
合理的抽象,从功能角色、职责划分上就很清晰,有了这个基础,才能清晰的编写业务逻辑代码,而不是堆砌各种条件判断和循环,同时带着两条斜杠和注释,这是可读性的基础。
2、 各司其职,职责单一
一个方法只做一件事,扩展到一个类也如此,职责单一,归根结底还得基于合理的抽象,所以,它其实是抽象的一种具体体现,二者总是相辅相成。
3、 使用清晰、简洁的命名:
变量和函数的命名是代码可读性的关键。命名应该简洁且具有描述性,能够清晰地表达其用途。避免使用模糊或者过于简化的命名。
4、 保持适当的注释:
注释是提高代码可读性的重要手段。对于复杂的逻辑和算法,适当的注释能够帮助读者理解代码的目的和工作原理。同时,注释也应该保持简洁和清晰,避免过多的解释。
5、 遵循编码规范:
各种编程语言都有一套推荐的编码规范,如Python的PEP8,Java的Google Java Style Guide等。这些规范不仅有助于保持代码的一致性,也有助于提高代码的可读性。
6、 使用有意义的空格和格式化:
在代码中使用适当的空格和格式化可以帮助读者更好地理解代码的结构和逻辑。例如,使用空格来分隔变量和函数名,使用空行来分隔不同的代码块等。
7、 限制代码行长度:
过长的代码行往往难以阅读和理解。一般来说,限制代码行的长度可以有助于提高代码的可读性。大多数的IDE和编辑器都提供了代码行限制的功能。
基于以上建议,我们再来看看以下代码:
// 类名:RegexValidator
// 函数名:validateString
// 函数功能:正则验证字符串
// POM依赖包:无
import java.util.regex.Pattern;
public class RegexValidator {
/**
* 正则验证字符串
* @param regex 正则表达式
* @param str 待验证的字符串
* @return 是否匹配正则表达式
*/
public static boolean validateString(String regex, String str) {
if (regex == null || str == null) { // 检查入参是否为空
throw new IllegalArgumentException("Regex and string cannot be null"); // 抛出异常,正则表达式和字符串不能为空
}
Pattern pattern = Pattern.compile(regex); // 编译正则表达式
return pattern.matcher(str).matches(); // 使用正则表达式匹配字符串,并返回结果
}
}
// 函数示例
// 正则验证字符串示例
// 入参:regex,正则表达式;str,待验证的字符串
// 出参:isValid,是否匹配正则表达式
// 调用示例:
// String regex = "\\d+";
// String str = "12345";
// boolean isValid = RegexValidator.validateString(regex, str);
// System.out.println(isValid);
// 输出结果:例如,通过正则表达式"\\d+"验证字符串"12345",结果为:true
// 则输出结果为:true
通过分析,不难发现:
1、命名:类名RegexValidator,函数名validateString都清晰明了,可以让人一眼看出它们的用途。
2、注释:在validateString函数上方,有一段详细的注释,解释了函数的功能、参数和返回值。这可以帮助读者理解代码的功能。
3、异常处理:在函数内部,对输入参数进行了空值检查,并抛出了IllegalArgumentException异常,这使得读者能够清楚地知道如果输入为空值会发生什么。
4、示例调用和输出:在代码的最后部分,提供了一个示例调用和输出结果的注释,这使得读者能够更容易地理解如何使用这个函数,以及它的预期输出是什么。
5、代码规范性:代码的格式很规范,缩进、空格等都符合Java的编码规范,这有助于提高代码的可读性。
综上,这是一个可读性非常好,很易于理解和使用的代码。而这段代码则是有全栈式全自动件开发工具soflu软件机器人推出的FuncGPT(慧函数)生成。作为飞算SoFlu软件机器人的一个重要组成部分,FuncGPT(慧函数)支持所有类型函数创建。通过自然语言描述Java函数需求,实时生成高质量、高可读性的Java函数代码。生成代码可直接复制到IDEA,或一键导入Java全自动开发工具函数库。想体验秒级生成可读性高的代码,现在免费下载使用FuncGPT(慧函数)[https://a.d4t.cn/QKKmTr]。