写代码有这20个好习惯,可以减少90%非业务的bug

news2024/11/25 4:21:28

每一个好习惯都是一笔财富,本文整理了写代码的20个好习惯,每个都很经典,养成这些习惯,可以规避多数非业务的bug!希望对大家有帮助哈,谢谢阅读,加油哦~

  1. 修改完代码,记得自测一下

「改完代码,自测一下」是每位程序员必备的基本素养。尤其不要抱有这种侥幸「心理:我只是改了一个变量或者我只改了一行配置代码,不用自测了」。改完代码,尽量要求自己都去测试一下哈,可以规避很多不必要bug的。

  1. 方法入参尽量都检验

入参校验也是每个程序员必备的基本素养。你的方法处理,「必须先校验参数」。比如入参是否允许为空,入参长度是否符合你的预期长度。这个尽量养成习惯吧,很多「低级bug都是「不校验参数」导致的。

例如之前出现过的:数据库存跳转链接字段设置为varchar(255),运营在业管后台配置了一个长度600链接,不校验参数,「插入数据库直接异常」了。

  1. 修改老接口的时候,思考接口的兼容性

很多bug都是因为修改了对外老接口,但是却「不做兼容导致」的。关键这个问题多数是比较严重的,可能直接导致系统发版失败的。新手程序员很容易犯这个错误哦~

所以,如果你的需求是在原来接口上修改,尤其这个接口是对外提供服务的话,一定要考虑接口兼容。举个例子吧,比如RPC接口:原本是只接收A,B参数,现在你加了一个参数C,就可以考虑这样处理。

「其实,RPC不管对内对外,接口方法入参,应优先考虑封装成model,这样增加参数个数,就是增加model字段,就会少很多接口兼容性的苦恼了。」

  1. 对于复杂的代码逻辑,添加清楚的注释

写代码的时候,是没有必要写太多的注释的,好的方法变量命名就是最好的注释。但是,如果是「业务逻辑很复杂的代码」,真的非常有必要写「清楚注释」。清楚的注释,更有利于后面的维护。

  1. 代码采取措施避免运行时错误

日常开发中,我们需要采取措施规避「数组边界溢出,被零整除,空指针」等运行时错误。

类似代码比较常见,

反例:

所以,应该「采取措施,预防一下数组边界溢出」

正例:

  1. 尽量不在循环里远程调用、或者数据库操作,优先考虑批量进行

远程操作或者数据库操作都是「比较耗网络、IO资源」的,所以尽量不在循环里远程调用、不在循环里操作数据库,能「批量一次性查回来尽量不要循环多次去查」。(但是呢,也不要一次性查太多数据哈,要分批500一次酱紫)

正例:

反例:

  1. 写完代码,脑洞一下多线程执行会怎样,注意并发一致性问题

我们经常见的一些业务场景,就是先查下有没有记录,再进行对应的操作(比如修改)。但是呢,(查询+修改)合在一起不是原子操作哦,脑洞下多线程,就会发现有问题了,

反例如下:

为了更容易理解它,看这个流程图吧:

o 1.线程A加现金

o 2.线程B加现金

o 3.线程A删除券

o 4.线程B删除券

显然这样存在「并发问题」,正例应该「利用数据库删除操作的原子性」,如下:

因此,这个习惯也是要有的,「写完代码,自己想下多线程执行,是否会存在并发一致性问题」

  1. 获取对象的属性,先判断对象是否为空

这个点本来也属于「采取措施规避运行时异常」的,但是我还是把它拿出来,当做一个习惯点来写,因为平时空指针异常太常见了,一个手抖不注意,就导致空指针报到生产环境去了。

所以,你要获取对象的属性时,尽量不要相信「理论上不为空」,我们顺手养成习惯判断一下是否为空,再获取对象的属性。

正例:

  1. 多线程异步优先考虑恰当的线程池而不是new thread,同时考虑线程池是否隔离

为什么优先使用线程池?使用线程池有这几点好处呀

o 它帮我们管理线程,避免增加创建线程和销毁线程的资源损耗。

o 提高响应速度。

o 重复利用。

同时呢,尽量不要所有业务都共用一个线程池,需要考虑「线程池隔离」。就是不同的关键业务,分配不同的线程池,然后线程池参数也要考虑恰当哈。

  1. 手动写完代码业务的SQL,先拿去数据库跑一下,同时也explain看下执行计划

