Thực hành tốt nhất để đánh dấu mã không dùng nữa trong Ruby?


127

Tôi muốn đánh dấu một phương thức là không dùng nữa, vì vậy những người sử dụng nó có thể dễ dàng kiểm tra mã của họ và bắt kịp. Trong Java, bạn đặt @Deprecated và mọi người đều biết điều này có nghĩa là gì.

Vì vậy, có một cách ưa thích (hoặc thậm chí các công cụ) để đánh dấu và kiểm tra sự phản đối trong Ruby?


Công bằng mà nói, chú thích của Java rất tệ, vì nó không có giá trị để chỉ ra một sự thay thế tiềm năng
Heiko Rupp

Câu trả lời:


160

Đối với hầu hết tất cả các trường hợp, tùy thuộc vào một thư viện hoặc siêu lập trình cho một sự phản đối là quá mức cần thiết. Chỉ cần thêm một bình luận cho các ndoc và gọi Kernel#warnphương thức. Ví dụ:

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

Nếu bạn đang sử dụng Yard thay vì ndoc , nhận xét tài liệu của bạn sẽ giống như thế này:

# @deprecated Please use {#useful} instead

Cuối cùng, nếu bạn tuân thủ tomdoc , hãy bình luận của bạn như thế này:

# Deprecated: Please use `useful` instead

Không dùng nữa: Cho biết phương thức không được dùng nữa và sẽ bị xóa trong phiên bản tương lai. Bạn NÊN sử dụng điều này để ghi lại các phương thức Công khai nhưng sẽ bị xóa ở phiên bản chính tiếp theo.


Ngoài ra, đừng quên để loại bỏ các phương pháp tán thành trong một số trong tương lai (và đúng semver 'd) phát hành . Đừng mắc những lỗi tương tự như các thư viện Java đã làm.


4
Tôi không chắc chắn đó là một "lỗi" từ phần Java, thay vào đó là một vấn đề tương thích ngược rất lớn (xem stackoverflow.com/questions/314540 ), rằng người mù có thể không cần xem xét mã Ruby của mình.
VonC

38
Mã là một trách nhiệm pháp lý. Càng ít mã bạn phải duy trì tốt hơn. Khấu hao là tốt cho khả năng tương thích ngược tạm thời, nhưng theo thời gian nó sẽ trở nên khó khăn. Nếu mọi người cần sử dụng các phương thức đã nghỉ hưu, họ nên sử dụng các phiên bản cũ hơn của thư viện của bạn.
Ryan McGeary

2
Phản ứng nhanh. Tôi chỉ muốn thêm một liên kết đến phản hồi nơi tôi hiển thị cách tiếp cận mà tôi đã sử dụng gần đây, dựa trên Ruby Std Lib: stackoverflow.com/questions/293981/ Lỗi
Ricardo Valeriano

1
@RicardoValeriano Tôi đồng ý, phản hồi của bạn nên được tích hợp (hoặc bình chọn cao hơn, hoặc cả hai :)).
Felix

53

Thư viện Ruby Standard có một mô-đun với logic cảnh báo: https://ruby-doc.org/stdlib/libdoc/rubygems/rdoc/Gem/Deprecate.html . Tôi có xu hướng thích nó để duy trì các thông điệp phản đối của mình theo cách "chuẩn":

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

Lưu ý rằng với phương pháp này, bạn sẽ có được thông tin miễn phí về nơi cuộc gọi diễn ra.


Đẹp, không biết về điều này trong lib tiêu chuẩn.
Kris

2
hàng đầu 0cho một chữ số làm cho nó bát phân và do đó có thể sẽ bị xóa.
Matt Whoop

3
Cảm ơn vì tiền hỗ trợ. Tôi đã từ chối toàn bộ một lớp và đề nghị sử dụng lớp mới hơn:deprecate :initialize, UseThisClassInstead, 2017, 5
Jon Kern

Ví dụ sử dụng tuyệt vời, Jon. Thực sự tốt đẹp một.
Ricardo Valeriano

5
Câu trả lời đúng trước đây đã không được chấp nhận và câu trả lời của Ricardo Valueriano nên được sử dụng
simon

14

Nếu bạn muốn có ý nghĩa (theo hướng dẫn là hữu ích), bạn có thể in dòng đầu tiên của cuộc gọi trong cảnh báo để cho các nhà phát triển biết họ đang sử dụng cuộc gọi không dùng đến đâu.

Điều này có nghĩa là bởi vì tôi khá chắc chắn rằng đó là một hit hiệu suất.

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

Khi được sử dụng một cách chính xác, điều này sẽ bao gồm đường dẫn tuyệt đối đến tệp và dòng nơi cuộc gọi không được sử dụng. Thông tin thêm về Kernel :: caller có sẵn ở đây


5
Tôi không xem xét điều này có nghĩa. Một cú đánh hiệu suất nhỏ sẽ tốt hơn là phải đuổi theo nơi cuộc gọi không được chấp nhận và đẹp hơn nhiều so với thứ gì đó bị phá vỡ khi phương thức cuối cùng bị loại bỏ.
Nathan Long

13

Sử dụng ActiveSupport:

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

Cảnh báo được tắt trong môi trường sản xuất theo mặc định


12

Bạn cũng có thể sử dụng ActiveSupport::Deprecation(có sẵn trong phiên bản 4.0+), như sau:

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

Bạn có libdeprecated-ruby(2010-2012, không có sẵn nữa trên rubygem năm 2015)

Một thư viện nhỏ nhằm hỗ trợ các nhà phát triển làm việc với mã không dùng nữa.
Ý tưởng xuất phát từ Dngôn ngữ lập trình '', nơi các nhà phát triển có thể đánh dấu một số mã nhất định là không dùng nữa, sau đó cho phép / không cho phép khả năng thực thi mã không dùng nữa.

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

Liên kết đưa tôi đến một trang về gói Debian. Điều này có vẻ tương tự (nếu không giống nhau) và là một RubyGem: rubygems.org/gems/deprecated
Benjamin Oakes

3

Bạn có thể sử dụng mẫu Macro Macros và viết một cái gì đó như thế này:

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

Khi sử dụng đường ray, bạn có phương thức Module # deprecate.


2

Canivete là một viên ngọc cho phép bạn loại bỏ các phương pháp của mình một cách đơn giản và thanh lịch. Một chút nữa về nó ở đây .


1

Cuối cùng tôi đã đưa ra một phương pháp nhẹ:

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

Sau đó, để loại bỏ một phương thức chèn một cuộc gọi trong thân phương thức (hoặc một hàm tạo cho một lớp)

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

Đó là khai báo khá và cung cấp đăng nhập với thông tin liên quan. Tôi không phải là một Rubyist nhiều nên nó có thể cần một số điều chỉnh / YMMV.


0

Chúng ta có thể sử dụng các phương thức macro nội bộ. Thí dụ:

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) 

kết thúc cuối

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

o = Foo.new p oa

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.