* 倾向数组及哈希的字面表示法(除非你需要给构造器传入参数)。 ~~~ # 差 arr = Array.new hash = Hash.new # 好 arr = [] hash = {} ~~~ * 创建元素为单词(没有空格和特殊符号)的数组时,用 `%w` 而不是 [] 方法。仅当数组有两个及以上元素时才应用这个规则。 ~~~ # 差 STATES = ['draft', 'open', 'closed'] # 好 STATES = %w(draft open closed) ~~~ * 当你需要一个符号的数组(并且不需要保持 Ruby 1.9 兼容性)时,使用 `%i`。仅当数组只有两个及以上元素时才应用这个规则。 ~~~ # 差 STATES = [:draft, :open, :closed] # 好 STATES = %i(draft open closed) ~~~ * 避免在 `Array` 和 `Hash` 字面量中的最后一个元素后面使用逗号。特别是元素同一行的情况下 ~~~ # 差 - 方面移动、增加和修改参数,但仍不建议使用 VALUES = [ 1001, 2020, 3333, ] # 差 VALUES = [1001, 2020, 3333, ] # 好 VALUES = [1001, 2020, 3333] ~~~ * 避免在数组中创造巨大的间隔。 ~~~ arr = [] arr[100] = 1 # 现在你有一个很多 nil 的数组 ~~~ * 当访问数组的首元素或尾元素时,尽量使用 `first` 或 `last`, 而非 `[0]` 或 `[-1]`。 * 当处理的元素没有重复时,使用 `Set` 来替代 `Array` 。 `Set` 实现了无序、无重复值的集合。 `Set` 的方法同数组类一样直观,还可像哈希中那样快速查找元素。 * 尽量用符号来取代字符串作为哈希的键。 ~~~ # 差 hash = { 'one' => 1, 'two' => 2, 'three' => 3 } # 好 hash = { one: 1, two: 2, three: 3 } ~~~ * 避免使用可变的对象作为键值。 * 当哈希的键为符号时,使用 Ruby 1.9 的哈希的字面语法。 ~~~ # 差 hash = { :one => 1, :two => 2, :three => 3 } # 好 hash = { one: 1, two: 2, three: 3 } ~~~ * 但哈希的键有符号也有字符串时,不使用Ruby 1.9的字面量语法。 ~~~ # 差 { a: 1, 'b' => 2 } # 好 { :a => 1, 'b' => 2 } ~~~ * 用 `Hash#key?`。不用 `Hash#has_key?`。用 `Hash#value?`。不用 `Hash#has_value?`。松本提到过已经不推荐使用较长的形式了。 ~~~ # 差 hash.has_key?(:test) hash.has_value?(value) # 好 hash.key?(:test) hash.value?(value) ~~~ * 在处理应该存在的哈希键时,使用 `Hash#fetch`。 ~~~ heroes = { batman: 'Bruce Wayne', superman: 'Clark Kent' } # 差 - 如果我们打错字的话,我们就无法找到对的英雄了 heroes[:batman] # => "Bruce Wayne" heroes[:supermen] # => nil # 好 - fetch 会抛出一个 KeyError 来使这个问题明显 heroes.fetch(:supermen) ~~~ * 在使用 `Hash#fetch` 时,使用第二个参数设置默认值。 ~~~ batman = { name: 'Bruce Wayne', is_evil: false } # 差 - 如果我们仅仅使用 || 操作符,那么当值为假时,我们不会得到预期的结果 batman[:is_evil] || true # => true # 好 - fetch 在遇到假值时依然正确 batman.fetch(:is_evil, true) # => false ~~~ * 如果求值的代码有副作用或者开销大,尽量用 `Hash#fetch` 加区块而不是直接设定默认值。 ~~~ batman = { name: 'Bruce Wayne' } # 差 - 默认值是立即求值 batman.fetch(:powers, obtain_batman_powers) # obtain_batman_powers 需要复杂的计算 # 好 - 区块是惰性求职,只有当 KeyError 异常时才执行 batman.fetch(:powers) { obtain_batman_powers } ~~~ * 当需要从哈希中同时获取多个键值时,使用 `Hash#values_at`。 ~~~ # 差 email = data['email'] username = data['nickname'] # 好 email, username = data.values_at('email', 'nickname') ~~~ * Ruby 1.9 的哈希是有序的,利用这个特性。 * 在遍历一个集合时,不要改动它。 * 当访问集合中的元素时,避免通过 `[n]` 直接访问,尽量使用提供的方法。这样可以防止你对 `nil` 调用 `[]`。 ~~~ # 差 Regexp.last_match[1] # 好 Regexp.last_match(1) ~~~ * 为集合提供存取器时,在访问元素之前采用一种替代的形式,从而防止用户访问的下标是 `nil`。 ~~~ # 差 def awesome_things @awesome_things end # 好 def awesome_things(index = nil) if index && @awesome_things @awesome_things[index] else @awesome_things end end ~~~