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

Insub · December 29, 2020 · Last by xinyuewaisong replied at January 02, 2021 · 462 hits

在一个方法中我可能有多个条件判断,如条件 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 Floor has deleted

这里可以考虑使用 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
Reply to rocLv

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

Reply to ruby117

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

You need to Sign in before reply, if you don't have an account, please Sign up first.