在 Ruby 中标记废弃代码的最佳实践?

我希望将一个方法标记为已弃用,这样使用它的人可以轻松地检查他们的代码并跟上进度。在 Java 中,你设置了@Depreated,每个人都知道这意味着什么。

那么有没有一种更好的方法(甚至是工具)来标记和检查 Ruby 中的反对意见呢?

32097 次浏览

你确实有 libdeprecated-ruby(2010-2012,2015年在 rubygem 上不再提供)

一个用于帮助开发人员使用废弃代码的小型库。
这个想法来自于“ 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

几乎在所有情况下,依赖库或元编程来弃用都是过分的。只需向 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

如果你使用的是 院子里而不是 Rdoc,你的文档注释应该是这样的:

# @deprecated Please use {#useful} instead

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

# Deprecated: Please use `useful` instead

弃用: 指示方法已被弃用,将在以后的版本中删除。您应该使用这个文档方法,这是公共的,但将在下一个主要版本删除。


另外,不要犯与 Java 库相同的错误。

如果你想表现得更加刻薄(在帮助的骗局下) ,你可以在警告期间打印出调用堆栈的第一行,让开发者知道他们在哪里使用了不推荐的调用。

这很刻薄,因为 我很确定这是一个性能的打击。

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

如果使用正确,这将包括文件的绝对路径和使用了弃用调用的行。有关 Kernel: : 调用方的更多信息可以使用 给你

Canivete 是一个 gem,它使您能够以简单和优雅的方式弃用您的方法。再多说一点 给你

您可以使用类宏模式并编写如下代码:

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

在使用 Rail 时,可以使用 Module # depreate 方法。

你也可以使用 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)

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.

请注意,使用这种方法,您将获得关于调用发生地点的免费信息。

我最终提出了一个轻量级的方法:

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

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

使用 ActiveSupport:

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

默认情况下,生产环境中的警告是关闭的

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

福同学 把“ I’m an A”结尾 Def get _ b; 将“ I’m an B”结尾 Def get _ c; 将“ I’m an C”结尾

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 行动计划