Каковы для вас плюсы и минусы использования:
FooLib::Plugins
FooLib::Plugins::Bar
против.
FooLib::Plugin
FooLib::Plugin::Bar
соглашения об именах? И что бы вы использовали или что используете? Что чаще всего используется в сообществе?
Каковы для вас плюсы и минусы использования:
FooLib::Plugins
FooLib::Plugins::Bar
против.
FooLib::Plugin
FooLib::Plugin::Bar
соглашения об именах? И что бы вы использовали или что используете? Что чаще всего используется в сообществе?
Использование:
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).
Мне FooLib::Plugins
отображается как модуль, используемый как пространство имен, в котором хранятся различные классы плагинов. FooLib::Plugin
выглядит как суперкласс для плагинов FooLib.
В FooLib::Plugins::Bar
, Bar
определенно похоже на имя плагина. С FooLib::Plugin::Bar
я сомневаюсь, что Bar
был вспомогательным классом, используемым Foo::Plugin
, или именем плагина.
Предполагая, что 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
. Наследует ли он от нескольких плагинов? Это звучит странно для меня; имя класса не должно предлагать что-то невозможное.
Как правило, подход, который я предпочитаю, имеет следующий вид:
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 можно найти гораздо меньше экземпляров классов как пространств имен, чем модулей. Единственный раз, когда я действительно вижу классы, используемые как пространство имен для другого класса, заключается в том, что цель этого класса является частной для класса пространства имен и не используется извне.
Я бы включил подход, описанный @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(...)