【问题标题】:Are there any Ruby language features you avoid?有没有你避免使用的 Ruby 语言特性?
【发布时间】:2010-10-31 06:40:05
【问题描述】:

在我看来,Ruby 具有很大的语法灵活性,很多东西可以用多种方式编写。

作为 Ruby 程序员,为了清楚起见,您是否有任何语言特性/语法糖/编码约定避免?我问的是你选择不是故意使用的东西,而不是你仍然需要学习的东西。

如果你的答案是“我什么都用!”,你有没有评论过如果读者知道相关的 Ruby 语法就会很明显的代码?

[我对 RoR 上下文中的 Ruby 特别感兴趣,但欢迎一切。]

【问题讨论】:

    标签: ruby syntax


    【解决方案1】:

    大部分从 Perl 继承的“$”全局变量(参见 Pickaxe2 pp333-336)的整个范围都非常可怕,尽管我有时发现自己使用 $: 而不是 $LOAD_PATH。

    【讨论】:

      【解决方案2】:

      我通常不会过度使用monkey patching,因为它可能会导致一些可维护性和可读性问题。如果使用得当,这是一个很棒的功能,但很容易让人忘乎所以。

      【讨论】:

      • 谢谢 Firas,第一个答案很好:这是我正在寻找的东西,以了解可能危险/难以阅读的内容等。
      【解决方案3】:

      for ... in ... 循环。它直接编译为 obj.each (并相应地抛出一个奇怪的错误消息)并且完全没有必要。我什至看不出它在哪里提高了可读性——如果你已经使用 ruby​​ 一个多星期了,#each 应该是自然的。

      【讨论】:

      • 我完全同意。那个井号表示我从来不理解的实例方法:)谢谢你的回答。
      • for ... in 相比,obj.each 的范围没有不同吗?
      • 确实如此,尤其是在 Ruby 1.9 中,但我认为这是不使用它的另一个原因。它只是增加了古怪的行为。
      【解决方案4】:

      这可能很明显,但如果有其他选择,我通常会避免使用 eval。

      【讨论】:

        【解决方案5】:

        首先:如果是针对简短的一次性脚本、命令行上的单行脚本或irb,我将打破其中的许多规则。但我大部分时间都花在中型或大型脚本或应用程序上。所以:

        避免:

        • 对类方法使用class << self 代码块。这是一个可爱的技巧,但并不比def self.foo 好,而且可读性较差(尤其是在第一页之后)。
        • for i in collection:改用collection.each
        • proc {...}:通常lambda {...} 更好。
        • 类变量(例如@@foo)。它们是有问题的,通常可以毫不费力地用类级实例变量替换。
        • 任何导致警告的东西,最好是通过更严格的ruby -w 运行时导致警告的任何东西。如果您正在编写一个供他人使用的 gem,这一点尤其重要。
        • else”在“begin ... rescue ... end”块上。个人偏好:它太极端了,很少有人知道它的存在或它的工作原理是值得的。
        • ObjectSpaceGC。你可能不需要去那里。你肯定不想去那里。
        • =begin=end 多行 cmets。个人偏好 line-wise cmets。这些简直惹恼了我。

        使用它,但要谨慎使用或作为最后的手段(并适当地评论它):

        • eval(或class_eval等)在传入字符串时。有一些元编程技巧是你不能不传入字符串的。有时,字符串版本的性能会显着提高(有时这很重要)。否则,我更愿意为我的元编程发送实际的 ruby​​ 代码块。对于许多元编程任务,可以完全避免 eval。
        • 在非我创建的类上添加或重新定义方法,并且可能由我无法控制的代码使用;又名猴子补丁。此规则主要适用于较大的代码库和库;我很乐意很快为小型一次性脚本破例。我也会对修复有缺陷的第三方库进行例外处理(尽管升级时您可能会自责!)。选择器命名空间(或类似的东西)在这方面会让 ruby​​ 变得更好。也就是说,有时值得麻烦。 ;-)
        • 全局变量(类除外)。我什至会将 $stdout 作为参数传递给我的对象或方法,而不是直接使用它们。它使代码的重用变得更加容易和安全。有时你无法避免它(例如$0$:$$ 和其他环境变量,但即便如此你也可以限制你的使用)。
          • 说到这一点,我更愿意完全限制我对 perlish 符号全局变量的使用,但如果它们需要使用更多,那么require "English"
        • break、redo、next、try:通常他们使块、循环或方法比其他方式更优雅。通常,当您有一段时间没有看到该代码时,它们只会让您挠头几分钟。
        • __END__ 用于数据块。非常适合小型单文件脚本。对多文件应用没有帮助。

        不要使用它,但也不要真正避免它:

        • 尝试/捕捉
        • 继续

        我经常使用、其他人可能不关心或我不经常看到的东西:

        • 'and'和'or'关键字:它们与&&||的优先级不同,所以你需要小心它们。我发现它们不同的优先级非常有用。
        • 正则表达式黑魔法(前提是我在单元测试中有一些示例)
        • HEREDOC 字符串

        【讨论】:

        • 实际上,在 Ruby 1.9 中,除了性能之外几乎没有理由使用 eval。在块采用与方法相同的参数列表之后,动态定义具有复杂参数列表的方法的常见情况就消失了。写得好,谢谢!
        • 是的,我期待最终将我的所有应用程序升级到 1.9。 :-)
        • 有趣的列表,谢谢!在对这个问题的回答中,我学到了很多关于 ruby​​ 的知识。
        【解决方案6】:

        我真正讨厌的一件事是“不当”使用 {}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

        【讨论】:

        • 是的,但我不知道它是否回答了这个问题。不过谢谢!
        【解决方案7】:

        避免将过多的方法调用链接在一起。在 Ruby 中将方法链接在一起是很常见的。

        user.friends.each {|friend| friend.invite_to_party}
        

        这看起来没问题,但会破坏Law of Demeter

        更正式地说,函数的得墨忒耳定律要求对象 O 的方法 M 只能调用以下类型对象的方法:

        1. O 本身
        2. M 的参数
        3. 创建/实例化的任何对象 M内
        4. O 的直接组件对象

        上面的例子并不完美,一个更好的解决方案是这样的:

        user.invite_friends_to_party
        

        这个例子的问题不是 Ruby 的错,但是很容易产生违反德墨忒耳法则并且使代码不可读的代码。

        简而言之,避免降低代码可读性的功能。您生成的代码易于阅读,这一点非常很重要。

        【讨论】:

        • 他说的是真的,但我一直在寻找更多特定于 Ruby 的东西,这些东西看起来像是好主意,但实际上令人困惑......感谢您的回复,这是一个很好的观点。
        • 如今此类火车残骸将被编码为user.friends.each(&:invite_to_party)。这是否总是一种改进是一个很好的问题......
        【解决方案8】:
        begin nil+234 rescue '' end
        

        上述语法是有效的,但你不应该使用它。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-06
          • 2011-03-30
          • 1970-01-01
          • 2017-05-31
          • 1970-01-01
          • 2018-12-03
          • 1970-01-01
          相关资源
          最近更新 更多