手动写完业务代码的SQL,可以先把它拿到数据库跑一下,看看有没有语法错误嘛。有些小伙伴不好的习惯就是,写完就把代码打包上去测试服务器,其实把SQL放到数据库执行一下,可以规避很多错误的。

同时呢,也用「explain看下你Sql的执行计划」,尤其走不走索引这一块。

  1. 调用第三方接口,需要考虑异常处理,安全性,超时重试这几个点

调用第三方服务,或者分布式远程服务的的话,需要考虑

o 异常处理(比如,你调别人的接口,如果异常了,怎么处理,是重试还是当做失败)

o 超时(没法预估对方接口一般多久返回,一般设置个超时断开时间,以保护你的接口)

o 重试次数(你的接口调失败,需不需要重试,需要站在业务上角度思考这个问题)

简单一个例子,你一个http请求别人的服务,需要考虑设置connect-time,和retry次数。

如果是转账等重要的第三方服务,还需要考虑「签名验签」「加密」等。

  1. 接口需要考虑幂等性

接口是需要考虑幂等性的,尤其下单、抢红包、记账、冲正这些重要接口。最直观的业务场景,就是「用户连着点击两次」,你的接口有没有hold住。

o 幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。

o 在编程中.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。

一般「幂等技术方案」有这几种:

o 查询操作

o 唯一索引

o token机制,防止重复提交

o 数据库的delete删除操作

o 乐观锁

o 悲观锁

o Redis、zookeeper 分布式锁(以前抢红包需求,用了Redis分布式锁)

o 状态机幂等

  1. 多线程情况下,考虑线性安全问题

「高并发」情况下,HashMap可能会出现死循环。因为它是非线性安全的,可以考虑使用ConcurrentHashMap。所以这个也尽量养成习惯,不要上来反手就是一个new HashMap();

o Hashmap、Arraylist、LinkedList、TreeMap等都是线性不安全的;

o Vector、Hashtable、ConcurrentHashMap等都是线性安全的

  1. 主从延迟问题考虑

先插入,接着就去查询,这类代码逻辑比较常见,这「可能」会有问题的。一般数据库都是有主库,从库的。写入的话是写主库,读一般是读从库。如果发生主从延迟,很可能出现你插入成功了,但是却查询不到的情况。

o 如果是重要业务,需要考虑是否强制读主库,还是再修改设计方案。

o 但是呢,有些业务场景是可以接受主从稍微延迟一点的,但是这个习惯还是要有吧。

o 写完操作数据库的代码,想下是否存在主从延迟问题。

  1. 使用缓存的时候,考虑缓存跟DB的一致性,还有(缓存穿透、缓存雪崩和缓存击穿)

通俗点说,我们使用缓存就是为了「查得快,接口耗时小」。但是呢,用到缓存,就需要「注意缓存与数据库的一致性」问题。同时,还需要规避缓存穿透、缓存雪崩和缓存击穿三大问题:

o 缓存雪崩:指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。

o 缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。

o 缓存击穿:指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。

  1. 注意检查日期YYYY格式设置的坑

日常开发,经常需要对日期格式化,但是呢,年份设置为YYYY大写的时候,是有坑的哦。

反例:

运行结果:

「解析」

为什么明明是2021-12-31就转了一下格式,就变成了2022-12-31了,因为YYYY是基于周来计算年的,它指向当天所在周属于的年份,一周从周日算起,周六结束,只要本周跨年,那么这一周就算下一年份的了。正确姿势是使用yyyy格式。

正例:

运行结果:

  1. 检查金额数值计算精度的坑

反例:

运行结果:

可以发现,计算结果跟我们预期不一致,其实是因为计算机是以二进制存储数值的,对于浮点数也是。对于计算机而言,0.1无法精确表达,这就是为什么浮点数会导致精确度丢失的。因此,「金额计算,一般都是用BigDecimal类型」

对于上述反例,我们改为BigDecimal,再看看运行效果:

运行结果:

发现结果还是不对,「其实」,使用BigDecimal表示和计算浮点数,必须使用「字符串的构造方法」来初始化BigDecimal,正例如下:

运行结果:

在进行金额计算,使用BigDecimal的时候,我们还需要「注意BigDecimal的几位小数点,还有它的八种舍入模式哈」。

  1. 检查Integer缓存的坑

反例:

运行结果:

为什么Integer值如果是128就不相等了呢?「编译器会把Integer a=127转换为Integer.valueOf(127)。」我们看源码:


