Ruby'de kullanımdan kaldırılan kodu işaretlemek için en iyi uygulama?


127

Bir yöntemi kullanımdan kaldırıldı olarak işaretlemek istiyorum, böylece onu kullanan kişiler kodunu kolayca kontrol edebilir ve yakalayabilir. Java'da @Deprecated ayarını yaparsınız ve bunun ne anlama geldiğini herkes bilir.

Öyleyse, Ruby'de kullanımdan kaldırmaları işaretlemek ve kontrol etmek için tercih edilen bir yol (veya hatta araçlar) var mı?


Potansiyel bir değiştirme için noktaya değeri yoktur adil olmak gerekirse, Java'nın açıklama, berbat
Heiko Rupp

Yanıtlar:


160

Neredeyse tüm durumlar için, bir kitaplığa veya kullanımdan kaldırmaya yönelik meta programlamaya bağlı olarak aşırı derecede abartılıdır. Sadece rdoc'a bir yorum ekleyin ve Kernel#warnyöntemi çağırın . Örneğin:

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 yerine Yard kullanıyorsanız , doküman yorumunuz şöyle görünmelidir:

# @deprecated Please use {#useful} instead

Son olarak, tomdoc'a bağlı kalırsanız , yorumunuzun şöyle görünmesini sağlayın:

# Deprecated: Please use `useful` instead

Kullanımdan kaldırıldı: Yöntemin kullanımdan kaldırıldığını ve gelecekteki bir sürümde kaldırılacağını gösterir. Bunu, Genel olan ancak bir sonraki ana sürümde kaldırılacak olan yöntemleri belgelemek için kullanmanız GEREKİR.


Ayrıca, bazı gelecekteki (ve uygun şekilde semver 'd) sürümlerde kullanımdan kaldırılmış yöntemi kaldırmayı unutmayın . Java kitaplıklarının yaptığı hataları yapmayın.


4
Bunun Java kısmından çok büyük bir "hata" olduğundan emin değilim, daha ziyade büyük bir geriye dönük uyumluluk sorunu (bkz. Stackoverflow.com/questions/314540 ), bu blindgaenger'ın Ruby kodu için dikkate alması gerekmeyebilir.
VonC

38
Kod bir sorumluluktur. Ne kadar az kod sağlamanız gerekiyorsa o kadar iyidir. Kullanımdan kaldırmalar, geçici geriye dönük uyumluluk için iyidir, ancak zamanla işe yaramaz hale gelir. Kişilerin emekli yöntemleri kullanmaları gerekiyorsa , bunun yerine kitaplıklarınızın eski sürümlerini kullanmaları gerekir.
Ryan McGeary

2
Mükemmel yanıt. Son zamanlarda kullandığım yaklaşımı gösterdiğim yanıta, Ruby Std Lib'e dayanan bir bağlantı eklemek istiyorum: stackoverflow.com/questions/293981/…
Ricardo Valeriano

1
@RicardoValeriano Kabul ediyorum, yanıtınız entegre edilmelidir (veya daha yüksek oy veya her ikisi de :)).
Felix

54

Ruby Standard Library, uyarı mantığına sahip bir modüle sahiptir: https://ruby-doc.org/stdlib/libdoc/rubygems/rdoc/Gem/Deprecate.html . Kullanımdan kaldırma mesajlarımı "standart" bir şekilde tutmasını tercih ederim:

# 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.

Bu yaklaşımla aramanın nerede gerçekleştiği hakkında ücretsiz bilgi edinebileceğinizi unutmayın.


Güzel, bunu standart kitaplıkta bilmiyordum.
Kris

2
0Sayısal değişmez değerin başında , onu sekizlik yapar ve bu nedenle büyük olasılıkla kaldırılmalıdır.
Matt Whipple

3
Bahşiş için teşekkürler. Tüm bir sınıfı kullanımdan kaldırdım ve daha yeni sınıfın kullanılmasını deprecate :initialize, UseThisClassInstead, 2017, 5
Jon Kern

Harika bir kullanım örneği, Jon. Gerçekten güzel.
Ricardo Valeriano

5
Önceki doğru cevap kullanımdan kaldırıldı ve Ricardo Valueriano'nun cevabı şimdi kullanılmalı
simon

14

Eğer kaba olmak istiyorsanız (yardımcı olma kurnazlığı altında), geliştiricilere kullanımdan kaldırılmış bir aramayı nerede kullandıklarını bildirmek için bir uyarı sırasında çağrı yığınının ilk satırını yazdırabilirsiniz.

Bu demek çünkü bunun bir performans-hit olduğundan oldukça eminim.

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

Doğru kullanıldığında bu, dosyanın mutlak yolunu ve kullanımdan kaldırılan çağrının kullanıldığı satırı içerecektir. Kernel :: caller hakkında daha fazla bilgiyi burada bulabilirsiniz


5
Bunun anlamsız olduğunu düşünmüyorum. Küçük bir performans vuruşu, kullanımdan kaldırılan aramanın olduğu yerde kovalamak zorunda kalmaktan daha hoş ve yöntem sonunda kaldırıldığında bir şey bozmaktan çok daha hoş.
Nathan Long

13

ActiveSupport'u kullanma:

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

Üretim ortamında uyarılar varsayılan olarak kapalıdır


12

Ayrıca ActiveSupport::Deprecation(4.0+ sürümünde mevcuttur) aşağıdakileri de kullanabilirsiniz :

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

Var libdeprecated-ruby(2010-2012, 2015'te artık rubygem'de mevcut değil)

Geliştiricilerin kullanımdan kaldırılmış kodla çalışmasına yardımcı olmayı amaçlayan küçük bir kitaplık.
Fikir D, geliştiricilerin belirli bir kodu kullanımdan kaldırılmış olarak işaretleyebilecekleri ve ardından kullanımdan kaldırılmış kodu yürütme yeteneğine izin verebilecekleri / engelleyebilecekleri ' ' programlama dilinden geliyor .

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

Bağlantı beni Debian paketiyle ilgili bir sayfaya götürüyor. Bu benzer görünüyor (aynı değilse) ve bir RubyGem: rubygems.org/gems/deprecated
Benjamin Oakes

3

Sınıf Makroları kalıbını kullanabilir ve şöyle bir şey yazabilirsiniz:

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

3

Rayları kullanırken, Modül # kullanımdan kaldırma yöntemine sahipsiniz.


2

Canivete , yöntemlerinizi basit ve zarif bir şekilde kullanımdan kaldırmanızı sağlayan bir mücevherdir. Bununla ilgili biraz daha fazla bilgi burada .


1

Sonunda hafif bir yöntemi bir araya getirdim:

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

Sonra bir yöntemi kullanımdan kaldırmak için yöntem gövdesine (veya bir sınıf için yapıcı) bir çağrı ekleyin

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

Oldukça açıklayıcıdır ve ilgili bilgilerle günlük kaydı sağlar. Pek Rubyist değilim, bu yüzden biraz ince ayar / YMMV'ye ihtiyacı olabilir.


0

Dahili makro yöntemlerini kullanabiliriz. Misal:

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) 

son sonu

kullanımdan kaldır: a,: get_a kullanımdan kaldır: b,: get_b kullanımdan kaldır: c,: get_c end

o = Foo.new p oa

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.