前言
《Springboot中如何优雅的写好controller层代码》一不小心进入了全站综合热榜,收到了大家热情的支持,非常感谢大家,同时说明大家都有同样一个诉求,想好好写代码,不想给别人挖坑,争取可以早点下班。今天我再接再厉,再和家大家分享一下对如何写好service层代码一点粗略看法,欢迎大家点评指正。
如何优雅写好Service层代码
其实如果controller层规划好了,完成了入参数据的统一校验,返回结果统一封装,那么servcie层就相对简洁清爽多了,基本上就是纯纯的业务逻辑。具体的业务功能千变万化,但是大致的套路都差不多。
在当下的很多项目建设当中,微服务架构、分布式部署、前后端分离,基本上属于标配了,所以在service层的业务逻辑和传统的单体项目相比,除了会调用Dao层的数据库操作方法,也会调用一些远程的方法。以电商项目为例来说,调用订单服务接口进行下单操作时,要先确认是否有库存,就会在订单服务接口内调用远程的库存服务接口,确认是否有库存,如果确认还有库存,继续调用订单服务的dao接口进行下单的业务逻辑,并调用库存服务的减库存接口,进行扣减库存。
因此,如何优雅写好service层代码,基本就分成了两块:
如何优雅调用本地dao接口
如何优雅调用远程服务接口
优雅调用本地dao接口
本地的dao接口调用其实相对简单的多,根据实际业务需要去调用即可。唯一需要注意的地方就是关于异常的处理,不管是增加、删除、修改、查询,尽量不要在dao调用上去try catch。为什么呢?没有必要,因为SQL写正确了,大概率是不会有异常的;如果在执行前SQL写的不正确,启动的时候就会报异常了,再去try catch捕获异常,有些画蛇添足。同样的道理,如果数据库挂了,连接失败,即便是捕获了异常,依然什么也做不了。所以这样的try catch没有意义,没有意义的事的又何必去做呢。反而,如果try catch中捕获了异常,那么你就必须进行有意义的异常处理,仅仅打印个日志不算处理,有意义的处理是指通过个异常处理可以保证后续程序的正确执行,因为异常的正确处理和事务回滚也有关系。很多时候,如果你发现,由于业务发生异常时应该数据回滚但却没有回滚,十有八九和不当的异常处理有关。
如果在SQL执行过程中异常,且当前SQL执行异常不希望影响后续业务逻辑,那么可以捕获。另外处理异常的时候,如果实在处理不了就向上抛,或者进行一些业务处理,以保证异常不会影响后续业务程序的正常执行。
大批量数据的写
关于数据写操作的dao调用,要特别注意,比较优雅的做法是,在删除、修改、增加的数据时候,先预估一下大致的数据量,如果数据量不多,直接操作也不会有太大影响;如果数据量很大,建议划分分若干组,小批量的进行操作,这样做有以下两个原因:
大批量的数据写操作,会造成大量数据锁定状态,引起其他业务操作的阻塞;
大批量的数据写操作,会引起索引结构的调整,消耗的时间更长;
小批量操作的好处,就是不会造成大量数据长时间锁定而阻塞其他业务请求,另外也索引结构的调整时间也会小一些,但这不代表把全部数据写完所消耗的时间会更短,因为影响数据库读写的因素有很多,小批量数据写操作更多考虑的是对业务整体的影响要更小。
优雅调用远程服务接口
在《Springboot中如何优雅的写好controller层代码》中,有小伙伴留言SpringCloud架构的项目,也能按这样的模式进行吗?其实完全没有问题,因为SpringCloud架构的项目,本质上是若干个springboot项目组成、彼此之间可以相互远程调用,所以只要是springboot项目都可以采用这样的模式让controller层的代码清爽起来。
因此,如果是使用SpringCloud或Dubbo这样分布式架构的项目,在service层就会有一些远程调用,即调用另外一个项目的接口。这种情况,建议使用用try catch进行异常捕获处理,捕获后有两种选择:如果这个远程调用失败不影响当前业务的继续执行,可以仅仅打印日志就行;如果这个远程调用失败与当前业务是强耦合关系,那就不仅要记录异常日志,还要处理这个异常,处理的方式有很多,这举几个例子供作参考:
抛出自定义的运行时异常,以便上层需要回滚就回回滚;
在catch里手动回滚其他数据操作;
记录一下发生异常时的数据信息,让程序继续向下执行,另外采用数据补偿机制来补救;
在catch中实现重试机制(一般情况下,dubbo、springcloud中有重试机制,不需要自己单独实现,这里主要是针对那些需要自己实现重试机制的情况);
总之,异常处理的本质是为保证程序顺利执行,记录日志是为了发生异常时可以定位追踪问题原因。不要为了记录日志而去try catch,需要记录的话,在关键位置记录一下日志就可以了,满屏都是try catch,太影响阅读体验了。毕竟代码最终是给虚拟机执行的,但是首先是给人看的,阅读性好,后续其他人在维护这段代码的时候效率就高,那就可以少加班了,多爽。
同步方法与异步方法
一般情况下,程序里的方法调用都同步方法,即方法之间是顺序执行的。异步方法是指异步方法被调用的时候,不用等异步方法执行完或有返回结果就可以继续向下顺序执行其他方法。有的时候业务逻辑比较复杂,全部采用同步方法执行,所需要消耗的时间就是所有顺序执行方法之和。一个比较有效的代化思路,就是可以把复杂业务逻辑中,对主线业务逻辑没有影响的业务逻辑抽取成异步方法,这样整个调用时间=同步方法的调用时间之和+异步方法中执行最长时间;在性能上会有一定提高 。
控制方法长度
为什么要控制方法长度?最主要的原因是为了程序的可阅读性和可维护性。相对比较短的方法,读着就舒服,就让人心情好,维护的时候能快速找到重点,改的时候效率就高。
怎么才能控制好方法长度?
建议了解一下设计模式六大原则中的单一职责;
有没有什么好的标准呢?
给编程工具里安装一个阿里编码规约插件,如果我没有记错好像是80行,但是这个也不绝对,标准是死的,个别可以根据实际情况灵活变通,不要动不动就搞个几百行、上千行的就行,如果给你一篇几千字的文章,就一个段落,你会怎么想?
总之,大家不要相互挖坑,写好代码,早点下班,陪陪女朋友,陪陪家人、孩子,多香呀。