重构 if a || b 的重构

liwei78 · 2013年09月07日 · 最后由 liwei78 回复于 2013年09月10日 · 8150 次阅读

当遇到 if a || b 的时候,我们要先看一下,a 和 b 到底是不是可以用区间来覆盖。

初中老师会让我们算,a < 3 或 a > 5 的那些整数。那么 a 一定是在这 2 个区间了,所以,if 中的那个,一定是两个区间中的一个。

这次我见到的代码是, if !a || a.user.name.nil?

这就不合符 or 的区间判断,or 两边就不是一回事!!

写代码的小伙伴们,这是种坏习惯。

建议:

先从区间上看,再从条件上看,这不是一个 or 查询,而是一个嵌套的 if 判断。

我们先改动如下:

f a.nil?
  ...
else
  if a.user.name.nil?
    ...
  end
end

但是既然写到重构板块,那么我们应该从测试的角度,再做一次优化。

if a.nil?
  ...
else
  a_new_method
end

def a_new_method(aa)

  if aa.user.name.nil?
    ...
  end

end

这样,我们就可以测试 a_new_method,是否完成了一个单元功能,再测试 if 是否完成了条件判断。

以上是一次很典型的重构加测试的实践。

原帖地址:http://railser.cn/blog/refactoring-if-a-or-b

初中老师会让我们算,a < 3 或 a > 5 的那些整数。那么 a 一定是在这 2 个区间了,所以,if 中的那个,一定是两个区间中的一个。

这个因为所以根本没有关系,谁说 if 里就非得是个区间了。

按照这么说,类似这样的代码都不能写了

if user.vip? || user.have_more_than_five_orders?
  xxx
end

无力吐槽了,还把初中数学都搬出来了。。。。。负分

if !a || a.user.name.nil? 这行值得吐槽的地方太多了...

#1 楼 @kenshin54 我指的是 or 中的判断。if 是要取 true 和 false 的。

a.try(:user).try(:name) 如何?

#1 楼 @kenshin54 从重构的角度看,这种代码可以,因为它的含义是,user 要么是 vip,要么是五个以上订单,是符合测试时候的语境的。have_more_than_five_orders 也是一个重构的形式。 我现在面对的是未重构的代码,我在探讨重构方式。

#5 楼 @hpyhacking 不好。我感觉未到非常非常必要,不要用 try。因为我可以在这个方法外围的适当的位置 begin...rescue...一个 exception 或者自定义的 exception,告诉我发现了什么错误,而不是回避错误。

#4 楼 @liwei78 那和 if user && user.name 没啥区别啊;非要纠结两边是 true or false,就写成 if user.present? && user.name.present?,2 遍都是 true or false 了。

#7 楼 @liwei78 楼主从 java 转的么... 如果不是转过来的 那一定是写了 N 多代码之后的结果...

a && a.user && a.user.name?

#8 楼 @kenshin54 and 查询和 or 查询的语境不同。

#9 楼 @zj0713001 是别人写的代码。我在研究重构方案,自己也提升一下重构和测试的能力。

#10 楼 @hooopo 被 8 楼带跑偏了,8 楼请喝茶。。我们讨论的是 if 中的 or 查询。

个人习惯上,只有在赋值的时候才用 || ,在判断的时候一概用 or 这个关键词。 这样,我的代码一定是 user = current_user||User.new 的样子。

a 的存在和 a 的关联关系存在,属性存在,是两种情形。我一般会在外部先确保 a 存在,在 if 里再做条件判断。“是否存在”不是 if 应该做的。

个人习惯上,只有在赋值的时候才用 || ,在判断的时候一概用 or 这个关键词。

你的习惯没有一点道理,||的本意也不是你想的那样。

a 的存在和 a 的关联关系存在,属性存在,是两种情形。我一般会在外部先确保 a 存在,在 if 里再做条件判断。“是否存在”不是 if 应该做的。

建议多看看其他人怎么写代码再研究重构,不要闭门造车。

当你 if else 都要想那么多的时候,是你该搞点别的事的时候了。

#7 楼 @liwei78 你可以加个if在前面,想检查什么检查什么,这样链式调用下去就省去那么多逻辑组合了。

#15 楼 @hpyhacking 这在重构和测试上是不允许的,在阅读感上也是最差的。当然,它是最直白的表达方式。

#16 楼 @liwei78 虽然是好兄弟,但是还是要义正严词的说 or 本来就不是区间判断,or 两边不是一回事也完全没问题。

foo = get_foo() or raise "Could not find foo!" 这样的代码我也觉得没有啥不妥的。

#18 楼 @Victor 坏习惯就如同我儿子吃自己的指甲,梅西也咬指甲,但那是坏习惯。 异常应该放到 get_foo() 里 raise,这样可以测试 get_foo 是否在条件下抛出了特定的 exception。 按照上面的写法,就不是最小化测试,或者单元测试了。

#19 楼 @liwei78 为啥异常就应该放到 get_Foo 里,我 a 方法要用 get_foo,b 方法也要用 get_foo,但是只有 b 在找不到 foo 时才认为是异常,在 a 里就没关系。这完全是根据需求来的,和习惯一点关系没有,这样我在 b 里使用get_foo() or raise "Could not find foo!"很正常啊。

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