【发布时间】:2010-10-31 06:40:05
【问题描述】:
在我看来,Ruby 具有很大的语法灵活性,很多东西可以用多种方式编写。
作为 Ruby 程序员,为了清楚起见,您是否有任何语言特性/语法糖/编码约定避免?我问的是你选择不是故意使用的东西,而不是你仍然需要学习的东西。
如果你的答案是“我什么都用!”,你有没有评论过如果读者知道相关的 Ruby 语法就会很明显的代码?
[我对 RoR 上下文中的 Ruby 特别感兴趣,但欢迎一切。]
【问题讨论】:
在我看来,Ruby 具有很大的语法灵活性,很多东西可以用多种方式编写。
作为 Ruby 程序员,为了清楚起见,您是否有任何语言特性/语法糖/编码约定避免?我问的是你选择不是故意使用的东西,而不是你仍然需要学习的东西。
如果你的答案是“我什么都用!”,你有没有评论过如果读者知道相关的 Ruby 语法就会很明显的代码?
[我对 RoR 上下文中的 Ruby 特别感兴趣,但欢迎一切。]
【问题讨论】:
大部分从 Perl 继承的“$”全局变量(参见 Pickaxe2 pp333-336)的整个范围都非常可怕,尽管我有时发现自己使用 $: 而不是 $LOAD_PATH。
【讨论】:
我通常不会过度使用monkey patching,因为它可能会导致一些可维护性和可读性问题。如果使用得当,这是一个很棒的功能,但很容易让人忘乎所以。
【讨论】:
for ... in ... 循环。它直接编译为 obj.each (并相应地抛出一个奇怪的错误消息)并且完全没有必要。我什至看不出它在哪里提高了可读性——如果你已经使用 ruby 一个多星期了,#each 应该是自然的。
【讨论】:
for ... in 相比,obj.each 的范围没有不同吗?
这可能很明显,但如果有其他选择,我通常会避免使用 eval。
【讨论】:
首先:如果是针对简短的一次性脚本、命令行上的单行脚本或irb,我将打破其中的许多规则。但我大部分时间都花在中型或大型脚本或应用程序上。所以:
避免:
class << self 代码块。这是一个可爱的技巧,但并不比def self.foo 好,而且可读性较差(尤其是在第一页之后)。for i in collection:改用collection.each。proc {...}:通常lambda {...} 更好。@@foo)。它们是有问题的,通常可以毫不费力地用类级实例变量替换。ruby -w 运行时导致警告的任何东西。如果您正在编写一个供他人使用的 gem,这一点尤其重要。else”在“begin ... rescue ... end”块上。个人偏好:它太极端了,很少有人知道它的存在或它的工作原理是值得的。ObjectSpace 和 GC。你可能不需要去那里。你肯定不想去那里。=begin 和 =end 多行 cmets。个人偏好 line-wise cmets。这些简直惹恼了我。使用它,但要谨慎使用或作为最后的手段(并适当地评论它):
eval(或class_eval等)在传入字符串时。有一些元编程技巧是你不能不传入字符串的。有时,字符串版本的性能会显着提高(有时这很重要)。否则,我更愿意为我的元编程发送实际的 ruby 代码块。对于许多元编程任务,可以完全避免 eval。$0、$:、$$ 和其他环境变量,但即便如此你也可以限制你的使用)。
require "English"。__END__ 用于数据块。非常适合小型单文件脚本。对多文件应用没有帮助。不要使用它,但也不要真正避免它:
我经常使用、其他人可能不关心或我不经常看到的东西:
and'和'or'关键字:它们与&&和||的优先级不同,所以你需要小心它们。我发现它们不同的优先级非常有用。【讨论】:
我真正讨厌的一件事是“不当”使用 {} 和 do ... end 来表示块。我似乎无法准确找到我自己在哪里学习的做法,但通常接受 {} 用于单行块,do ... end 用于多行块。
正确使用:
[1, 2, 3, 4].map {|n| n * n }.inject(1) { |n,product| n * product }
或
[1, 2, 3, 4].inject do |n,product|
n = n * n
product = n * product
end
不当使用:
[1,2,3,4].map do |n| n * n end.inject(1) do |n,product| n * product end
或
[1, 2, 3, 4].inject { |n,product|
n = n * n
product = n * product
}
当然,所有这些都会执行给576
【讨论】:
避免将过多的方法调用链接在一起。在 Ruby 中将方法链接在一起是很常见的。
user.friends.each {|friend| friend.invite_to_party}
这看起来没问题,但会破坏Law of Demeter:
更正式地说,函数的得墨忒耳定律要求对象 O 的方法 M 只能调用以下类型对象的方法:
上面的例子并不完美,一个更好的解决方案是这样的:
user.invite_friends_to_party
这个例子的问题不是 Ruby 的错,但是很容易产生违反德墨忒耳法则并且使代码不可读的代码。
简而言之,避免降低代码可读性的功能。您生成的代码易于阅读,这一点非常很重要。
【讨论】:
user.friends.each(&:invite_to_party)。这是否总是一种改进是一个很好的问题......
begin nil+234 rescue '' end
上述语法是有效的,但你不应该使用它。
【讨论】: