1

RSpec は、最上位の名前空間を実行する「describe」メソッドを追加します。ただし、単にクラス/モジュールの外部でメソッドを定義する代わりに、次のようにします。

# code from rspec-core/lib/rspec/core/dsl.rb 
module RSpec
  module Core
    # Adds the `describe` method to the top-level namespace.
    module DSL
      def describe(*args, &example_group_block)
        RSpec::Core::ExampleGroup.describe(*args, &example_group_block).register
      end
    end
  end
end

extend RSpec::Core::DSL
Module.send(:include, RSpec::Core::DSL)

モジュールやクラスの外側で単に記述を定義するのではなく、この手法を使用する利点は何ですか? (私が知る限り、DSL モジュールは rspec-core の他の場所では使用されていません。)

4

2 に答える 2

3

この変更は数か月前に行ったのでdescribe、システム内のすべてのオブジェクトに追加されることはなくなりました。最上位で定義した場合:

def describe(*args)
end

...その場合、システム内のすべてのオブジェクトにはプライベートdescribeメソッドがあります。RSpec はシステム内のすべてのオブジェクトを所有しているわけではありませんdescribe。2 つのスコープで使用できる describe メソッドのみが必要です。

describe MyClass do
end

(最上位、メイン オブジェクトの外)

module MyModule
  describe MyClass do
  end
end

(どのモジュールからも離れているため、記述をモジュールスコープにネストします)

Moduleこれをモジュールに入れると、メイン オブジェクトへの拡張 (すべてのオブジェクトではなく、そのオブジェクトのみに追加する) とインクルード(すべてのモジュールに追加する) が容易になります。

于 2012-10-10T20:47:32.467 に答える
1

実際、コードにそれがすべてある場合、私はそれがはるかに優れているとは本当に信じていません。一般的な議論は、メソッドの所有者を確認することで、RSpec がこのメソッドをグローバル名前空間に追加する責任があることを簡単に確認できるということです。メソッドの場所にはすでにその情報が保存されているため、どういうわけか、これが必要だとは感じませんでした。

スコープ外でメソッドを定義することは、オブジェクトでプライベート インスタンス メソッドを定義することと同じです。

class Object
  private
  def double(arg)
    arg * 2
  end
end

double(3)      # OK
3.double(3)    # Error: double is private
self.double(3) # Error: double is private

質問に示されているコードに欠けている、意味のない特定のメソッド呼び出しを行うことを防ぐため、プライベート性は有用な側面だと思います。

ただし、モジュールでメソッドを定義することには利点がありますが、RSpec コードはそれを利用していないようです: を使用するmodule_functionと、インスタンス メソッドのプライベート性が保持されるだけでなく、パブリック クラス メソッドも取得されます。これは、同じ名前のインスタンス メソッドがある場合でも、クラス メソッドのバージョンを使用して、モジュールで定義されたメソッドを参照できることを意味します。

の一般的な例module_functionは、(別の 1 つです)Kernelのようなほとんどの関数のようなコア メソッドを含むモジュールです。を再定義するクラスにいる場合でも、必要に応じて明示的に使用できます。putsMathputsKernel#puts

class LikeAnIO
  def puts(string)
    @output << string
  end

  def do_work
    puts "foo" # inserts "foo" in @output
    Kernel.puts "foo" # inserts "foo" in $stdout
  end
end
于 2012-10-10T19:12:12.693 に答える