使用 def
时,当有参数时使用括号。当方法不接受任何参数时,省略括号。
def some_method
# body omitted
end
def some_method_with_arguments(arg1, arg2)
# body omitted
end
永远不要使用 for
,除非你很清楚为什么。大部分情况应该使用迭代器来取代。 for
是由 each
所实作的(所以你加入了一层的迂回),但出乎意料的是 — for
并没有包含一个新的视野(不像是 each
)而在这个区块中定义的变量将会被外部所看到。
arr = [1, 2, 3]
# 差
for elem in arr do
puts elem
end
# 好
arr.each { |elem| puts elem }
永远不要在多行的 if/unless
使用 then
# 差
if some_condition then
# body omitted
end
# 好
if some_condition
# body omitted
end
偏爱三元操作符 ? :
胜于 if/then/else/end
结构。它更为常见及更精准。
# 差
result = if some_condition then something else something_else end
# 好
result = some_condition ? something : something_else
使用一个表达式给一个三元操作符的分支。这也意味着三元操作符不要嵌套。嵌套情况使用 if/else
结构。
# 差
some_condition ? (nested_condition ? nested_something : nested_something_else) : something_else
# 好
if some_condition
nested_condition ? nested_something : nested_something_else
else
something_else
end
永远不要使用 if x: ...
— 它已经在 Ruby 1.9 被移除了。使用三元操作符来取代。
# 差
result = if some_condition: something else something_else end
# 好
result = some_condition ? something : something_else
永远不要使用 if x: ...
使用三元操作符来取代。
一行的情况使用 when x then ...
。替代方案的语法 when x: ...
在 Ruby 1.9 被移除了。
永远不要使用 when x: ...
。参考前一个规则。
布尔表达式使用 &&/||
,控制流程使用 and/or
。
(经验法则:如果你需要使用外部括号,你正在使用错误的操作符。)
# 布尔表达式
if some_condition && some_other_condition
do_something
end
# 控制流程
document.saved? or document.save!
避免多行的 ? :
(三元操作符),使用 if/unless
来取代。
偏爱 if/unless
修饰符当你有单行的主体。
另一个好的方法是使用控制流程的 and/or
。
# 差
if some_condition
do_something
end
# 好
do_something if some_condition
# 另一个好方法
some_condition and do_something
否定条件偏爱 unless
优于 if
(或是控制流程 or
)。
# 差
do_something if !some_condition
# 好
do_something unless some_condition
# 另一个好方法
some_condition or do_something
永远不要使用 unless
搭配 else
。将它们改写成肯定条件。
# 差
unless success?
puts 'failure'
else
puts 'success'
end
# 好
if success?
puts 'success'
else
puts 'failure'
end
不要使用括号围绕 if/unless/while
的条件式,除非这条件包含了一个赋值(见下面使用 =
(一个赋值)的返回值)。
# 差
if (x > 10)
# body omitted
end
# 好
if x > 10
# body omitted
end
# 好
if (x = self.next_value)
# body omitted
end
忽略围绕方法参数的括号,如内部 DSL (如:Rake, Rails, RSpec),Ruby 中带有“关键字”状态的方法(如:attr_reader
, puts
)以及属性存取方法。
所有其他的方法呼叫使用括号围绕参数。
class Person
attr_reader :name, :age
# 忽略
end
temperance = Person.new('Temperance', 30)
temperance.name
puts temperance.age
x = Math.sin(y)
array.delete(e)
单行区块喜好 {...}
胜于 do..end
。多行区块避免使用 {...}
(多行串连总是丑陋)。在 do...end
、“控制流程”及“方法定义” ,永远使用 do...end
(如 Rakefile 及某些 DSL)。串连时避免使用 do...end
。
names = ["Bozhidar", "Steve", "Sarah"]
# 好
names.each { |name| puts name }
# 差
names.each do |name|
puts name
end
# 好
names.select { |name| name.start_with?("S") }.map { |name| name.upcase }
# 差
names.select do |name|
name.start_with?("S")
end.map { |name| name.upcase }
某些人会争论多行串连时,使用 {...} 看起来还可以,
但他们应该问问自己 — 这样代码真的可读吗
以及不能把区块内容取出来放到绝妙的方法中吗。
避免在不需要的场合时使用 return
。
# 差
def some_method(some_arr)
return some_arr.size
end
# 好
def some_method(some_arr)
some_arr.size
end
当赋予缺省值给方法参数时,使用空格围绕 =
操作符。
# 差
def some_method(arg1=:default, arg2=nil, arg3=[])
# 做些什么...
end
# 好
def some_method(arg1 = :default, arg2 = nil, arg3 = [])
# 做些什么...
end
然而几本 Ruby 书建议第一个风格,第二个风格在实践中更为常见
(并可争议地可读性更高一点)。
避免在不需要的场合使用续行 \
。在实践中,尽量避免使用续行。
# 差
result = 1 - \
2
# 好 (但仍丑的跟地狱一样)
result = 1 \
- 2
使用 =
(一个赋值)的返回值是好的,但用括号环绕赋值。
# 好 — 演示赋值的目标用途
if (v = array.grep(/foo/)) ...
# 差
if v = array.grep(/foo/) ...
# 也很好 — 演示赋值的目标用途及有正确的优先序
if (v = self.next_value) == "hello" ...
随意使用 ||=
来初始化变量
# 仅在 name 为 nil 或 false 时,把名字设为 Bozhidar。
name ||= 'Bozhidar'
不要使用 ||=
来初始化布尔变量。
(想看看如果现在的值刚好是 false
时会发生什么。)
# 差 — 会把 enabled 设成真,即便它本来是假。
enabled ||= true
# 好
enabled = true if enabled.nil?
避免使用 Perl 风格的特别变量(像是 $0-9
, $`
, 等等)。它们看起来非常神秘以及不鼓励使用一行的脚本。
避免在方法名与左括号之间放一个空格。
# 差
f (3 + 2) + 1
# 好
f(3 + 2) + 1
如果方法的第一个参数由左括号开始,永远在这个方法呼叫里使用括号。
举个例子,写 f((3+2) + 1)
。
总是使用 -w
来执行 Ruby 直译器,如果你忘了某个上述的规则,它就会警告你!
当你的哈希键是符号时,使用 Ruby 1.9 哈希字面语法。
# 差
hash = { :one => 1, :two => 2 }
# 好
hash = { one: 1, two: 2 }
使用新的 lambda 字面语法。
# 差
lambda = lambda { |a, b| a + b }
lambda.call(1, 2)
# 好
lambda = ->(a, b) { a + b }
lambda.(1, 2)
未使用的区块参数使用 _
。
# 差
result = hash.map { |k, v| v + 1 }
# 好
result = hash.map { |_, v| v + 1 }