把 throw error 当做 goto 使用是一个好的实践吗?

2018-05-09 00:57:55 +08:00
 FrankFang128

最近我在做后台权限检验的时候有如下需求:

  1. 如果发现用户不满足条件 A,就返回响应 A',并停止后面的渲染
  2. 如果发现用户不满足条件 B,就返回响应 B',并停止后面的渲染
  3. 其他情况正常渲染资源详情

由于要在很多接口里做类似的判断,所以我不太可能在每个接口里写 if...else。

目前我的做法是在这些接口里调用一个 before_action (函数)

如果 before_action 发现用户不满足条件,就抛出一个错误。

然后在较高层面捕获这个错误,发送对应的响应 A' 或 B',同时由于 before_action 报错了,所以正常渲染逻辑就不会执行了。

也就是说我在把 throw error 当做 goto 在使用:结束当前子程序,直接去执行另一段程序。

大家平时也会这么写吗?

2910 次点击
所在节点    程序员
14 条回复
wellCh4n
2018-05-09 01:08:44 +08:00
摘自 阿里巴巴 Java 开发手册 第七章第四条
```
[推荐] 表达异常的分支时,少用 if-else 方式,这种方式可以改写成:
if (condition) { ...
return obj; }
// 接着写 else 的业务逻辑代码;
说明:如果非得使用 if()...else if()...else...方式表达逻辑, [强制] 避免后续代码维
护困难,请勿超过 3 层。
```
此外,我司(技术栈 Java )在开发的时候校验参数条件经常使用 `断言`
FrankFang128
2018-05-09 01:16:24 +08:00
这么多地方写一样的 if ... else 会很烦吧
@wellCh4n 用断言然后不满足情况就报错么
ss098
2018-05-09 01:32:39 +08:00
可以考虑用 middle action 来解决?我一直是这样做权限检查的。
FrankFang128
2018-05-09 02:13:05 +08:00
@ss098 middle action 阻止后面的渲染是怎么做的? 回调吗
ss098
2018-05-09 03:48:24 +08:00
@FrankFang128 https://laravel-china.org/docs/laravel/5.6/middleware

Laravel 中间件的文档,可以看里面的例子理解下。

就是如果判断不通过,就返回需要返回的内容。判断通过,就调用下一个函数,返回这个函数的值。
dcoder
2018-05-09 04:11:32 +08:00
@FrankFang128
我一直觉得 '异常' 基本就是个 goto 啊, 目的之一就是为了减少复杂的 if-else. 难道这个理解不对么?
billlee
2018-05-09 07:51:03 +08:00
这个就是异常的基本用法啊,在底层发现错误,高层统一处理
zjsxwc
2018-05-09 09:27:04 +08:00
当然用抛异常了,更通用点,可以写一个正常无鉴权的类 CA 和一个专门鉴权的通用类 CB,CB 对象 IB1 持有这个无鉴权对象 IA1,IB1 就是对 IA1 的增强版了,然后注入替换 IA1 就行,以后有更多的类似 CA 这种类时都可以用一个 CB 对象注入替换,这样写的代码好处是完全没有副作用,**不需要更改原来任何的代码**
wjpdev
2018-05-09 09:45:18 +08:00
AOP
puritania
2018-05-09 13:27:42 +08:00
个人更喜欢抛异常一点,在最外层做好 catch 就好,无数的方法调用都可以抛出异常而不是各种 return 判断
SakuraKuma
2018-05-09 13:43:44 +08:00
个人也是抛异常,外面 catch 就好了。
lihongjie0209
2018-05-09 13:43:50 +08:00
可以使用 aop 在所有请求外面代理一下, 不满足权限的都不会进入业务代码.
这里也不会涉及任何的异常, 只是把所有的 if 检查放到 aop 中而已
xiaoshenke
2018-05-09 13:54:49 +08:00
只有我一个人是在外面套一层 while(True),然后 break 么。。。
scmod
2018-05-09 15:19:53 +08:00
这种抛异常挺正常啊,如果这个异常只是为了当个 goto 一样的东西的话建议楼主自定义异常,重写 fillInStackTrace 返回 null 就行了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/453276

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX