Rubyで非推奨のコードをマークするためのベストプラクティスは?


127

メソッドを非推奨としてマークしたいので、そのメソッドを使用している人々が簡単にコードをチェックして追いつくことができます。Javaでは@Deprecatedを設定し、これが何を意味するかを誰もが知っています。

それで、Rubyの非推奨をマークしてチェックするための好ましい方法(またはツール)はありますか?


公平を期すために、Javaの注釈は、潜在的な置き換えを示す価値がないため、
うんざり

回答:


160

ほとんどの場合、ライブラリまたはメタプログラミングに依存して非推奨にするのはやりすぎです。コメントを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の代わりにYardを使用している場合、ドキュメントのコメントは次のようになります。

# @deprecated Please use {#useful} instead

最後に、tomdocを使用する場合は、コメントを次のようにします。

# Deprecated: Please use `useful` instead

非推奨:メソッドが非推奨であり、将来のバージョンで削除されることを示します。これを使用して、パブリックであったが次のメジャーバージョンで削除されるメソッドを文書化する必要があります。


また、将来の(そして適切にサーバー化された)リリースで非推奨のメソッドを削除することを忘れないでください。Javaライブラリが行ったのと同じ間違いをしないでください。


4
私はそれがJava部分の「間違い」ではなく、大きな後方互換性の問題(stackoverflow.com/questions/314540を参照)であることを確信していないため、blindgaengerは彼のRubyコードについて考慮する必要がないかもしれません。
VonC、2008

38
コードは責任です。維持しなければならないコードが少ないほど良いです。非推奨は一時的な下位互換性には適していますが、時間がたつと残酷になります。廃止されたメソッドを使用する必要がある場合は、代わりに古いバージョンのライブラリを使用する必要があります。
Ryan McGeary

2
優れた応答。私はちょうどRubyのSTDのLibに依存している私は、私が最近使用したことのアプローチを示し、応答、へのリンクを追加したい:stackoverflow.com/questions/293981/...
リカルドValeriano

1
@RicardoValeriano同意します。あなたの回答は統合する必要があります(またはそれ以上の投票、または両方:)。
Felix

53

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.

このアプローチを使用すると、呼び出しが行われた場所に関する無料の情報が得られることに注意してください。


いいですね、標準ライブラリではこれについて知りませんでした。
クリス

2
0数値リテラルの先頭は、それを8進数にするため、削除する必要があります。
Matt Whipple

3
先端をありがとう。クラス全体を廃止し、新しいクラスを使用することを提案しました:deprecate :initialize, UseThisClassInstead, 2017, 5
Jon Kern

すばらしい使用例、ジョン。本当にいいもの。
Ricardo Valeriano

5
以前の正解は非推奨になり、Ricardo Valuerianoの回答を使用する必要があります
simon

14

意地悪になりたい場合(役立つという名目で)、警告中にコールスタックの最初の行を出力して、非推奨の呼び出しを使用している場所を開発者に知らせることができます。

これは、パフォーマンスヒットになると確信しているためです。

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

正しく使用すると、非推奨の呼び出しが使用されたファイルと行への絶対パスが含まれます。Kernel :: callerの詳細については、こちらをご覧ください。


5
私はこの意味を考えていません。小さなパフォーマンスヒットは、廃止された呼び出しがあった場所を追跡する必要があるよりも優れており、メソッドが最終的に削除されるときに何かが壊れるよりもはるかに優れています。
Nathan Long

13

ActiveSupportの使用:

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

警告は本番環境ではデフォルトでオフになっています


12

次の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)

8

あなたは持っています 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

リンクをクリックすると、Debianパッケージに関するページに移動します。これは似ているように見えますが(同じではない場合)、RubyGemです: rubygems.org/gems/deprecated
Benjamin Oakes

3

クラスマクロパターンを使用して、次のように記述できます。

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



1

私は軽量のメソッドを一緒に投げることになりました:

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が必要になるかもしれません。


0

内部マクロメソッドを使用できます。例:

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) 

終わり終わり

deprecate:a、:get_a deprecate:b、:get_b deprecate:c、:get_c end

o = Foo.new p oa

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.