Redian新闻
>
注意了:请不要将抛出异常作为业务逻辑使用!!!

注意了:请不要将抛出异常作为业务逻辑使用!!!

公众号新闻

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 10:33 更新文章,每天掉亿点点头发...

源码精品专栏

 
来源:cnblogs.com/myfor/
p/13024120.html

一个奇怪的用法

我遇到过一个项目,使用 .net core 搭建的一套OA系统,搭建这个系统的架构师,选择将不合法的请求,或是失败的请求用 throw 抛出异常,然后再异常过滤器中打包成一个正常相应的数据,返回给前端。

例:服务器接受到客户端的请求,检查上传的参数的时候,发现少了一个参数,这个时候应该告诉客户端:你少给我了一个参数。在这个系统中,要求所有的工程师遇到这个种情况要抛出异常,并在异常信息里写明要返回给客户端的描述信息。就是:

if (参数少了一个) {
    throw new Exception("前端你的参数少了一个");   
}

然后在异常过滤器中将异常信息包装成一个正常返回值,主动抛出的异常描述信息也在这个返回值中返回给前端。

现在请思考下这种设计有没有什么不妥?

这种方式完全违背了异常机制的初衷,将异常机制大材小用,而唯一的好处就是写起来短。

异常机制表示这不是一个正常的业务代码,怎么理解?异常的抛出会停止系统的所有接下来的操作,这是强制性的。为什么这么做?为什么要停下来?是因为抛出异常代表发生了一个不可预知的危险操作,代表发生了正常业务逻辑以外的事,如果继续执行下去,可能会发生无法挽回的危险。所以需要一个抛出的操作强制终止程序的执行。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

写个除法器

举个简单的例子,你需要写一个方法来计算两个数相除的商,你可以很快地写下这个方法:

double Div(double n1, double n2)
{
    return n1 / n2;
}

那如果除数 n2 接收到的是 0 ,怎么办?

在 .net 里除数为 0 的话会直接抛出异常,但如果让你来实现除法的话,你要这么应对这种情况呢?

可能有人会想到,多返回两个结果参数,一个用来指示计算是否成功,一个指示失败的原因,一共有三个参数,就像:

(bool, string, double) Div(double n1, double n2)
{
    //
}

这个可能是一个比较周全的方法,考虑到成功和失败的情况,但请思考一下,如果除数传进来是 0 ,这个方法会返回 (false, "除数不能为零", ??)。商的返回值应该是什么?有人会想:商的返回值是什么都可以,因为已经有 false 指示相除失败,也有说明失败原因的结果参数了。调用方只要先判断相除是否成功的参数就可以了。

没错,理想情况的确是这样,那么,你要怎么保证调用方一定会按照你的想法去使用这个方法呢?这个时候可能有人会想:那我管不着!别人要乱用我有什么办法!

对,这么想当然没问题,但我们是软件工程师,我们可以做的更好。你想一下,如果你的这个方法被使用在金融系统中,可能会造成多大的损失。无论你的返回值多么详尽,这仍然是一个不安全的方法。在调用方传递了一个不合法的值 0 后,仍然在商的结果位给了一个数字,而你是没有办法保证调用方不会拿你的返回的错误结果商去当作正常的值使用,这可能会在金融系统中造成无法估量的损失,比如算少了你的工资。

这个时候我们应该怎么做,才能帮用户最大程度上减少损失?

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

抛出异常的妙用

我们要么确保一定给调用方返回一个正确的值,要么在计算不出正确的值时,什么都不返回。这就是需要抛出异常机制的时候了。

在接受到 0 作为除数时,直接抛出错误,阻止程序继续往下走。这样,在调用方给你一个错误的参数,你就阻止了调用方可能会做的胡搞瞎搞,从而迫使调用方检查他的参数。

尽管异常会造成一些性能损耗,但和可能发生的业务损失相比,这些性能损耗太微不足道了。

明白了吗,抛出异常的使用,不是作为正常的业务流程所使用,而是当发生你无法预计的不正常业务流程时,阻止他继续可能会造成的损失来使用的。像开头我提到了架构师搭建的项目,将抛出作为正常业务流程的一部分来使用,这使得抛出这个动作发生得十分频繁。

因为你检查客户端的参数,这是一个正常的流程,你能知道哪些参数是正确的,哪些是不正确的,并知道要怎么提醒客户端。如果这里再检查参数不正确后就主动抛出,因为可能发生得十分频繁,就会十分损耗性能。这是十分不可取的一种方式。

思考到这里,想一下,如果你调用的别人的代码抛出了异常,你要怎么办呢?是 try catch 捕获之后,当无事发生吗?这就浪费了别人抛出的一番苦心了,你要做的是,检查修改你的代码,看看参数是不是不正确,完善逻辑,以保证不会再诱发下一次同样的报错。如果你不能保证,并且也不能承担 try catch 后可能会发生的损失,那就让它报错。



欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢

已在知识星球更新源码解析如下:

最近更新《芋道 SpringBoot 2.X 入门》系列,已经 101 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

文章有帮助的话,在看,转发吧。

谢谢支持哟 (*^__^*)

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
高开即将结束,请不要用孩子18岁的成就定义终身成功聊聊美国的居委会 HOA在美想买车的注意了:小心这10款车10万英里后毛病多!暑假,请不要带孩子去旅行!明确了:12月1日起将禁止使用!道他刁鸟酷叼鲷又是一年高考时,请不要用孩子18岁的成就定义终身成功似有却无是金钱、似无却有是赊欠热死啦!!!!!!!!!!!!!!yyds,付费搞来的,请低调使用!!!“一飞机发出异响紧急备降”!最新情况不要将自己的主要精力放在抚平情绪上杨立昆:生成式AI还不如狗聪明;谷歌建议员工不要将机密内容输入Bard;王小川公司发布开源大模型| AI一周资讯《樱桃小丸子》同学原型“孤独死”,屋里飘出异臭才被邻居发现…冲牛津大学的注意了:2023年依旧采用线上面试!部分笔试交给TCS管理!六月!!!来势汹汹!!!Databricks撕逼Snowflake!!!“有很多茅台股份最后抛出去了...”好险,差点变成富二代!!!近期回中国注意了:刚入境被海关严查!箱子直接上“锁”云绑定应用:实现业务逻辑,减轻开发者负担​田浩江|有些歌,如果你还记得,请不要忘了云迁移为业务赋能,跨出数字化转型第一步拜托,如果我中暑昏倒了,请不要给我喂这个药高铁互殴事件闽籍华人之光!!!!!!!澳洲这条法律今日正式生效!员工可选择在家办公,老板若拒绝可提出异议不作为!竟拖延1小时!亚裔女在唐人街遭尾随被捅40多刀!! 家人起诉警察无所作为....38岁女领导房间传出异动,我一时情急闯入却不料看到一出好戏最低气温12℃,来黑龙江的游客注意了:一定记得穿外套这年头,大师兄不但要救师傅,还要为业绩背锅?大批华人抗议! 技术人才即将抛弃澳洲, 全因父母移民重大调整: 审批时间长达50年!今日聚焦:能力不够,请不要当医生!这样从医,就是杀人!孩子多受罪啊……接着讨论希腊文明是不是伪造的?拜登称“说服岸田”增加防卫费 日政府向美“提出异议”这六句话,请不要说给抑郁症患者听!只给大模型LeetCode编号,也能解题!大模型表现好是源于对训练数据的记忆吗?请不要迷信大模型
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。