可以发现,i在一定范围内,是会返回缓存的。

「默认情况下呢,这个缓存区间就是[-128,127],所以我们业务日常开发中,如果涉及Integer值的比较,需要注意这个坑哈。还有呢,设置JVM参数加上–XX:AutoBoxCacheMax=1000,是可以调整这个区间参数的,大家可以自己试一下哈」

  1. 检查Arrays.asList的几个坑

(1)基本类型不能作为Arrays.asList方法的参数,否则会被当做一个参数。

示例:

运行结果:

Arrays.asList源码如下:

(2)Arrays.asList返回的List不支持增删操作。

示例:

运行结果:

Arrays.asList返回的List并不是我们期望的java.util.ArrayList,而是Arrays的内部类ArrayList。内部类的ArrayList没有实现add方法,而是父类的add方法的实现,是会抛出异常的呢。

(3)使用Arrays.asList的时候,对原始数组的修改会影响到我们获得的那个List。

示例:

运行结果:

从运行结果可以看到,原数组改变,Arrays.asList转化来的list也跟着改变了,大家使用的时候要注意一下哦,可以用new ArrayList(Arrays.asList(arr))包一下的。

  1. ArrayList.toArray()强转的坑

反例:

运行结果:

因为返回的是Object类型,Object类型数组强转String数组,会发生ClassCastException。解决方案是,使用toArray()重载方法toArray(T[] a)。

正例:

运行结果:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++初探 5-2(while循环 do while循环 输入 二维数组)

目录 注 while循环 for 与 while 编写延时循环 do while循环 基于范围的for循环(C11) 循环和文本输入 使用原始的cin进行输入 使用cin.get(char)进行补救 使用不同的cin.get( ) 文件尾条件 另一个cin.get( )版本 嵌套循环和二维数组 初始化…

长视频又添新变数

配图来自Canva可画 互联网广告市场依旧没有等来春天。据QuestMobile数据显示,2021下半年,中国互联网广告市场规模为3578.2亿元,而在2022年上半年这一数值下降至2903.6亿元,且同比增长率为-2.3%。 反应到具体的互联网平台上&…

[附源码]java毕业设计流浪动物救助网站

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM mybatis Maven Vue 等等组成,B/S模式 M…

Zookeeper系列——概述

