这是“深入浅出系列”文章的第一篇,次要记录和分享程序设计的一些思维和方法论,如果读者感觉所有受用,还请“一键三连”,这是对我最大的激励。
一、陈词滥调,到底啥是可读性
一句话:见名知其义。有人说好的代码必然有清晰残缺的正文,我不否定;也有人说代码即正文,是代码简洁之道的最高境界,我也不否定。但我都不齐全承受,如果照搬前者,有人会在每个办法、每个循环、每个判断都增加大量正文,对于一个表白不谨严的 coder 来说,代码与汉字可能词不达意;而且,一旦代码逻辑发生变化,正文改不改?对于后者,英语水平可能也就是个半吊子,动词名词不辨别,真能做到代码即正文的有多少人?
二、骂归骂,总归要硬着头皮干
先来举个简略例子:
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
这个办法的目标,必须通读代码,而我只是想晓得它做了什么事;最初,这个办法如果某一行出问题了,那么影响范畴是整个业务流程。
如果前期须要改变,大部分人可能会减少条件判断,或是在前面持续追加代码实现,最初会导致越来越难以浏览,这其实也就是“能运行就不要动它”这个梗的本源了,因为没人能读明确它到底做了什么,但又不得不改,同时可能随同着“口吐芳香”。
三、意识后行,从一行做起
那么到底该如何做呢?上面是我的一个例子:
public StepExitEnum doExecute(StepContext stepContext) throws Exception {initTempFilePath(stepContext);
File[] encryptedFiles = findEncryptedFiles(stepContext);
dencryptFiles(encryptedFiles, stepContext);
return StepExitEnum.CONTINUING;
}
先不管具体实现细节,是不是一眼看过之后就理解 doExecute
做了什么事?这个办法确实没有任何正文,是否影响浏览?其实我做的只是把先前的代码从新归类,别离放到了三个办法中,外围实现还是本来的代码,没有改变,当初浏览起来是不是顺畅了许多?
通读代码后我发现其实只做了三件事:创立目录、读取加密文件、解密文件,这是最外围的三个步骤,把它形象进去,独立为办法,既表白了逻辑性能,也清晰浏览,还能够放大影响范畴,今后哪里有问题改哪里,不须要再通读代码了。
四、回到主题,再说可读性
(1)形象,正当的业务逻辑形象
“一个办法只应该做一件事”,想必很多人听过相似的表述,听起来简略做起来难,怎么定义“只做一件事”?这件事的边界是什么?这就依赖 coder 对业务逻辑、对性能实现的深刻了解和正当形象,这能力清晰的辨别出各个性能的边界,或者说是如何定义这件“事”。
没有基于业务的正当形象,硬生生地写了几个办法,你会发现这几个办法“藕断丝连”,一个办法的参数变动总会影响到另一个办法,很难将一个办法单拎进去利用在其余场景,一处改,处处改,这时候就要思考,办法形象的是否正当?
正当的形象,从性能角色、职责划分上就很清晰,有了这个根底,能力清晰的编写业务逻辑代码,而不是堆砌各种条件判断和循环,同时带着两条斜杠和正文,这是可读性的根底。
(2)各司其职,职责繁多
一个办法只做一件事,扩大到一个类也如此,职责繁多,归根结底还得基于正当的形象,所以,它其实是形象的一种具体体现,二者总是相辅相成。
(3)命名标准
这也是陈词滥调了,但真正做到的 coder 其实不多,类名、办法、变量的命名规定其实很有考究,但这不是本文的主题,不多赘述,类名用名词,办法名用动词,因为类表述的是做什么事,而办法名表述的是如何做,标准的命名和正确的词法,这是编码的根底功底,这会有助于别人浏览代码,当然也是为什么咱们读 spring 源码会感觉顺畅,而读共事写的业务代码却很糟糕的起因,咱们太过于强调 spring 的 IOC 了,却疏忽了最根底的货色。
(4)要害正文
正文不能少,但也不应该每个办法、每个判断、每个循环到处都是 //
和/*
,毕竟代码是主体不是正文,而且这样还会带来隐性的工作量问题:代码批改,正文也必须批改。所以好的正文不是多,是要害。例如 java.util.HashMap
类的正文上会通知你线程平安问题:
Note that this implementation is not synchronized.
这是很要害的信息,所以正文要给出关键性的、应用上留神的事项,不在于多。
代码可读性其实是一个比拟宽泛的问题,也是一个陈词滥调的问题,随着编码教训积攒,在不同职业阶段,咱们对可读性都会有不同的了解和意识,本文从我本人的角度和教训,探讨了一些比拟浅的了解,如何写出易读、易懂的优良代码,可能是咱们 coder 永远追寻的指标之一,即便它没有起点。
作者:京东科技 张宇
起源:京东云开发者社区 转载请注明起源