V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
FrankFang128
V2EX  ›  程序员

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

  •  
  •   FrankFang128 · May 9, 2018 · 3638 views
    This topic created in 2922 days ago, the information mentioned may be changed or developed.

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

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

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

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

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

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

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

    大家平时也会这么写吗?

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

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

    就是如果判断不通过,就返回需要返回的内容。判断通过,就调用下一个函数,返回这个函数的值。
    dcoder
        6
    dcoder  
       May 9, 2018
    @FrankFang128
    我一直觉得 '异常' 基本就是个 goto 啊, 目的之一就是为了减少复杂的 if-else. 难道这个理解不对么?
    billlee
        7
    billlee  
       May 9, 2018
    这个就是异常的基本用法啊,在底层发现错误,高层统一处理
    zjsxwc
        8
    zjsxwc  
       May 9, 2018
    当然用抛异常了,更通用点,可以写一个正常无鉴权的类 CA 和一个专门鉴权的通用类 CB,CB 对象 IB1 持有这个无鉴权对象 IA1,IB1 就是对 IA1 的增强版了,然后注入替换 IA1 就行,以后有更多的类似 CA 这种类时都可以用一个 CB 对象注入替换,这样写的代码好处是完全没有副作用,**不需要更改原来任何的代码**
    wjpdev
        9
    wjpdev  
       May 9, 2018
    AOP
    puritania
        10
    puritania  
       May 9, 2018 via iPhone
    个人更喜欢抛异常一点,在最外层做好 catch 就好,无数的方法调用都可以抛出异常而不是各种 return 判断
    SakuraKuma
        11
    SakuraKuma  
       May 9, 2018
    个人也是抛异常,外面 catch 就好了。
    lihongjie0209
        12
    lihongjie0209  
       May 9, 2018
    可以使用 aop 在所有请求外面代理一下, 不满足权限的都不会进入业务代码.
    这里也不会涉及任何的异常, 只是把所有的 if 检查放到 aop 中而已
    xiaoshenke
        13
    xiaoshenke  
       May 9, 2018
    只有我一个人是在外面套一层 while(True),然后 break 么。。。
    scmod
        14
    scmod  
       May 9, 2018
    这种抛异常挺正常啊,如果这个异常只是为了当个 goto 一样的东西的话建议楼主自定义异常,重写 fillInStackTrace 返回 null 就行了
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   1054 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 61ms · UTC 22:48 · PVG 06:48 · LAX 15:48 · JFK 18:48
    ♥ Do have faith in what you're doing.