Zookeeper系列——概述Zookeeper官方文档模型结构模型的特点节点的类型持久节点(PERSISTENT)持久顺序节点(PERSISTENT_SEQUENTIAL)临时节点(EPHEMERAL)临时顺序节点(EPHEMERAL_SEQUENTIAL)安装Zookeeper启动进入容器连接zookeeper的cli配置文件(zoo_sample.cfg&…

基于微信小程序的足浴城消费系统设计与实现-计算机毕业设计源码+LW文档

小程序开发说明 开发语言:Java 框架:ssm JDK版本:JDK1.8 服务器:tomcat7 数据库:mysql 5.7(一定要5.7版本) 数据库工具:Navicat11 开发软件:eclipse/myeclipse/idea Mav…

m基于simulink的WCDMA通信链路仿真

目录 1.算法概述 2.仿真效果预览 3.核心MATLAB代码预览 4.完整MATLAB程序 1.算法概述 W-CDMA由ETSI NTT DoCoMo作为无线介面为他们的3G网路FOMA开发。后来NTTDocomo提交给ITU一个详细规范作为一个象IMT-2000一样作为一个候选的国际3G标准。国际电信联盟(ITU) 最终接受W-CDM…

ESP32-WROOM-32 ESP32 wifi模块基本参数与引脚定义

基本参数: WiFi描述标准FCC/CE/TELEC/KCC/SRRC/NCC协议 802.11 b/g/n/e/i (802.11n,速度高达150Mbps) A-MPDU和A-MSDU聚合,支持0.4μS防护间隔 频率范围2.4GHz~2.5GHz(2400M~2483.5M)蓝牙描述协议符合蓝牙v4.2BR/EDR和BLE标准射频 具有-98dB…

nosql课后答案

文章目录第一章 绪论1. NoSQL和关系型数据库在设计目标上有何主要区别?2. 简要总结一下NoSQL数据库的技术特点。第二章 NoSQL数据库的基本原理1. 描述分布式数据管理的特点。2 什么是CAP原理?CAP原理是否适用于单机环境?3. 简述BASE理论的具体…

杨紫开直播被吐槽脸胖、脖子粗、嘴唇厚,这就是明星开美颜的原因

自从发明了美颜,人人都变成了美女,不过这样的话也有弊端,那就是真真假假虚虚实实难以辨别。爱美之心人皆有之。尤其是娱乐圈的明星,在直播的时候更是开启十级美颜,以至于整个人都变形了。 当然也有不开美颜的明星&…

【技术分享】计算机视觉常见的十种图像标注方法

文章目录1.语义分割2.矩形框标注3.多边形标注4.关键点标注5.立方体标注6.3D点云标注7.2D/3D融合标注8.目标追踪9.OCR转写10.属性识别1.语义分割 语义分割是指根据物体的属性,对复杂不规则图片进行进行区域划分,并标注对应上属性,以帮助训练图…

工业互联网MES解决方案-最新全套文件

工业互联网MES解决方案-最新全套文件一、建设背景生产企业面临的问题:二、思路架构MES系统的实现对企业的影响:三、建设方案四、获取 - 工业互联网MES全套最新解决方案合集一、建设背景 MES(生产制造执行系统)在整个企业生产过程…

《FFmpeg Basics》中文版-08-模糊,锐化和其他去噪

正文 包含各种噪声的视频输入可以使用去噪滤波器和选项来增强。 在视频编码之前,去噪是视频预处理的一部分。 模糊视频效果 模糊效果用于提高图像(视频帧)中某些类型的噪声的质量,其中每个输出像素值是根据相邻像素值计算的。 …

java项目-第138期ssm就业信息管理系统-java毕业设计_计算机毕业设计

java项目-第138期ssm就业信息管理系统-java毕业设计_计算机毕业设计 【源码请到资源专栏下载】 今天分享的项目是《ssm就业信息管理系统》 该项目分为管理员和普通用员2个角色。 普通用户有就业信息、就业统计2个功能 管理员用户有就业信息、 就业统计:按专业统计 …

AVR单片机及其编译软件

内容包括AVRStudio及WinAVR介绍,软件下载地址,编译环境设置,IAR for AVR的使用,AVR单片机的介绍。紫色文字是超链接,点击自动跳转至相关博文。持续更新,原创不易! 目录: 一、AVRSt…

用Python脚本能获取Wifi密码么?能。

注意,本文不是破解 WIFI 密码,当然你把程序发给别人再获取对方密码,那是社会工程学。 文章目录⛳️ 实战场景与 subprocess 模块介绍⛳️ Python 获取本地 Wifi 密码⛳️ 实战场景与 subprocess 模块介绍 这篇博客给大家带来一个小小的案例&…

魏副业而战:做闲鱼比打工强

我是魏哥,与其在家躺平,不如魏副业而战! 学员小D做闲鱼又赚了122元,并在社群中晒了收入截图,大家纷纷点赞。 小D说,做闲鱼比打工强,一边聊天,一边赚钱,很喜欢这种赚钱方…

多线程服务器端的实现

理解线程的概念 引入线程的背景 多进程模型的缺点 ①、创建进程的过程会给操作系统带来相当沉重的复旦 ②、为了完成进程间数据交换,需要特殊的IPC技术 ③、每秒少则数十次、多则数千次的“上下文切换”是创建进程时最大的开销(主要) 线…

2022实验室更新 DBCO-NH2,DBCO-Amine 叠氮化物功能化化合物

DBCO(二苯并环辛炔) 氨基衍生物,可与含有羧基的生化小分子形成稳定酰胺键连接。DBCO-NHS酯是一种与胺反应的化合物,可用于修饰含胺分子(在水性介质中的溶解度有限)。它与伯胺(例如赖氨酸的侧链氨基或多肽的N端氨基)在中性或弱碱性pH下反应形成共价键。这…

某政府门户网站维护项目运维方案

一.1 运维总体原则 一.1.1 整体性原则 我们将综合考虑XXX目前所有门户网站相关应用系统的现状,提出整体的运行维护策略,有效保障系统运行中各环节的不间断运行,并综合使用不同层次的技术手段,为应用系统和系统依托的基础环境提供全…

【AI理论学习】多模态介绍及当前研究方向

多模态介绍及当前研究方向什么是多模态?多模态的任务和数据集有哪些?多种模态融合的方式有哪些?多模态任务的研究方向有哪些?参考资料什么是多模态? 什么是多模态?多模态指的是多种模态的信息,…