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

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

相关文章

C++使用栈实现括号匹配的代码详解

《C++使用栈实现括号匹配的代码详解》在编程中,括号匹配是一个常见问题,尤其是在处理数学表达式、编译器解析等任务时,栈是一种非常适合处理此类问题的数据结构,能够精确地管理括号的匹配问题,本文将通过C+... 目录引言问题描述代码讲解代码解析栈的状态表示测试总结引言在编程中,括号匹配是一个常见问题,尤其是在

Java调用DeepSeek API的最佳实践及详细代码示例

《Java调用DeepSeekAPI的最佳实践及详细代码示例》:本文主要介绍如何使用Java调用DeepSeekAPI,包括获取API密钥、添加HTTP客户端依赖、创建HTTP请求、处理响应、... 目录1. 获取API密钥2. 添加HTTP客户端依赖3. 创建HTTP请求4. 处理响应5. 错误处理6.

使用 sql-research-assistant进行 SQL 数据库研究的实战指南(代码实现演示)

《使用sql-research-assistant进行SQL数据库研究的实战指南(代码实现演示)》本文介绍了sql-research-assistant工具,该工具基于LangChain框架,集... 目录技术背景介绍核心原理解析代码实现演示安装和配置项目集成LangSmith 配置(可选)启动服务应用场景

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

MySQL数据库函数之JSON_EXTRACT示例代码

《MySQL数据库函数之JSON_EXTRACT示例代码》:本文主要介绍MySQL数据库函数之JSON_EXTRACT的相关资料,JSON_EXTRACT()函数用于从JSON文档中提取值,支持对... 目录前言基本语法路径表达式示例示例 1: 提取简单值示例 2: 提取嵌套值示例 3: 提取数组中的值注意

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

Java实现状态模式的示例代码

《Java实现状态模式的示例代码》状态模式是一种行为型设计模式,允许对象根据其内部状态改变行为,本文主要介绍了Java实现状态模式的示例代码,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来... 目录一、简介1、定义2、状态模式的结构二、Java实现案例1、电灯开关状态案例2、番茄工作法状态案例

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.

CSS自定义浏览器滚动条样式完整代码

《CSS自定义浏览器滚动条样式完整代码》:本文主要介绍了如何使用CSS自定义浏览器滚动条的样式,包括隐藏滚动条的角落、设置滚动条的基本样式、轨道样式和滑块样式,并提供了完整的CSS代码示例,通过这些技巧,你可以为你的网站添加个性化的滚动条样式,从而提升用户体验,详细内容请阅读本文,希望能对你有所帮助...