2008-11-16 9 views
111

Je voudrais marquer une méthode comme obsolète, afin que les personnes qui l'utilisent puissent facilement vérifier leur code et le rattraper. Dans Java, vous définissez @Deprecated et tout le monde sait ce que cela signifie.Meilleure pratique pour marquer le code obsolète dans Ruby?

Alors y a-t-il un moyen préféré (ou même des outils) pour marquer et vérifier les dépréciations dans Ruby?

+0

Pour être juste, l'annotation Java suce, car il n'a pas de valeur pour pointer vers un remplacement potentiel –

Répondre

144

Pour presque tous les cas, en fonction d'une bibliothèque ou metaprogramming pour Désapprobation est surpuissant. Ajoutez simplement un commentaire à la commande rdoc et appelez la méthode Kernel#warn. Par exemple:

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 vous utilisez Yard au lieu de rdoc, votre commentaire doc devrait ressembler à ceci:

# @deprecated Please use {#useful} instead 

Enfin, si vous adhérez à tomdoc, rendre votre commentaire comme ceci:

# Deprecated: Please use `useful` instead 

Déconseillé: Indique que la méthode est obsolète et qu'elle sera supprimée dans une future version. Vous DEVRIEZ l'utiliser pour documenter des méthodes qui étaient publiques mais qui seront supprimées à la prochaine version majeure.


En outre, ne pas oublier d'enlever la méthode désapprouvée dans un avenir (et bien semver « d) libérer. Ne faites pas les mêmes erreurs que les bibliothèques Java.

+3

Je ne suis pas sûr que ce soit tellement une "erreur" de la partie Java, plutôt un énorme problème de compatibilité descendante (voir http://stackoverflow.com/questions/314540), que blindgaenger pourrait ne pas avoir besoin de considérer pour son code Ruby. – VonC

+33

Le code est une responsabilité. Le moins de code que vous devez maintenir le mieux. Les dépréciations sont bonnes pour une rétrocompatibilité temporaire, mais avec le temps, elles deviennent cruelles. Si les personnes ont besoin * d'utiliser des méthodes supprimées, elles doivent utiliser des versions plus anciennes de vos bibliothèques. –

+2

Excellente réponse. Je veux juste ajouter un lien vers la réponse où je montre l'approche que j'ai utilisée récemment, qui repose sur le Ruby Std Lib: http://stackoverflow.com/questions/293981/best-practice-to-mark-deprecated -code-in-ruby/23554720 # 23554720 –

7

Vous n'avez libdeprecated-ruby (2010-2012, ne sont plus disponibles sur rubygem en 2015)

Une petite bibliothèque destinée à aider les développeurs qui travaillent avec le code désapprouvée.
L'idée vient du langage de programmation 'D', où les développeurs peuvent marquer certains codes comme obsolètes, puis autoriser/interdire la possibilité d'exécuter du code obsolète.

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

Le lien me prend à une page sur un paquet Debian. Cela semble similaire (si ce n'est pas la même chose) et est un RubyGem: https://rubygems.org/gems/deprecated –

12

Si vous voulez être méchant (sous le prétexte d'être utile), vous pouvez imprimer la première ligne de la callstack pendant un avertissement pour informer les développeurs de l'endroit où ils utilisent un appel obsolète.

Ceci est méchant parce que Je suis presque sûr que c'est une performance-hit.

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

Lorsqu'ils sont utilisés correctement, cela comprendra le chemin absolu du fichier et de la ligne où a été utilisé l'appel dépréciée. Plus d'informations sur Kernel :: caller est disponible here

+3

Je ne considère pas cela comme un moyen. Un petit coup de performance est plus agréable que d'avoir à chercher où se trouvait l'appel désapprouvé, et beaucoup plus agréable que quelque chose qui se brise lorsque la méthode est finalement supprimée. –

1

Canivete est une gemme qui vous permet de déprécier vos méthodes de manière simple et élégante. Un peu plus à ce sujet here.

3

Vous pouvez utiliser des macros modèle de classe et d'écrire quelque chose comme ceci:

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

Lorsque vous utilisez des rails, vous avez la méthode du module # de Déprécier.

6

Vous pouvez également utiliser ActiveSupport::Deprecation (disponible dans la version 4.0+), en tant que tel:

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

Ruby Standard Library dispose d'un module avec la logique d'avertissement: http://ruby-doc.org/stdlib-1.9.3/libdoc/rubygems/rdoc/Gem/Deprecate.html. J'ai tendance à préférer maintenir mes messages dans une désapprobation « standard » chemin:

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

Notez que cette approche vous gagnerez des informations gratuitement sur l'endroit où a eu lieu l'appel.

+0

Nice, ne savait pas à ce sujet dans la norme lib. – Kris

+0

Content de t'aider, Kris! –

+2

le '0 'principal pour un littéral numérique le rend octal et devrait donc probablement être supprimé. –

1

Je fini par jeter ensemble une méthode légère:

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

ensuite à désapprouver une méthode insérer un appel dans le corps de la méthode (ou un constructeur pour une classe)

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

Il est assez déclarative et fournit la journalisation avec des informations pertinentes. Je ne suis pas très Rubisiste, donc il faudra peut-être quelques ajustements/YMMV.

6

En utilisant ActiveSupport:

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

Avertissements sont désactivés dans un environnement de production par défaut

Questions connexes