2008-11-16 17 views
111

Me gustaría marcar un método como obsoleto, por lo que las personas que lo usan pueden verificar fácilmente su código y ponerse al día. En Java establece @Deprecated y todos saben lo que esto significa.¿La mejor práctica para marcar el código obsoleto en Ruby?

¿Existe alguna forma (o incluso herramientas) preferidas para marcar y verificar las deprecaciones en Ruby?

+0

Para ser justos, anotación de Java chupa, ya que no tiene ningún valor para apuntar a un posible reemplazo –

Respuesta

144

Para casi todos los casos, en función de una biblioteca o metaprogramming para una desaprobación es una exageración. Simplemente agregue un comentario al rdoc y llame al método Kernel#warn. Por ejemplo:

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 

Si está utilizando Yard en lugar de rdoc, el comentario de documentación debería tener este aspecto:

# @deprecated Please use {#useful} instead 

Por último, si se adhieren a tomdoc, hacer que su mirada comentario como este:

# Deprecated: Please use `useful` instead 

Obsoleto: indica que el método está en desuso y se eliminará en una versión futura. DEBE usar esto para documentar los métodos que eran públicos, pero se eliminarán en la siguiente versión principal.


Además, no se olvide de quitar el método obsoleto en un futuro (y adecuadamente semver 'd) liberar. No cometa los mismos errores que las bibliotecas de Java.

+3

No estoy seguro de que sea tanto un "error" de la parte de Java, sino un gran problema de compatibilidad con versiones anteriores (ver http://stackoverflow.com/questions/314540), ese blindgaenger podría no necesitar considerar su código Ruby. – VonC

+33

El código es una responsabilidad. Cuanto menos código tenga para mantener, mejor. Las depreciaciones son buenas para la compatibilidad retroactiva temporal, pero con el tiempo se vuelve defectuoso. Si las personas * necesitan * utilizar métodos retirados, en su lugar deberían usar versiones anteriores de sus bibliotecas. –

+2

Excelente respuesta. Solo quiero agregar un enlace a la respuesta donde muestro el enfoque que he usado últimamente, que se basa en Ruby Std Lib: http://stackoverflow.com/questions/293981/best-practice-to-mark-deprecated -code-en-ruby/23554720 # 23554720 –

7

Usted tiene libdeprecated-ruby (2010-2012, no habrá mas de rubygem en 2015)

Una pequeña biblioteca destinada a ayudar a los desarrolladores que trabajan con código obsoleto.
La idea proviene del lenguaje de programación 'D', donde los desarrolladores pueden marcar ciertos códigos como obsoletos y luego permitir/no permitir la capacidad de ejecutar código obsoleto.

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 
+0

El enlace me lleva a una página sobre un paquete Debian. Esto parece similar (si no es el mismo) y es un RubyGem: https://rubygems.org/gems/deprecated –

12

Si quiere ser malo (bajo la astucia de ser útil) puede imprimir la primera línea de la pila de llamadas durante una advertencia para que los desarrolladores sepan dónde están utilizando una llamada obsoleta.

Esto es malo porque Estoy bastante seguro de que es un golpe de rendimiento.

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

Cuando se usan correctamente, esto incluirá la ruta absoluta al archivo y la línea donde se utilizó la llamada en desuso. Más información sobre Kernel :: la persona que llama está disponible here

+3

No considero que esto sea malo. Un pequeño golpe de rendimiento es mejor que tener que buscar dónde estaba la llamada obsoleta, y mucho mejor que algo que se rompe cuando finalmente se elimina el método. –

1

Canivete es una joya que le permite despreciar sus métodos de manera simple y elegante. Un poco más al respecto here.

3

Puede utilizar el patrón Clase Macros y escribir algo como esto:

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

Al utilizar los carriles, que tienen el método # Desaprobar módulo.

6

También puede utilizar ActiveSupport::Deprecation (disponible en la versión 4.0 o superior), tales como:

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) 
36

Rubí biblioteca estándar tiene un módulo con la lógica de alerta: http://ruby-doc.org/stdlib-1.9.3/libdoc/rubygems/rdoc/Gem/Deprecate.html. Yo tiendo a preferir que le permite mantener mis mensajes de desaprobación de una manera "estándar":

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

Tenga en cuenta que con este enfoque va a ganar para obtener información gratuita acerca de donde se produjo la llamada.

+0

Agradable, no sabía esto en lib estándar. – Kris

+0

¡Me alegro de ayudar, Kris! –

+2

el '0' inicial para un literal numérico lo convierte en octal y, por lo tanto, debería eliminarse. –

1

terminé tirando juntos un método ligera:

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

Entonces desaprobar un método de insertar una llamada en el cuerpo del método (o un constructor para una clase)

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

Es bastante declarativa y proporciona el registro con información relevante. No soy muy Rubyista así que puede necesitar algunos ajustes/YMMV.

6

Usando ActiveSupport:

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

Señales de aviso desactivadas en el entorno de producción de manera predeterminada

Cuestiones relacionadas