【问题标题】:Best practice to mark deprecated code in Ruby?在 Ruby 中标记已弃用代码的最佳实践?
【发布时间】:2008-11-16 15:20:13
【问题描述】:

我想将一个方法标记为已弃用,以便使用它的人可以轻松检查他们的代码并赶上进度。在 Java 中,你设置了@Deprecated,每个人都知道这是什么意思。

那么在 Ruby 中是否有首选的方法(甚至工具)来标记和检查弃用?

【问题讨论】:

  • 公平地说,Java 的注解很烂,因为它没有任何价值指向潜在的替代品

标签: ruby deprecated


【解决方案1】:

对于几乎所有情况,依赖于库或元编程来弃用是过分的。只需在 rdoc 中添加注释并调用 Kernel#warn 方法。例如:

class Foo
  # <b>DEPRECATED:</b> Please use <tt>useful</tt> instead.
  def useless
    warn "[DEPRECATION] `useless` is deprecated.  Please use `useful` instead."
    useful
  end

  def useful
    # ...
  end
end

如果您使用的是Yard 而不是rdoc,您的文档注释应如下所示:

# @deprecated Please use {#useful} instead

最后,如果你坚持tomdoc,请让你的评论看起来像这样:

# Deprecated: Please use `useful` instead

已弃用:表示该方法已弃用,将在未来版本中删除。您应该使用它来记录公开但将在下一个主要版本中删除的方法。


另外,不要忘记在将来的某个版本(以及正确的semver'd)版本中删除已弃用的方法。不要犯与 Java 库一样的错误。

【讨论】:

  • 我不确定这是否是 Java 部分的一个“错误”,而是一个巨大的向后兼容性问题(参见 stackoverflow.com/questions/314540),盲人可能不需要考虑他的 Ruby 代码。
  • 代码是一种责任。您必须维护的代码越少越好。弃用有利于暂时的向后兼容性,但随着时间的推移,它会变得笨拙。如果人们需要使用废弃的方法,他们应该改用旧版本的库。
  • 优秀的反应。我只想在响应中添加一个链接,在其中我展示了我最近使用的方法,它依赖于 Ruby Std Lib:stackoverflow.com/questions/293981/…
  • @RicardoValeriano 我同意,您的回复应该被整合(或更高票数,或两者兼而有之:))。
【解决方案2】:

Ruby 标准库有一个带有警告逻辑的模块:https://ruby-doc.org/stdlib/libdoc/rubygems/rdoc/Gem/Deprecate.html。我倾向于以“标准”方式维护我的弃用消息:

# my_file.rb

class MyFile
  extend Gem::Deprecate

  def no_more
    close
  end
  deprecate :no_more, :close, 2015, 5

  def close
    # new logic here
  end
end

MyFile.new.no_more
# => NOTE: MyFile#no_more is deprecated; use close instead. It will be removed on or after 2015-05-01.
# => MyFile#no_more called from my_file.rb:16.

请注意,通过这种方法,您将免费获得有关通话地点的信息。

【讨论】:

  • 很好,在标准库中不知道这个。
  • 数字文字的前导 0 使其成为八进制,因此应该删除。
  • 感谢您的提示。我弃用了整个类,并建议使用较新的类:deprecate :initialize, UseThisClassInstead, 2017, 5
  • 很好的用法示例,乔恩。真的很不错。
  • 之前的正确答案已被弃用,现在应该使用 Ricardo Valueriano 的答案
【解决方案3】:

使用 ActiveSupport:

class Player < ActiveRecord::Base
  def to_s
    ActiveSupport::Deprecation.warn('Use presenter instead')
    partner_uid
  end
end

生产环境默认关闭警告

