可读性强的代码,不仅能让团队成员清晰了解代码意图;而且面对频繁变更的需求,也是维护代码的基础。然而在实践中怎样才能逐渐增强代码的可读性呢?以下几点心得可供参考。
- 避免巨复杂的表达式
将复杂表达式按照与、或、非逻辑进行拆分,并以合理的变量名对逻辑单元进行注释(以变量名代替注释)。
例如:
if( ("csv".equals(fileName.substring(fileName.lastIndexOf(".") + 1))) || ("json".equals(fileName.substring(fileName.lastIndexOf(".") + 1))){
//..
}else{
//..
}
改写成如下:
boolean isCsv = "csv".equals(fileName.substring(fileName.lastIndexOf(".") + 1);
boolean isJson = "json".equals(fileName.substring(fileName.lastIndexOf(".") + 1);
if(isCsv || isJson){
//..
}else{
//..
}
- 避免又臭又长的方法
按照一个方法只做一件事原则,将大功能抽象拆分成小功能,在本方法中只关注小功能之间的关系,并递归处理小功能。
例如:将大象装进冰箱,可以抽象成三个步骤:打开冰箱门、放入大象、关上冰箱门,即三个方法。而不是把所有的代码都写到一个上层方法中。
- 避免超大的类
超大类表现在类的成员变量越来越多、类的方法越来越多,即该类承担的责任越来越大。这个时候就要考虑将一些非本类核心功能的方法抽离出去,或者是将该类的功能合理拆分,并分别由几个小类来实现。
例如:Spark框架中SparkContext是用户的编程入口,也是框架执行的大管家,需要管理DAG划分、Task执行、RPC调用、UI等等。这里的每一部分在分布式框架中都极其复杂,如果实现细节都写在SparkContext中,那么该类将变得极其臃肿形成一个超大类难以维护,因此Spark框架分别将上述功能在DAGScheduler、RpcEndpointRef 、TaskSchedule SparkUI等类中单独实现,并维护几个实例。
- 避免过重的模块
与类拆分思路相似,当工程过于复杂后将其拆分成不同模块。
- 避免魔幻值
代码中每一个变量、常量、函数等都需要一个能够准确表达其含义的名称,这样才能让人理解。一个代表特定含义的值却没有对应的说明,不免让人费解。比如,if(type == 1){//..}else{//..}
,这里的1其实代表了一个特定的类别,如性别中的男,读代码的人却只能猜。解决此类问题,可以使用静态常量或枚举类型,通过名称对其含义进行准确地说明。
- 避免参数列表过长
将多个参数封装成对象,即将几个特定的参数封装成一个有意义的对象参数中。
例如:时间参数from和to,可以封装成一个range对象参数,其中包含from和to两个成员变量。
- 精准的命名
准确的命名,既可以表达其含义,又能够揭示其内在联系
例如:时间参数from和to,不仅见名知义,而且隐含from在to之前的关系(边界检查)