编程技巧:小技巧,大作用,一招提高代码的可读性

2024-04-18 04:04

本文主要是介绍编程技巧:小技巧,大作用,一招提高代码的可读性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1.引言

2.将复杂的代码模块化

3.避免函数的参数过多

4.移除函数中的 flag 参数

5.移除嵌套过深的代码

6.学会使用解释性变量


1.引言

        本节介绍一些实用的编程技巧。编程技巧比较琐碎、比较多。在本节中,作者仅列出了一些个人认为非常实用的编程技巧,更多的技巧需要读者在实践中慢慢积累。

2.将复杂的代码模块化

        在编写代码时,我们要有模块化思维,善于将大块的复杂的代码封装成类或函数,让阅读代码的人不会迷失在代码的细节中,这样能极大地提高代码的可读性。我们结合示例代码进行说明。

//重构前的代码
public void invest(long userId, long financialProductId){Calendar calendar = Calendar.getInstance();calendar.setTime(date);    calendar.set(Calendar.DATE(calendar.get(Calendar.DATE)+1));if(calendar.get(Calendar.DAY OF MONTH)==1){return;}...
}//原构后的代码:封装成isLastDayofMonth()函数之后,逻辑更加清晰
public void invest(long userId, long fnancialProductId){if(isLastDayofMonth(new Date())){return;}public boolean isLastDayOfMonth(Date date){Calendar calendar=Calendar.getInstance();calendar.setTime(date);calendar.set(Calendar.DATE, (calendar.get(Calendar.DATE)+ 1));        if(calendar.get(Calendar.DAY_OF_MONTH)==1){return true;}return false,}
}

        在重构前,imvest()函数中的关于时间处理的代码比较难理解。重构之后,我们将其抽象成isLastDayOfMonth函数,从该函数的命名,我们就能清晰地了解它的功能:判断某天是不是当月的最后一天。

3.避免函数的参数过多

        如果函数的参数过多,那么我们在阅读或使用该函数时都会感到不方便。函数包含多少参数才算过多呢?当然,这也没有固定标准。根据作者的经验,函数的参数一般超过5个就算过多了,因为函数参数超过5个之后,在调用函数时,调用语句容易超出一行代码的长度,要将其分为两行甚至多行,导致代码的可读性降低。除此之外,参数过多也增加了传递出错风险。

        如果导致函数的参数过多的原因是函数的职责不单一,那么我们可以通过将这个函数拆分成多个函数的方式来减少参数。示例代码如下。

public User getUser(String id,String username, String telephone, String email,String udid,     String uuid);//拆分成多个函数
public User getUserById(String id);
public User getUserByUsername(String username);
public User getUserByTelephone(String telephone);
public User getUserByEmail(String email);
public User getUserByUdid(String udid);
public User getUserByUuid(string uuid);

        针对函数参数过多的问题,我们还可以通过将参数封装为对象的方式来解决。这种处理式不仅可以减少参数的个数,还能提高函数的兼容性。在向函数中添加新的参数时,只需要问对象中添加成员变量,不需要改变函数定义,原来的调用代码不需要修改。示例代码如下。

public void postBlog(String title, String summary, String keywords, String contentString category,long authorId);//将参数封装成对象
public class Blog{private String title;private String summary;private String keywords;private Strint content;private String category;private long authorId; 
}
public void postBlog(Blog blog);

4.移除函数中的 flag 参数

        我们不应该在函数中使用布尔类型的 fag(标识)参数来控制内部逻辑(hag为me时执行一个代码逻辑,fag为alse 时执行另一个代码逻辑),这违背单一职贵原则和接口隔离原则。我们建议将包含 flag参数的函数拆分成两个函数。示例代码如下,其中,isVip是 flag参数。

public void buyCourse(long userId, long courseId, boolean isVip) ;
//将其拆分成两个函数
public void buyCourse(long userId, long courseId);
public void buyCourseForVip(long userId, long courseId);

        不过,如果函数是私有(private)函数,其影响范围有限,或者拆分之后的两个函数经常同时被调用,那么我们可以考虑保留 flag 参数。示例代码如下。

