语法 (Syntax)

优质
小牛编辑
140浏览
2023-12-01
  • 永远不要用 for,除非有非常特殊的理由。
    绝大部分情况都应该用 eachfor 是用 each 实现的(所以你间接加了一层),
    但区别是 - for 不会有新 scope (不像 each) 里面定义的变量外面可见。

    arr = [1, 2, 3]
    
    # 错误
    for elem in arr do
      puts elem
    end
    
    # 正确
    arr.each { |elem| puts elem }
  • 单行的情况下, 尽量用 {...} 而不是 do...end
    多行的情况下避免用 {...}. 对于 "control flow" 和 "方法定义"(举例: 在 Rakefiles 和某些 DSLs 里) 总是用 do...end
    方法连用(chaining)时 避免使用 do...end

    names = ["Bozhidar", "Steve", "Sarah"]
    
    # 正确
    names.each { |name| puts name }
    
    # 错误
    names.each do |name| puts name end
    
    # 正确
    names.each do |name|
      puts name
      puts 'yay!'
    end
    
    # 错误
    names.each { |name|
      puts name
      puts 'yay!'
    }
    
    # 正确
    names.select { |name| name.start_with?("S") }.map { |name| name.upcase }
    
    # 错误
    names.select do |name|
      name.start_with?("S")
    end.map { |name| name.upcase }

    有些人会说多行连用(chaining) 用 {...} 符号 其实也没那么难看, 但他们应该问问自己这代码真的可读吗, 而且 block 里的内容是否可以抽出来弄好看些.

  • 尽可能用短的自赋值操作符 (self assignment operators)。

    # 错误
    x = x + y
    x = x * y
    x = x**y
    x = x / y
    x = x || y
    x = x && y
    
    # 正确
    x += y
    x *= y
    x **= y
    x /= y
    x ||= y
    x &&= y
  • 避免用分号。 除非是单行 class 定义的情况下。 而且当使用分号时, 分号前面不应该有空格。

    # 错误
    puts 'foobar'; # 多余的分号
    puts 'foo'; puts 'bar' # 两个表达式放到一行
    
    # 正确
    puts 'foobar'
    
    puts 'foo'
    puts 'bar'
    
    puts 'foo', 'bar' # this applies to puts in particular
  • :: 的使用场景是引用常量,(比如 classes 和 modules 里的常量) 以及调用构造函数 (比如 Array() 或者 Nokogiri::HTML())。 普通方法调用就不要使用 :: 了。

    # 错误
    SomeClass::some_method
    some_object::some_method
    
    # 正确
    SomeClass.some_method
    some_object.some_method
    SomeModule::SomeClass::SOME_CONST
    SomeModule::SomeClass()
  • 尽量避免用 return

    # 错误
    def some_method(some_arr)
      return some_arr.size
    end
    
    # 正确
    def some_method(some_arr)
      some_arr.size
    end
  • 条件语句里不要用返回值

    # 错误 - shows intended use of assignment
    if (v = array.grep(/foo/))
      ...
    end
    
    # 错误
    if v = array.grep(/foo/)
      ...
    end
    
    # 正确
    v = array.grep(/foo/)
    if v
      ...
    end
  • 请随意用 ||= 来初始化变量。

    # 把 name 赋值为 Bozhidar, 仅当 name 是 nil 或者 false 时
    name ||= 'Bozhidar'
  • 不要用 ||= 来初始化布尔变量。 (想象下如果值刚好是 false 会咋样.)

    # 错误 - would set enabled to true even if it was false
    enabled ||= true
    
    # 正确
    enabled = true if enabled.nil?
  • 当调用 lambdas 时,明确使用 .call

    # 错误
    lambda.(x, y)
    
    # 正确
    lambda.call(x, y)
  • 避免使用 Perl 风格的特殊变量名 ( 比如 $0-9, $, 等等. ). 因为看起来蛮神秘的. 建议只在单行里使用。建议用长名字, 比如 $PROGRAM_NAME.

  • 当一个方法块只需要 1 个参数,而且方法体也只是读一个属性, 或者无参数的调用一样方法,这种情况下用 &: .

    # 错误
    bluths.map { |bluth| bluth.occupation }
    bluths.select { |bluth| bluth.blue_self? }
    
    # 正确
    bluths.map(&:occupation)
    bluths.select(&:blue_self?)
  • 当调用当前实例的某个方法时, 尽量用 some_method 而不是 self.some_method

    # 错误
    def end_date
      self.start_date + self.nights
    end
    
    # 正确
    def end_date
      start_date + nights
    end

    在下面 3 种常见情况里, 需要用, 而且应该用self.:

    1. 当定义一个类方法时: def self.some_method.
    2. 当调用一个赋值方法 (assignment method) 时,左手边 应该用 self, 比如当 self 是 ActiveRecord 模型然后你需要赋值一个属性: self.guest = user.
    3. 指向 (Referencing) 当前实例的类: self.class.