Подтвердить что ты не робот

Какой предпочтительный способ (лучший стиль) назвать пространство имен в Ruby? Сингулярное или множественное?

Каковы для вас плюсы и минусы использования:

FooLib::Plugins
FooLib::Plugins::Bar

против.

FooLib::Plugin
FooLib::Plugin::Bar

соглашения об именах? И что бы вы использовали или что используете? Что чаще всего используется в сообществе?

4b9b3361

Ответ 1

Использование:

module FooLib end
module FooLib::Plugins end
class  FooLib::Plugins::Plugin; end #the base for plugins
class  FooLib::Plugins::Bar < FooLib::Plugins::Plugin; end
class  FooLib::Plugins::Bar2 < FooLib::Plugins::Plugin; end

или другими словами:

module FooLib
  module Plugins
    class Plugin; end #the base for plugins
    class Bar < Plugin; end
    class Bar2 < Plugin; end
  end
end

Также упорядочивайте файлы следующим образом:

- foo_lib/
  - plugins/
    - plugin.rb
    - bar.rb
    - bar2.rb

Это как Rails делает это (так это путь Rails). То есть посмотрите пространство имен ассоциаций и класс Ассоциации:: Ассоциация, из которого наследуются все классы, входящие в пространство имен ассоциаций (т.е. Ассоциации:: SingularAssociation).

Ответ 2

Мне FooLib::Plugins отображается как модуль, используемый как пространство имен, в котором хранятся различные классы плагинов. FooLib::Plugin выглядит как суперкласс для плагинов FooLib.

В FooLib::Plugins::Bar, Bar определенно похоже на имя плагина. С FooLib::Plugin::Bar я сомневаюсь, что Bar был вспомогательным классом, используемым Foo::Plugin, или именем плагина.

Ответ 3

Предполагая, что Plugin является базовым классом:

  • class FooLib::Plugin::Bar < FooLib::Plugin

    Это тот, который я использую и рекомендую. Bar является Plugin в FooLib и наследуется от FooLib::Plugin. Он также поддерживает плагины, предоставляемые библиотекой FooLib, вложенной в пространство имен общего класса, которое естественно читается:

    # Assign the Bar Plugin of the FooLib library to p.
    p = FooLib::Plugin::Bar
    

    Если бы мне пришлось разработать сторонний плагин для вашей библиотеки, я бы создал следующую структуру:

    # Baz is a Plugin for the FooLib library provided by BarLib.
    class BarLib::FooLib::Plugin::Baz < ::FooLib::Plugin
    

    Обратите внимание, что я зеркалирую иерархию FooLib, но в пространстве имен BarLib. Я бы не стал распространять его напрямую.

  • class FooLib::Plugins::Bar < FooLib::Plugin

    Я также использовал этот, и я думаю, что это имеет наибольший смысл. Bar extends FooLib::Plugin и является одним из Plugins, предоставленным FooLib. Однако он создает потенциально ненужный модуль.

    Я думаю, что это был бы отличный выбор, если Plugins был центральным репозитором плагинов, который реализует такие методы, как Plugins.add, Plugins.all и Plugins.loaded.

    Используйте его, если вы можете обосновать дополнительный модуль.

  • class FooLib::Plugins::Bar < FooLib::Plugins

    Не имеет большого смысла для меня. Bar является одним из Plugins в FooLib, эта часть выглядит отлично. Однако он наследует от Plugins. Наследует ли он от нескольких плагинов? Это звучит странно для меня; имя класса не должно предлагать что-то невозможное.

Ответ 4

Как правило, подход, который я предпочитаю, имеет следующий вид:

module Foo
  module Plugin
    class Base; end
  end
end

class Foo::Plugin::Bar < Foo::Plugin::Base; end

Класс Base для плагинов - это соглашение, найденное повсеместно в кодовой базе RubyOnRails, а также многие другие. (например, ActiveRecord::Base, ActionController::Base и т.д.)

Я не согласен с подходом @Matheus Moreira, где Foo::Plugin используется как базовый класс, так и пространство имен для плагинов.

Единственная функциональная причина, по которой это не должно быть сделано, связана с конвенцией - в сообществе Ruby можно найти гораздо меньше экземпляров классов как пространств имен, чем модулей. Единственный раз, когда я действительно вижу классы, используемые как пространство имен для другого класса, заключается в том, что цель этого класса является частной для класса пространства имен и не используется извне.

Ответ 5

Я бы включил подход, описанный @jtrim.

Учитывая, что модуль (т.е. плагин) используется только для пространства имен, я обычно переопределяю новый метод в модуле:

module Foo
  module Plugin

    def self.included(base)
      raise "cannot be included"
    end

    def self.extended(base)
      raise "cannot extend"
    end

    def self.new(*args)
      Base.new(*args)
    end

    class Base;end
  end
end


base_plugin_obj = Foo::Plugin.new(...)