ruby部分代码风格

每个缩排层级使用两个空格。不要使用制表符.

1
2
3
4
5
6
7
8
9
# 差 - 四个空格
def some_method
do_something
end

# 好
def some_method
do_something
end

范围的字面量语法中,不要添加任何空格。

1
2
3
4
5
6
7
# 差
1 .. 3
'a' ... 'z'

# 好
1..3
'a'...'z'

使用 _ 语法改善大数的数值字面量的可读性。

1
2
3
4
5
# 差 - 有几个零?
num = 1000000

# 好 - 方便人脑理解
num = 1_000_000

使用 def 定义方法时,如果有参数则使用括号,如果无参数则省略括号。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 差
def some_method()
# 省略主体
end

# 好
def some_method
# 省略主体
end

# 差
def some_method_with_parameters param1, param2
# 省略主体
end

# 好
def some_method_with_parameters(param1, param2)
# 省略主体
end

除非必要,否则避免在并行赋值时使用单字符的 _ 变量。优先考虑前缀形式的下划线变量,而不是直接使用 _,因为前者可以提供一定的语义信息。但当赋值语句左侧出现带 * 操作符的变量时,使用 _ 也是可以接受的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
foo = 'one,two,three,four,five'

# 差 _可有可无,且无任何有用信息
first, second, _ = foo.split(',')
first, _, _ = foo.split(',')
first, *_ = foo.split(',')

# 好 _可有可无,但提供了额外信息
first, _second = foo.split(',')
first, _second, = foo.split(',')
first, *_ending = foo.split(',')

# 好 _占位符,_ 担当最后一个元素
*beginning, _ = foo.split(',')
*beginning, something, _ = foo.split(',')

永远不要使用 for, 除非你很清楚为什么。大部分情况下,你应该使用迭代器。for 是由 each 实现的,所以你绕弯了。另外,for 没有引入一个新的作用域 (each 有),因此在它内部定义的变量在外部仍是可见的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
arr = [1, 2, 3]

# 差
for elem in arr do
puts elem
end

# 注意,elem 可在 for 循环外部被访问
elem # => 3

# 好
arr.each { |elem| puts elem }

# 注意,elem 不可在 each 块外部被访问
elem # => NameError: undefined local variable or method `elem'

倾向使用三元操作符(?:)而不是 if/then/else/end 结构。前者更为常见且简练。

1
2
3
4
5
# 差
result = if some_condition then something else something_else end

# 好
result = some_condition ? something : something_else

永远不要使用 if x; ...。使用三元操作符来替代。

1
2
3
4
5
# 差
result = if some_condition; something else something_else end

# 好
result = some_condition ? something : something_else

使用 ! 而不是 not

1
2
3
4
5
# 差 - 因为操作符的优先级,这里必须使用括号
x = (not something)

# 好
x = !something

永远不要使用 andor 关键字。使用 &&|| 来替代。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 差
# 布尔表达式
ok = got_needed_arguments and arguments_are_valid

# 流程控制
document.save or fail(RuntimeError, "Failed to save document!")

# 好
# 布尔表达式
ok = got_needed_arguments && arguments_are_valid

# 流程控制
fail(RuntimeError, "Failed to save document!") unless document.save

# 流程控制
document.save || fail(RuntimeError, "Failed to save document!")

对于单行主体,倾向使用 {...} 而不是 do...end。对于多行主体,避免使用 {...}。对于“流程控制”或“方法定义”(比如 Rakefile、其他 DSL 构成片段),总是使用 do...end。避免在链式方法调用中使用 do...end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
names = %w[Bozhidar Steve Sarah]

# 差
names.each do |name|
puts name
end

# 好
names.each { |name| puts name }

# 差
names.select do |name|
name.start_with?('S')
end.map { |name| name.upcase }

# 好
names.select { |name| name.start_with?('S') }.map(&:upcase)

某些人可能会争论在多行链式方法调用时使用 {...} 看起来还可以。但他们应该扪心自问——这样的代码真的可读吗?难道不能把区块内容提取出来放到小巧的方法里吗? #我觉得写成代码块易读。

避免在不需要流程控制的情况下使用 return

1
2
3
4
5
6
7
8
9
# 差
def some_method(some_arr)
return some_arr.size
end

# 好
def some_method(some_arr)
some_arr.size
end

嗯。。。很魔幻。

通过使用范围或 Comparable#between? 来替代复杂的比较逻辑。

1
2
3
4
5
6
7
8
# 差
do_something if x >= 1000 && x <= 2000

# 好
do_something if (1000..2000).include?(x)

# 好
do_something if x.between?(1000, 2000)

当创建一组元素为单词(没有空格或特殊字符)的数组时,倾向使用 %w 而不是 []。此规则只适用于数组元素有两个或以上的时候。

1
2
3
4
5
# 差
STATES = ['draft', 'open', 'closed']

# 好
STATES = %w[draft open closed]

倾向使用符号而不是字符串作为哈希键。

1
2
3
4
5
# 差
hash = { 'one' => 1, 'two' => 2, 'three' => 3 }

# 好
hash = { 'one': 1, 'two': 2, 'three': 3 }

倾向使用 Hash#each_key 而不是 Hash#keys.each,使用 Hash#each_value 而不是 Hash#values.each

1
2
3
4
5
6
7
8
9
# 差
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 }