项目
博客
文档
归档
资源链接
关于我
项目
博客
文档
归档
资源链接
关于我
写代码的16个好习惯
2020-12-07
·
捡田螺的小男孩
·
原创
·
性能调优
·
本文共 620个字,预计阅读需要 3分钟。
> 转自:捡田螺的小男孩 ### 前言 每一个好习惯都是一笔财富,本文整理了写代码的16个好习惯,每个都很经典,养成这些习惯,可以规避多数非业务的bug!希望对大家有帮助哈,谢谢阅读,加油哦~ ### 1. 修改完代码,记得自测一下 **「改完代码,自测一下」** 是每位程序员必备的基本素养。尤其不要抱有这种侥幸**「心理:我只是改了一个变量或者我只改了一行配置代码,不用自测了」**。改完代码,尽量要求自己都去测试一下哈,可以规避很多不必要bug的。 ### 2. 方法入参尽量都检验 入参校验也是每个程序员必备的基本素养。你的方法处理,**「必须先校验参数」**。比如入参是否允许为空,入参长度是否符合你的预期长度。这个尽量养成习惯吧,很多**「低级bug」**都是**「不校验参数」**导致的。 > 如果你的数据库字段设置为varchar(16),对方传了一个32位的字符串过来,你不校验参数,**「插入数据库直接异常」**了。 > ### 3. 修改老接口的时候,思考接口的兼容性 很多bug都是因为修改了对外老接口,但是却**「不做兼容导致」**的。关键这个问题多数是比较严重的,可能直接导致系统发版失败的。新手程序员很容易犯这个错误哦~ 所以,如果你的需求是在原来接口上修改,,尤其这个接口是对外提供服务的话,一定要考虑接口兼容。举个例子吧,比如dubbo接口,原本是只接收A,B参数,现在你加了一个参数C,就可以考虑这样处理。 ``` //老接口 void oldService(A,B);{ //兼容新接口,传个null代替C newService(A,B,null); } //新接口,暂时不能删掉老接口,需要做兼容。 void newService(A,B,C); ``` ### 4.对于复杂的代码逻辑,添加清楚的注释 写代码的时候,是没有必要写太多的注释的,好的方法变量命名就是最好的注释。但是,如果是**「业务逻辑很复杂的代码」**,真的非常有必要写**「清楚注释」**。清楚的注释,更有利于后面的维护。 ### 5. 使用完IO资源流,需要关闭 应该大家都有过这样的经历,windows系统桌面如果**「打开太多文件」**或者系统软件,就会觉得电脑很卡。当然,我们linux服务器也一样,平时操作文件,或者数据库连接,IO资源流如果没关闭,那么这个IO资源就会被它占着,这样别人就没有办法用了,这就造成**「资源浪费」**。 所以使用完IO流,可以使用finally关闭哈 ``` FileInputStream fdIn = null; try { fdIn = new FileInputStream(new File("/jay.txt")); } catch (FileNotFoundException e) { log.error(e); } catch (IOException e) { log.error(e); }finally { try { if (fdIn != null) { fdIn.close(); } } catch (IOException e) { log.error(e); } } ``` JDK 7 之后还有更帅的关闭流写法,**「try-with-resource」**。 ``` /* * 关注公众号,捡田螺的小男孩 */ try (FileInputStream inputStream = new FileInputStream(new File("jay.txt")) { // use resources } catch (FileNotFoundException e) { log.error(e); } catch (IOException e) { log.error(e); } ``` ### 6.代码采取措施避免运行时错误(如数组边界溢出,被零除等* 日常开发中,我们需要采取措施规避**「数组边界溢出,被零整除,空指针」**等运行时错误。 类似代码比较常见: ``` String name = list.get(1).getName(); //list可能越界,因为不一定有2个元素哈 ``` 所以,应该**「采取措施,预防一下数组边界溢出」**,正例: ``` if(CollectionsUtil.isNotEmpty(list)&& list.size()>1){ String name = list.get(1).getName(); } ``` ### 7.尽量不在循环里远程调用、或者数据库操作,优先考虑批量进行 远程操作或者数据库操作都是**「比较耗网络、IO资源」**的,所以尽量不在循环里远程调用、不在循环里操作数据库,能**「批量一次性查回来尽量不要循环多次去查」**。(但是呢,也不要一次性查太多数据哈,要分批500一次酱紫) 正例: ``` remoteBatchQuery(param); ``` 反例: ``` for(int i=0;i
❝ > > 简单一个例子,你一个http请求别人的服务,需要考虑设置connect-time,和retry次数。 > > ❞ 如果是转账等重要的第三方服务,还需要考虑**「签名验签」**,**「加密」**等。之前写过一篇加签验签的,有兴趣的朋友可以看一下哈 程序员必备基础:加签验签 ### 13.接口需要考虑幂等性 接口是需要考虑幂等性的,尤其抢红包、转账这些重要接口。最直观的业务场景,就是**「用户连着点击两次」**,你的接口有没有hold住。 > ❝ > > - 幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。 > - 在编程中.一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。幂等函数,或幂等方法,是指可以使用相同参数重复执行,并能获得相同结果的函数。 > > ❞ 一般**「幂等技术方案」**有这几种: - 查询操作 - 唯一索引 - token机制,防止重复提交 - 数据库的delete删除操作 - 乐观锁 - 悲观锁 - Redis、zookeeper 分布式锁(以前抢红包需求,用了Redis分布式锁) - 状态机幂等 ### 14. 多线程情况下,考虑线性安全问题 在**「高并发」**情况下,HashMap可能会出现死循环。因为它是非线性安全的,可以考虑使用ConcurrentHashMap。所以这个也尽量养成习惯,不要上来反手就是一个new HashMap(); > ❝ > > - Hashmap、Arraylist、LinkedList、TreeMap等都是线性不安全的; > - Vector、Hashtable、ConcurrentHashMap等都是线性安全的 > > ❞ ### 15.主从延迟问题考虑 先插入,接着就去查询,这类代码逻辑比较常见,这**「可能」**会有问题的。一般数据库都是有主库,从库的。写入的话是写主库,读一般是读从库。如果发生主从延迟,很可能出现你插入成功了,但是却查询不到的情况。 - 如果是重要业务,需要考虑是否强制读主库,还是再修改设计方案。 - 但是呢,有些业务场景是可以接受主从稍微延迟一点的,但是这个习惯还是要有吧。 - 写完操作数据库的代码,想下是否存在主从延迟问题。 ### 16.使用缓存的时候,考虑缓存跟DB的一致性,还有(缓存穿透、缓存雪崩和缓存击穿) 通俗点说,我们使用缓存就是为了**「查得快,接口耗时小」**。但是呢,用到缓存,就需要**「注意缓存与数据库的一致性」**问题。同时,还需要规避缓存穿透、缓存雪崩和缓存击穿三大问题。 > ❝ > > - 缓存雪崩:指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。 > - 缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。 > - 缓存击穿:指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。