2008-11-16 9 views
111

Ich möchte eine Methode als veraltet markieren, damit Benutzer, die sie verwenden, ihren Code einfach überprüfen und aufholen können. In Java setzen Sie @Deprecated und jeder weiß, was das bedeutet.Best Practice, um veralteten Code in Ruby zu markieren?

Gibt es also einen bevorzugten Weg (oder sogar Tools) zu markieren und auf Abwertungen in Ruby zu überprüfen?

+0

Um fair zu sein, Java Annotations saugt ausgeschaltet, da sie keinen Wert auf einen potentiellen Ersatz-zu-Punkt haben –

Antwort

144

Für fast alle Fälle, abhängig von einer Bibliothek oder Metaprogrammierung für eine Abwertung ist Overkill. Fügen Sie einfach einen Kommentar zum rdoc hinzu und rufen Sie die Methode Kernel#warn auf. Zum Beispiel:

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 

Wenn Sie mit Yard statt rdoc, sollte Ihr doc Kommentar wie folgt aussehen:

# @deprecated Please use {#useful} instead 

Schließlich, wenn Sie zu tomdoc halten, um Ihren Kommentar Look wie folgt:

# Deprecated: Please use `useful` instead 

Veraltet: Gibt an, dass die Methode veraltet ist und in einer zukünftigen Version entfernt wird. Sie sollten dies verwenden, um Methoden zu dokumentieren, die öffentlich waren, aber bei der nächsten Hauptversion entfernt werden.


Auch vergessen Sie nicht, die veraltete Methode in einem zukünftigen (und richtig semver ‚d) lösen zu entfernen. Machen Sie nicht die gleichen Fehler wie die Java-Bibliotheken.

+3

Ich bin nicht sicher, es ist so sehr ein "Fehler" aus dem Java-Teil, eher ein großes Problem der Rückwärtskompatibilität (siehe http://StackOverflow.com/questions/314540), den der blindgaenger für seinen Ruby-Code nicht in Betracht ziehen muss. – VonC

+33

Code ist eine Verbindlichkeit. Je weniger Code du hast, desto besser. Abschreibungen sind gut für temporäre Rückwärtskompatibilität, aber im Laufe der Zeit wird es zum Crust. Wenn Personen * pensionierte Methoden verwenden müssen, sollten sie stattdessen ältere Versionen Ihrer Bibliotheken verwenden. –

+2

Ausgezeichnete Antwort. Ich möchte nur einen Link zu der Antwort hinzufügen, wo ich den Ansatz zeige, den ich in letzter Zeit verwendet habe, der auf der Ruby Std Lib beruht: http://stackoverflow.com/questions/293981/best-practice-to-mark-deprecated -code-in-ruby/23554720 # 23554720 –

7

Sie haben libdeprecated-ruby (2010-2012 Buch nicht rubygem in 2015)

Eine kleine Bibliothek sollte Entwickler mit veraltetem Code arbeiten unterstützen.
Die Idee stammt aus der Programmiersprache '', in der Entwickler bestimmten Code als veraltet markieren und dann die Ausführung von veraltetem Code zulassen/verbieten können.

+0

Der Link führt mich zu einer Seite über ein Debian-Paket. Dies scheint ähnlich (wenn nicht das gleiche) und ist ein RubyGem: https://rubygems.org/gems/deprecated –

12

Wenn Sie bösartig sein wollen (unter dem Vorwand, hilfreich zu sein), können Sie während einer Warnung die erste Zeile des Callstacks ausdrucken, damit die Entwickler wissen, wo sie einen veralteten Anruf verwenden.

Das ist gemein, weil Ich bin mir ziemlich sicher, dass es ein Performance-Hit ist.

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

Bei richtiger Anwendung, wird dies den absoluten Pfad zu der Datei und Zeile enthalten, in dem die veralteten Aufruf verwendet wurde. Weitere Informationen über Kernel :: Anrufer ist verfügbar here

+3

Ich halte das nicht für gemein. Ein kleiner Performance-Hit ist schöner, als wenn man nach dem veralteten Call jagt, und viel schöner als etwas, das bricht, wenn die Methode schließlich entfernt wird. –

1

Canivete ist ein Juwel, mit dem Sie Ihre Methoden auf einfache und elegante Weise ablehnen können. Ein wenig mehr darüber here.

3

Sie können Klasse Macros Muster verwenden und so etwas schreiben:

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

Wenn Schienen verwenden, können Sie das Modul # deprecate Methode haben.

6

Sie können auch ActiveSupport::Deprecation (in der Version 4.0 oder höher) verwenden, wie zum Beispiel:

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-Standardbibliothek ein Modul mit der Warnung Logik: http://ruby-doc.org/stdlib-1.9.3/libdoc/rubygems/rdoc/Gem/Deprecate.html. Ich neige dazu, es zu bevorzugen meine deprecation Nachrichten in einer „Standard“ Art und Weise zu erhalten:

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

Beachten Sie, dass mit diesem Ansatz, den Sie kostenlos Informationen gewinnen, wo der Anruf stattfand.

+0

Schön, wusste nicht darüber in Standard-lib. – Kris

+0

Gut zu helfen, Kris! –

+2

die führende '0' für ein numerisches Literal macht es oktal und sollte daher wahrscheinlich entfernt werden. –

1

Ich landete ein leichtes Verfahren werfen zusammen:

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

Dann, ein Verfahren verbitten einen Anruf bei dem Verfahren Körper einsetzen (oder einen Konstruktor für eine Klasse)

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

Es ist ziemlich deklarative und bietet Protokollierung mit relevanten Informationen. Ich bin nicht viel von einem Rubyist, also kann es etwas zwicken/YMMV benötigen.

6

Mit Active:

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

Warnungen werden in der Produktionsumgebung standardmäßig