对于数组与哈希,倾向使用字面量语法来构建实例(除非你需要给构造器传递参数)。
[link]
# 差
arr = Array.new
hash = Hash.new
# 好
arr = []
hash = {}
当创建一组元素为单词(没有空格或特殊字符)的数组时,倾向使用 %w
而不是 []
。此规则只适用于数组元素有两个或以上的时候。
[link]
# 差
STATES = ['draft', 'open', 'closed']
# 好
STATES = %w[draft open closed]
当创建一组符号类型的数组(且不需要保持 Ruby 1.9 兼容性)时,倾向使用 %i
。此规则只适用于数组元素有两个或以上的时候。
[link]
# 差
STATES = [:draft, :open, :closed]
# 好
STATES = %i[draft open closed]
避免在数组与哈希的字面量语法的最后一个元素之后添加逗号,尤其当元素没有分布在同一行时。
[link]
# 差 - 尽管移动、新增、删除元素颇为方便,但仍不推荐这种写法
VALUES = [
1001,
2020,
3333,
]
# 差
VALUES = [1001, 2020, 3333, ]
# 好
VALUES = [1001, 2020, 3333]
避免在数组中创造巨大的间隔。
[link]
arr = []
arr[100] = 1 # 现在你有一个很多 nil 的数组
当访问数组的首元素或尾元素时,倾向使用 first
或 last
而不是 [0]
或 [-1]
。
[link]
当处理的对象不存在重复元素时,使用 Set
来替代 Array
。Set
是实现了无序且无重复元素的集合类型。它兼具 Array
的直观操作与 Hash
的快速查找。
[link]
倾向使用符号而不是字符串作为哈希键。
[link]
# 差
hash = { 'one' => 1, 'two' => 2, 'three' => 3 }
# 好
hash = { one: 1, two: 2, three: 3 }
避免使用可变对象作为哈希键。
[link]
当哈希键为符号时,使用 Ruby 1.9 的字面量语法。
[link]
# 差
hash = { :one => 1, :two => 2, :three => 3 }
# 好
hash = { one: 1, two: 2, three: 3 }
当哈希键既有符号又有字符串时,不要使用 Ruby 1.9 的字面量语法。
[link]
# 差
{ a: 1, 'b' => 2 }
# 好
{ :a => 1, 'b' => 2 }
倾向使用 Hash#key?
而不是 Hash#has_key?
,使用 Hash#value?
而不是 Hash#has_value?
。
[link]
# 差
hash.has_key?(:test)
hash.has_value?(value)
# 好
hash.key?(:test)
hash.value?(value)
倾向使用 Hash#each_key
而不是 Hash#keys.each
,使用 Hash#each_value
而不是 Hash#values.each
。
[link]
# 差
hash.keys.each { |k| p k }
hash.values.each { |v| p v }
hash.each { |k, _v| p k }
hash.each { |_k, v| p v }
# 好
hash.each_key { |k| p k }
hash.each_value { |v| p v }
当处理应该存在的哈希键时,使用 Hash#fetch
。
[link]
heroes = { batman: 'Bruce Wayne', superman: 'Clark Kent' }
# 差 - 如果我们打错了哈希键,则难以发现这个错误
heroes[:batman] # => 'Bruce Wayne'
heroes[:supermann] # => nil
# 好 - fetch 会抛出 KeyError 使这个错误显而易见
heroes.fetch(:supermann)
当为哈希键的值提供默认值时,倾向使用 Hash#fetch
而不是自定义逻辑。
[link]
batman = { name: 'Bruce Wayne', is_evil: false }
# 差 - 如果仅仅使用 || 操作符,那么当值为假时,我们不会得到预期结果
batman[:is_evil] || true # => true
# 好 - fetch 在遇到假值时依然可以正确工作
batman.fetch(:is_evil, true) # => false
当提供默认值的求值代码具有副作用或开销较大时,倾向使用 Hash#fetch
的区块形式。
[link]
batman = { name: 'Bruce Wayne' }
# 差 - 此形式会立即求值,如果调用多次,可能会影响程序的性能
batman.fetch(:powers, obtain_batman_powers) # obtain_batman_powers 开销较大
# 好 - 此形式会惰性求值,只有抛出 KeyError 时,才会产生开销
batman.fetch(:powers) { obtain_batman_powers }
当需要一次性从哈希中获取多个键的值时,使用 Hash#values_at
。
[link]
# 差
email = data['email']
username = data['nickname']
# 好
email, username = data.values_at('email', 'nickname')
利用“Ruby 1.9 之后的哈希是有序的”的这个特性。
[link]
当遍历集合时,不要改动它。
[link]
当访问集合中的元素时,倾向使用对象所提供的方法进行访问,而不是直接调用对象属性上的 [n]
方法。这种做法可以防止你在 nil
对象上调用 []
。
[link]
# 差
Regexp.last_match[1]
# 好
Regexp.last_match(1)
当为集合提供存取器时,尽量支持索引值为 nil
的访问形式。
[link]
# 差
def awesome_things
@awesome_things
end
# 好
def awesome_things(index = nil)
if index && @awesome_things
@awesome_things[index]
else
@awesome_things
end
end