【讨论】:

    【解决方案4】:

    如果您想变得刻薄(以提供帮助为幌子),您可以在警告期间打印出调用堆栈的第一行,让开发人员知道他们在哪里使用了已弃用的调用。

    这很刻薄,因为我很确定这会影响性能。

    warn Kernel.caller.first + " whatever deprecation message here"
    

    如果使用正确,这将包括文件的绝对路径和使用过时调用的行。有关 Kernel::caller 的更多信息,请访问here

    【讨论】:

    • 我不认为这意味着。一个小的性能损失比必须追踪已弃用的调用所在的位置要好得多,并且比最终删除该方法时发生的破坏要好得多。
    【解决方案5】:

    您也可以使用ActiveSupport::Deprecation(4.0+ 版本提供),例如:

    require 'active_support/deprecation'
    require 'active_support/core_ext/module/deprecation'
    
    class MyGem
      def self.deprecator
        ActiveSupport::Deprecation.new('2.0', 'MyGem')
      end
    
      def old_method
      end
    
      def new_method
      end
    
      deprecate old_method: :new_method, deprecator: deprecator
    end
    
    MyGem.new.old_method
    # => DEPRECATION WARNING: old_method is deprecated and will be removed from MyGem 2.0 (use new_method instead). (called from <main> at file.rb:18)
    

    【讨论】:

      【解决方案6】:

      您确实有 libdeprecated-ruby(2010-2012,2015 年不再在 ruby​​gem 上提供)

      一个小型库,旨在帮助开发人员处理已弃用的代码。
      这个想法来自“D”编程语言,开发人员可以在其中将某些代码标记为已弃用,然后允许/禁止执行已弃用代码的能力。

      require 'lib/deprecated.rb'
      require 'test/unit'
      
      # this class is used to test the deprecate functionality
      class DummyClass
        def monkey
          return true
        end
      
        deprecate :monkey
      end
      
      # we want exceptions for testing here.
      Deprecate.set_action(:throw)
      
      class DeprecateTest < Test::Unit::TestCase
        def test_set_action
      
          assert_raise(DeprecatedError) { raise StandardError.new unless DummyClass.new.monkey }
      
          Deprecate.set_action(proc { |msg| raise DeprecatedError.new("#{msg} is deprecated.") })
      
          assert_raise(DeprecatedError) { raise StandardError.new unless DummyClass.new.monkey }
      
      
          # set to warn and make sure our return values are getting through.
          Deprecate.set_action(:warn)
      
          assert_nothing_raised(DeprecatedError) { raise StandardError.new unless DummyClass.new.monkey } 
        end
      end
      

      【讨论】:

      • 该链接将我带到一个关于 Debian 软件包的页面。这看起来很相似(如果不相同)并且是 RubyGem:rubygems.org/gems/deprecated
      【解决方案7】:

      您可以使用 Class Macros 模式并编写如下内容:

      class Module     
           def deprecate(old_method, new_method)
                define_method(old_method) do |*args, &block|
                     warn "Method #{old_method}() depricated. Use #{new_method}() instead"
                     send(new_method, *args, &block)
                end
           end
      end
      
      
      class Test
           def my_new_method
                p "My method"
           end
      
           deprecate :my_old_method, :my_method
      end
      

      【讨论】:

        【解决方案8】:

        使用 Rails 时,您有 Module#deprecate 方法。

        【讨论】:

          【解决方案9】:

          Canivete 是一个 gem,它使您能够以简单而优雅的方式弃用您的方法。关于它的更多信息here

          【讨论】:

            【解决方案10】:

            我最终拼凑出一个轻量级的方法:

            def deprecate(msg)
              method = caller_locations(1, 1).first.label
              source = caller(2, 1).first
              warn "#{method} is deprecated: #{msg}\ncalled at #{source}"
            end
            

            然后要弃用方法,在方法主体(或类的构造函数)中插入调用

            def foo
              deprecate 'prefer bar, will be removed in version 3'
              ...
            end
            

            它具有相当的声明性,并提供相关信息的日志记录。我不是一个 Rubyist,所以它可能需要一些调整/YMMV。

            【讨论】:

              【解决方案11】:

              我们可以使用内部宏方法。 示例:

              class Foo def get_a; puts "I'm an A" end def get_b; puts "I'm an B" end def get_c; puts "I'm an C" end

              def self.deprecate(old_method, new_method)
                define_method(old_method) do |*args, &block|
                   puts "Warning: #{old_method} is deprecated! Use #{new_method} instead"
                   send(new_method, *args, &block) 
              

              结束 结束

              弃用 :a, :get_a 弃用 :b, :get_b 弃用 :c, :get_c 结束

              o = Foo.new p o.a

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2018-08-05
                • 1970-01-01
                • 2012-05-30
                • 2022-10-13
                • 2011-05-09
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多