//拆分成两个函数之后的调用方式
boolean isVip=false;
...
if(isVip){buyCourseForVip(userId,courseId)
}else (buyCourse(userId,courseId);
}
//保留flag参数调用方式,代码更加简洁
boolean isVip = false;
...
buyCourse(userId,courseId,isVip);

        实际上,在函数中,除使用布尔类型的 flag参数来控制内部逻辑以外,还有人喜欢使用参数是否为 null 来控制内部逻辑。对于后一种情况,我们也应该将这个函数拆分成多个函数。拆分之后的函数的职责明确。示例代码如下,其中,selectTransactions()函数根据参数startDate、endDate 是否为 null,执行不同的代码逻辑。

public list<Transaction> selectTransactions(Long userId, Date startDate, Date endDate){if(startDate != null && endDate != null){//查询两个时间之间的交易}if(startDate != null && endDate == null){//查询startDate之后的所有交易}if(startDate ==null && endDate != null){//查询endDate之前的所有交易}if (startDate == null && endDate == null){//查询所有的交易}
}
public List<Transaction> selectTransactionsBetween(Long userId, Date startDate, Date endDate) {//拆分成多个公共(public)函数,代码变得清晰、易用return selectTransactions(userId, startDate, endDate);
}
Public list<Transaction> selectTransactionsStartWith(Long userId, Date startDate) return selectTransactions(userId, startDate, null);
}Public list<Transaction> selectTransactionsEndWith(Long userld, Date endDate){return selectTransactions(userId,null,endDate);
}
public List<Transaction> selectAllTransactions(Long userId){return selectTransactions(userId,null,null);
}
private list<Transaction> selectTransactions(Long userId, Date startDate, Date endDate){...
}

5.移除嵌套过深的代码

        代码嵌套过深往往是因为if-else、switch-case和for 循环过度嵌套。作者建议嵌套最好不超过两层,如果嵌套超过两层,就要想办法减少嵌套层数。嵌套过深导致代码语句多次缩进大量代码语句超过一行的长度而被分成两行或多行,影响代码的可读性。

        针对嵌套过深的问题,作者总结了下列4种常见的处理思路。

        1)去掉几余的 if、else 语句,示例代码如下:

