新手问题 一个方法中有多个条件判断,当其中一项不符合即中断并返回结果,怎么写比较合理简洁一点?

Insub · 2020年12月29日 · 最后由 xinyuewaisong 回复于 2021年01月02日 · 476 次阅读

在一个方法中我可能有多个条件判断,如条件 A,B,C,D,顺序执行,全部成功则返回成功结果,如果其中任意一项条件不满足的话,不再执行剩余条件判断,直接返回带错误信息的失败。 大概就是像下面代码这种情况,怎么写比较合理简洁一点呢?

def show
   if !condition_A
     # 跳到 render 400 并返回一个 A 报错
   end
   if !condition_B
     # 跳到 render 400 并返回一个 B 报错
   end
   if !condition_C
     # 跳到 render 400 并返回一个 C 报错
   end

   if all_ok
     render :status => 200, :json => { :success => true, :msg => "All ok."}
   else
     render :status => 400, :json => { :success => false, :msg => "condition B fail."}
   end
 end

render && return

代码简洁之道里面说的,不建议每步都 return,而是先把值赋给一个变量,然后最后 return。




def show
   status = 400
   is_success = false
   msg = "condition B fail"

   unless   condition_A
     # 跳到 render 400 并返回一个 A 报错
   end
   unless condition_B
     # 跳到 render 400 并返回一个 B 报错
   end
   unless condition_C
     # 跳到 render 400 并返回一个 C 报错
   end

   if all_ok
     status = 200
     is_success = true
     msg = "All ok"  
  end

  render :status => status, :json => { :success => is_success, :msg => msg }
 end

考虑到系统运行的效率,尽早 return 其实更好。

attr_access :status, :is_success, :msg

def show
   render_failed_in_condition_a and return unless condition_a?
   render_failed_in_condition_b and return unless condition_b? 
   render_failed_in_condition_c and return unless condition_c?

   initial_default_response  

   set_success_response if all_ok?

   render :status => status, :json => { :success => is_success, :msg => msg }
 end

private
   def render_failed_in_condition_a
      render :status => 400, :json => { :success => false, :msg => "condition A fail."}
   end

   def render_failed_in_condition_b
      render :status => 400, :json => { :success => false, :msg => "condition B fail."}
   end

   def render_failed_in_condition_c
     render :status => 400, :json => { :success => false, :msg => "condition C fail."}
   end

   def initial_default_response
       status = 400
       is_success = false
       msg = "unknown condition fail"
   end

   def set_success_response
      status = 200
      is_success = true
      msg = "All ok"
   end

```

大概这个样子比较好了,当然还有优化的空间。比如说所有40X,50X的可以继承Exception,然后作为异常抛出。

代码优化对于业务来说有最优解,单纯的从代码层面来看总是会有一些优化空间的。

@rocLv 有时候 condition A 是 condition B 的前置条件,这么看我感觉还是多写几行 render && return 比较直观一点?

不满足condition A 就直接返回了

5 楼 已删除

这里可以考虑使用 before_action,尝试修改如下:

before_action :render_fail, only: :show

def show
  render status: 200, json: { success: true, msg: :ok }
end

private

def render_fail
  msg = if !condition_A
    'msg a'
  elsif !condition_B
    'msg b'
  elsif !condition_C
    'msg c'
  end

  render status: 400, json: { success: false, msg: msg } if msg
end
rocLv 回复

请教下 render_failed_in_condition_x && returnreturn render_failed_in_condition_x 有什么区别?个人理解后面这种形式应该更符合逻辑吧?用 return 返回 render sanitized html template“字符串”。

ruby117 回复

这里的 return 只是为了终结方法执行,返回具体什么值是次要的,所以两种没啥区别

需要 登录 后方可回复, 如果你还没有账号请 注册新账号