代码之丑第一期-缩进

各位小伙伴们,大家好!咱今天就算是正式开张了。实不相瞒,第一期的内容早已写好,但唯独这开篇方式,笔者想了好些时间,包括但不限于如下风格:

  • 斗破苍穹式(已经三刷):代码优雅之力,三段!级别:低级!
  • 百年孤独式(困扰于错综复杂的人物关系,放弃):多年以后,面对吐槽,我将会回想起,前辈们带我去见识代码规范的那个遥远的下午
  • 安娜·卡列尼娜式(仅仅听过开头):好的代码怎么看都优雅,丑的代码则各有各的丑
  • 野草·秋夜式(相信我,我是写到这时才刚刚查到这个句式是出自鲁迅先生的这篇文章):我的手中有两种代码,一种是能跑就行的,另一种是别动,动必炸的

就在我兴致勃勃的继续列举时,却尴尬的发现,除了斗破苍穹是在中考在即熬夜看完的,其他的一概没看。加之高中的补课科目中有语文这项,我不得不清醒过来,接受了这样的事实:我令人捉急的语文水平实在不足以撑起想装的野心,遂放弃。

在进入正题之前,先问大家一个问题:大家都玩过街霸吗?想必大多数人都玩过(可能是在游戏厅被父母逮到),没玩过的大概率也听说过,那么大家应该知道有这么个招式:
![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b76a770504e8448b9b68feea026dd39a.png
现在,我们来看看敌人是谁:
在这里插入图片描述
不知道大家看过这个逻辑是什么感受,我的第一感觉是:这个方法可以让人有【沉浸式的】阅读体验,你必须不受打扰,非常专注才能(也许不能)读懂这段逻辑。好吧,这是高情商的说法,大家应该也知道了,它的问题是嵌套的太深,缩进太多。

我们只需说明问题即可,就不使用这段逻辑做演示了(事实是笔者偷懒了)。下面,我们用一个相对简单的例子进行说明:

public void notice(int threshold) {if (BooleanUtils.isTrue(isInSilenceTime())) {if (threshold <= 0) {// do something1} else {// do something2}} else {// do something3}
}

上面的例子也是我最近开发遇见的一个case,我需要判断当前时间是否为静默时间,如果是,则继续判断阈值是否有效,如果无效直接返回,如果有效则执行对应逻辑;如果是非静默时间,则执行另一段逻辑。

这段代码有什么问题?它的逻辑相对简单,总不会有什么问题吧?是的,功能上确实没有什么问题,但咱要的是优雅!回看上面的龟派气功,我们知道缩进过多是很讨厌的,因此缩进是我们首要考虑的问题。那么,为什么会造成缩进过多呢?从直接原因上看,是if和else的判断过多;从根本原因上看是我们在写代码时是完全按照自己的思考步骤来写的,但在写完之后没有做美颜。

有一种很常见的处理if-else的手法:通过使用卫语句替换if-else,简单来说,就是一旦发现条件不满足,就直接返回,这样说有些抽象,我们看看用这种手法优化后的代码:

public void notice(int threshold) {if (BooleanUtils.isFalse(isInSilenceTime())) {// do something3return;}if (threshold <= 0) {do something1return;}// do something2}

大家是否觉得现在清爽了很多呢?

  • 由于原逻辑中do something2的分支中逻辑较少,因为我们先进行静默时间的判断,如果不满足,直接执行do something2,然后返回
  • 考虑完不满足静默时间的逻辑,就只剩满足静默时间的了,因此不再需要else判断
  • 如果阈值无效,直接返回,那么阈值有效的情况也不必再使用else了

总的来说,上面case的优化思路就是:

  • 提前判断条件,如果命中直接返回,这样会将缩进影响的行数大大减少
  • 少用或者不用else

提前判断还比较好理解,但if-else几乎像是亲兄弟,现在居然让我别用?是的,我刚开始都不信,不过这是Jeff Bay在对象健身操中指出的:拒绝使用else关键字,同样震撼的还有其他观点,如:每个方法只使用一级缩进,方法的长度不要超过5行。好吧,我承认目前做不到这种无理的要求,但我们可以试着向这个方向靠拢,让我们再看个例子:

public int getPrice(int userLevel) {int price;if (userLevel == 1) {price = 10;} else if(userLevel == 2) {price = 20;} else if (userLevel == 3) {price = 30;} else {price = 40;}return price;
}

在这个例子中,会根据不同的用户级别返回不同的价格,这一看似乎没什么问题,但想想上面提到的优化思路,优化后的代码如下所示:

public int getPrice(int userLevel) {if (userLevel == 1) {return 10;} if(userLevel == 2) {return 20;} if (userLevel == 3) {return 30;} return 40;
}

怎么样?是否阅读体验更好了呢?在明确了用户级别之后价格就直接返回了,不必再往下看,也不必再担心下面是不是还对价格做了其他的处理,至少在这个例子中,else确实是可以不用的!

还有这种情况也是比较常见的,如果集合不为空,则执行业务逻辑,否则什么都不做。这么写在功能上肯定没问题,但这种写法还是根据我们的思考步骤写的,那我们就可以稍微美化一下:先判断如果集合为空就返回,不为空再写业务逻辑:

优化前:

public void function(List<String> list) {if (CollectionUtils.isNotEmpty(list)) {// 业务逻辑}
}

优化后:

public void function(List<String> list) {if (CollectionUtils.isEmpty(list)) {return;}// 业务逻辑
}

这便是卫语句的威力了,事实上,通过这种手法已经能够改善日常开发中相当多的场景了,至于其他场景我们还可以使用策略模式、封装等方法来进行优化,我们会在后面逐渐看到。

有一个标准来专门衡量我们今天的内容:圈复杂度,它的值越高,代码的复杂性就越高,理解和维护代码的难度也就越大。当然,今天的case只是这个标准的一小部分,感谢兴趣的伙伴们可以自行了解更多。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/482122.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JVM 性能调优 -- JVM常用调优工具【jps、jstack、jmap、jstats 命令】

前言&#xff1a; 前面我们分析怎么去预估系统资源&#xff0c;怎么去设置 JVM 参数以及怎么去看 GC 日志&#xff0c;本篇我们分享一些常用的 JVM 调优工具&#xff0c;我们在进行 JVM 调优的时候&#xff0c;通常需要借助一些工具来对系统的进行相关分析&#xff0c;从而确定…

linux上离线部署Mysql5.7.22

官网下载地址: https://downloads.mysql.com/archives/community/ Mysql安装步骤&#xff1a; 1.上传mysql安装包 上传 mysql-5.7.22-linux-glibc2.12-x86_64.tar.gz 到服务器指定目录 2.解压缩 tar -zxvf mysql-5.7.22-linux-glibc2.12-x86_64.tar.gz 3.修改名称 mv mysq…

日志与线程池

这里写自定义目录标题 日志Log.hpp测试main.cpp结果 线程池线程池的种类ThreadPool.hpp测试 Task.hpp 和 main.cppTask.hppmain.cpp结果 线程池的单例模式实现方式SignalThreadPool.hpp测试main.cpp 线程安全与重入问题死锁死锁的四个必要条件 日志 日志需要包含的信息 • 时间…

1.1 数据结构的基本概念

1.1.1 基本概念和术语 一、数据、数据对象、数据元素和数据项的概念和关系 数据&#xff1a;是客观事物的符号表示&#xff0c;是所有能输入到计算机中并被计算机程序处理的符号的总称。 数据是计算机程序加工的原料。 数据对象&#xff1a;是具有相同性质的数据元素的集合&…

泷羽sec学习打卡-shell命令5

声明 学习视频来自B站UP主 泷羽sec,如涉及侵权马上删除文章 笔记的只是方便各位师傅学习知识,以下网站只涉及学习内容,其他的都 与本人无关,切莫逾越法律红线,否则后果自负 关于shell的那些事儿-shell5 字符串运算符逻辑运算符之布尔运算符实践是检验真理的唯一标准 字符串运算…

Elasticearch索引mapping写入、查看、修改

作者&#xff1a;京东物流 陈晓娟 一、ES Elasticsearch是一个流行的开源搜索引擎&#xff0c;它可以将大量数据快速存储和检索。Elasticsearch还提供了强大的实时分析和聚合查询功能&#xff0c;数据模式更加灵活。它不需要预先定义固定的数据结构&#xff0c;可以随时添加或修…

Mybatis Plus 增删改查方法(一、增)

先定义一个简单的测试表&#xff0c;执行脚本如下&#xff1a; create table user(id bigint primary key auto_increment,name varchar(255) not null,age int not null default 0 check (age > 0) ); 根据Spingbootmybatisplus的结构根据表自行构建结构&#xff0c;大致…

本地部署 WireGuard 无需公网 IP 实现异地组网

WireGuard 是一个高性能、极简且易于配置的开源虚拟组网协议。使用路由侠内网穿透使其相互通讯。 第一步&#xff0c;服务端&#xff08;假设为公司电脑&#xff09;和客户端&#xff08;假设为公司外的电脑&#xff09;安装部署 WireGuard 1&#xff0c;点此下载&#xff08;…

unity中添加预制体及其基本设置

unity中添加预制体及其基本设置 Unity 中使用预制体的好处使用示例代码解释 Unity 中使用预制体的好处 1. 提高代码复用性 预制体可将一个游戏对象及其所有组件、子对象和设置存储在一个资源文件中&#xff0c;然后在项目中多次使用这个资源。这大大提高了代码的复用性&#x…

给定一个整数可能为正,0,负数,统计这个数据的位数.

题目描述 给定一个整数可能为正,0,负数,统计这个数据的位数. 例如1234567输出7位; -12345678输出8位;0输出1位 代码实现 int main() { long long m; long long n; scanf("%lld",&n); mn; int count0;//位数 do { count; n/10;//舍弃个位 }while(n!0); printf(&…

Linux:文件系统inode

早期&#xff0c;存储文件的设备是磁盘&#xff08;当下的市场几乎都是SSD&#xff09;&#xff0c;但大家习惯的把它们都称为磁盘&#xff0c;磁盘是用来表示区分内存的存储设备。而在操作系统看来&#xff0c;这个存储设备的结构就是一个线性结构&#xff0c;这一点很重要。 …

C++STL之vector(超详细)

CSTL之vector 1.vector基本介绍2.vector重要接口2.1.构造函数2.2.迭代器2.3.空间2.3.1.resize2.3.2.capacity 2.4.增删查找 3.迭代器失效4.迭代器分类 &#x1f31f;&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f;&#x1f31f; &#x1f680;&#x1f68…

深入浅出机器学习中的梯度下降算法

大家好&#xff0c;在机器学习中&#xff0c;梯度下降算法&#xff08;Gradient Descent&#xff09;是一个重要的概念。它是一种优化算法&#xff0c;用于最小化目标函数&#xff0c;通常是损失函数。梯度下降可以帮助找到一个模型最优的参数&#xff0c;使得模型的预测更加准…

树莓派5+文心一言 -> 智能音箱

一、简介 效果&#xff1a;运行起来后&#xff0c;可以连续对话 硬件&#xff1a;树莓派5、麦克风、音箱&#xff0c;成本500-1000 软件&#xff1a;snowboy作为唤醒词、百度语音作为语音识别、brain作为指令匹配、百度文心一言作为对话模块、微软的edge-tts语音合成... 二…

Springboot——SseEmitter流式输出

文章目录 前言SseEmitter 简介测试demo注意点异常一 ResponseBodyEmitter is already set complete 前言 最近做AI类的开发&#xff0c;看到各大AI模型的输出方式都是采取的一种EventStream的方式实现。 不是通常的等接口处理完成后&#xff0c;一次性返回。 而是片段式的处理…

5G学习笔记之随机接入

目录 1. 概述 2. MSG1 2.1 选择SSB 2.2 选择Preamble Index 2.3 选择发送Preamble的时频资源 2.4 确定RA-RNTI 2.5 确定发送功率 3. MSG2 4. MSG3 5. MSG4 6. 其它 6.1 切换中的随机接入 6.2 SI请求的随机接入 6.3 通过PDCCH order重新建立同步 1. 概述 随机接入…

【Linux-多线程】重谈地址空间+内存管理方式

一、背景知识 a.重谈地址空间 我们之前已经说过&#xff0c;CPU内部见的地址&#xff0c;以及我们打印出来的地址都是虚拟地址&#xff1b;物理内存加载到CPU&#xff0c;CPU内执行进程创建内核数据结构&#xff0c;页表等&#xff0c;通过页表映射到物理磁盘上&#xff1b;也…

Spark Optimization —— Reducing Shuffle

Spark Optimization : Reducing Shuffle “Shuffling is the only thing which Nature cannot undo.” — Arthur Eddington Shuffle Shuffle Shuffle I used to see people playing cards and using the word “Shuffle” even before I knew how to play it. Shuffling in c…

Elasticsearch——Java API 操作

Elasticsearch 软件是由Java语言开发的,所以也可以通过JavaAPI的方式对 Elasticsearch服务进行访问。 创建 Maven 项目 我们在 IDEA 开发工具中创建 Maven 项目(模块也可)ES。并修改pom文件&#xff0c;增加Maven依赖关系。 #直接复制在pom文件的<dependencies></de…

量化的8位LLM训练和推理使用bitsandbytes在AMD GPUs上

Quantized 8-bit LLM training and inference using bitsandbytes on AMD GPUs — ROCm Blogs 在这篇博客文章中&#xff0c;我们将介绍bitsandbytes的8位表示方式。正如你将看到的&#xff0c;bitsandbytes的8位表示方式显著地减少了微调和推理大语言模型&#xff08;LLMs&…