//示例一
public double caculateTotalAmount(List<Order> orders){if(orders == null || orders.isEmpty()){return 0.0;}else{ //if内部使用return,因此,此处的else可以去掉double amount = 0.0;for(Order order:orders){if(order != null){amount += (order.getCount()*order.getPrice());      }}return amount;
}
//示例二
Public List<String> matchStrings(List<string> strList, String substr){List<String> matchedStrings = new ArrayList<>();if(strList != null && substr != null){for (String str : strList){if(str != nu11){//此处的if可以与下一行的if语句合并for(String str:strList)            if(str.contains(substr)){matchedStrings.add(str);}}}}return matchedStrings;
}

        2)使用 continue、break和retum 关键字提前退出嵌套,示例代码如下。

 //重构前的代码
public List<String> matchStrings(List<String> strList, String substr){List<String> matchedStrings = new List<>();if(strList != null && substr != null){for(String str : strList){if(str != null && str.contains(substr)){matchedStrings.add(str);...}}}return matchedStrings;
}
//重构后的代码:使用continue提前退出嵌套
public List<string> matchstrings(List<string> strlist,String substr){List<String> matchedStrings = new ArrayList<>();if(strList !=null && substr !=null){for(String str:strList){if(str==null || !str.contains(substr)){continue;}matchedStrings.add(str);...}return matchedStrings;
}

        3)通过调整执行顺序来减少嵌套层数,示例代码如下。

//重构前的代码
public list<String> matchStrings(List<String> strlist,String substr){List<String> matchedstrings = new ArrayList<>();if(strList != null && substr != null){for (String str:strlist){if(str!=null){if(str.contains(substr)){matchedStrings.add(str);}}}return matchedStrings;
}
//重构后的代码:先执行判断是否为空逻辑,再执行正常逻辑
public list<string> matchstrings(List<string> strlist,String substr){if(strList != nu11 && substr != nu1l){//先判断是否为空return Collections.emptyList();}List<String> matchedStrings = new ArrayList<>();for(String str:strList){if(str!=null){if(str.contains(substr)){matchedStrings.add(str);}}}return matchedstrings;
}

        4)我们可以将部分嵌套代码封装成函数,以减少嵌套层数,示例代码如下。


//重构前的代码
public List<string> appendSalts(List<string> passwords){if(passwords == null || passwords.isEmpty()){return Collections.emptylist();}List<String> passwordsWithSalt = new rrayList<>();for(String password:passwords){if(password==null){continue;}if(password.length()<8){...}else {...}}return passwordswithSalt;
}//重构后的代码:将部分代码封装为函数
public List<String> appendSalts(List<String> passwords){if(passwords == null || passwords.isEmpty()){return Collections.emptyiist();}List<String> pasowordanithSalt = new ArrayList<>();for(String password :Passwords){if(password == null){continue;}passwordsWithSolt.add(appendSalt(password));}return passwordsWithSolt;
}
private String appendSalt(String password) {String passwordWithSalt = password;if(paasword.length()<8){...}else{...}return passwordwithSalt;
}

6.学会使用解释性变量

        解释性变量可以提高代码的可读性,也可以减少不必要的注释。常用的解释性变量有以下两种。

        1)使用常量取代魔法数字,示例代码如下。

public double CalculatecircularArea(double radius) {return (3.1415)*radius*radius;
}//常量替代魔法数字
public static final Double PI =  3.1415;public double CalculateCircularArea(double radius){return PI * radius * radius;
}

        2)使用解释性变量来解释复杂表达式,示例代码如下。

if (date.after(SUMMER_START) && date.before(SUMMER_END)){...
}else {...
}//引入解释性变量后,代码更易被人理解
boolean isSummer = date.after(SUMMER START)&&date.before(SUMMER END);
if(isSummer){...
}else {...
}

这篇关于编程技巧:小技巧,大作用,一招提高代码的可读性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/913713

相关文章

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核

java中反射Reflection的4个作用详解

《java中反射Reflection的4个作用详解》反射Reflection是Java等编程语言中的一个重要特性,它允许程序在运行时进行自我检查和对内部成员(如字段、方法、类等)的操作,本文将详细介绍... 目录作用1、在运行时判断任意一个对象所属的类作用2、在运行时构造任意一个类的对象作用3、在运行时判断

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

python常用的正则表达式及作用

《python常用的正则表达式及作用》正则表达式是处理字符串的强大工具,Python通过re模块提供正则表达式支持,本文给大家介绍python常用的正则表达式及作用详解,感兴趣的朋友跟随小编一起看看吧... 目录python常用正则表达式及作用基本匹配模式常用正则表达式示例常用量词边界匹配分组和捕获常用re

Go语言数据库编程GORM 的基本使用详解

《Go语言数据库编程GORM的基本使用详解》GORM是Go语言流行的ORM框架,封装database/sql,支持自动迁移、关联、事务等,提供CRUD、条件查询、钩子函数、日志等功能,简化数据库操作... 目录一、安装与初始化1. 安装 GORM 及数据库驱动2. 建立数据库连接二、定义模型结构体三、自动迁

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Java 继承和多态的作用及好处

《Java继承和多态的作用及好处》文章讲解Java继承与多态的概念、语法及应用,继承通过extends复用父类成员,减少冗余;多态实现方法重写与向上转型,提升灵活性与代码复用性,动态绑定降低圈复杂度... 目录1. 继承1.1 什么是继承1.2 继承的作用和好处1.3 继承的语法1.4 子类访问父类里面的成