这篇 [帖子][1] 里楼主提到如下写法:
def self.rule_exchange_anhao(tao_deal)
if operation_name = tao_deal_operation_name(tao_deal)
find_rule_by_operation_name(operation_name)
end
end
引来了关于 [In-logic assignment][2] 的讨论。反对观点如下:
if 语句中 不应该出现 一个等号。因为, 一个等号 和 两个等号 看起了 极度相似,不仔细看,会造成混乱。
这样的代码, 绝对是未来bug的源泉, 你要是不改, 迟早还要再次中招. 建议有空看看Ruby重构吧.任何一个阅读过重构的人, 看到楼主这样写代码, 不发飙才怪
于是我找来 Ruby 社区最流行的一份 [Code style][3] 和 Rails 和 Rubinius 源码里面的片段来说明,即使看过重构,懂 [SRP][4] 的大牛们也是这样写代码的,Rails 团队里对代码有洁癖的人不少,他们不但没发飙而且自己还这样写。。。
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/sanitization.rb#L59
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/reflection.rb#L298
https://github.com/rails/rails/blob/master/activerecord/lib/active_record/nested_attributes.rb#L281
https://github.com/rubinius/rubinius/blob/master/lib/un.rb#L227
所以我的结论是未来bug的源泉
和任何一个阅读过重构的人, 看到楼主这样写代码, 不发飙才怪
都是假想出来的,带着这种情绪去讨论没有意义。
我的观点是:In-logic assignment is simple and abstracts repeated patterns (DRY). 经常写代码的同学应该都熟悉类似流程: 如果对象存在,然后对該对象进行处理;如果对象不存在返回 nil/抛出异常/新建对象。 In-logic assignment 就是对上面的模式的抽象。
类似的抽象还有Object.tap
、Object.try
、||=
,至于你对这些方法的使用场景没了解就使用,出现了错误这是你自己的问题。
就像我们经常写a ||= b
,而不是写:
if a == nil || a == false
a = b
end
经常写a.tap{|obj|do_some_thing_with(obj)}
,而不是去重复下面的代码:
a = xx
do_some_thing_with(a)
return a
经常写
if tag = Tag.find_or_create_by_name(name)
tag.increment_counter(:visits_count)
end
而不是:
tag = Tag.find_by_name(name)
if tag
tag.increment_counter(:visits_count)
else
tag = Tag.create(:name => name)
tag.increment_counter(:visits_count)
end
[1]: http://ruby-china.org/topics/5141 [2]: http://www.quirkey.com/blog/2009/02/13/ruby-idiom-in-logic-assignment/ [3]: https://github.com/bbatsov/ruby-style-guide [4]: http://en.wikipedia.org/wiki/Single_responsibility_principle