What are for you the pros and cons of using:
FooLib::Plugins
FooLib::Plugins::Bar
vs.
FooLib::Plugin
FooLib::Plugin::Bar
naming conventions? And what would you use or what are you using? What is more commonly used in the comunity?
What are for you the pros and cons of using:
FooLib::Plugins
FooLib::Plugins::Bar
vs.
FooLib::Plugin
FooLib::Plugin::Bar
naming conventions? And what would you use or what are you using? What is more commonly used in the comunity?
Use:
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
or in a different words:
module FooLib
module Plugins
class Plugin; end #the base for plugins
class Bar < Plugin; end
class Bar2 < Plugin; end
end
end
Also arrange the files like this:
- foo_lib/
- plugins/
- plugin.rb
- bar.rb
- bar2.rb
This is how Rails does it (so this is the Rails Way). I.e. look at the Associations namespace and the Associations::Association class from which all of the classes form the Associations namespace inherits (i.e. Associations::SingularAssociation).
To me FooLib::Plugins
appears like a module, used as a namespace which various plugin classes are kept in. FooLib::Plugin
looks like a superclass for FooLib plugins.
In FooLib::Plugins::Bar
, Bar
definitely seems like the name of a plugin. With FooLib::Plugin::Bar
, I would be doubtful whether Bar
was a helper class used by Foo::Plugin
, or the name of a plugin.
Assuming Plugin
is a base class:
class FooLib::Plugin::Bar < FooLib::Plugin
This is the one I use and recommend. Bar
is a Plugin
in FooLib
and it inherits from FooLib::Plugin
. It also keeps the plugins provided by the FooLib
library nested under the namespace of the general class, which reads naturally:
# Assign the Bar Plugin of the FooLib library to p.
p = FooLib::Plugin::Bar
If I were to develop a third party plugin for your library, I would create the following structure:
# Baz is a Plugin for the FooLib library provided by BarLib.
class BarLib::FooLib::Plugin::Baz < ::FooLib::Plugin
Note that I mirror the FooLib
hierarchy, but under BarLib
's namespace. I would not extend it directly.
class FooLib::Plugins::Bar < FooLib::Plugin
I have also used this one, and I think it makes the most sense. Bar
extends FooLib::Plugin
and is one of the Plugins
provided by FooLib
. However, it creates a potentially needless module.
I think this would be a great choice if Plugins
was a central plugin repository that implements methods like Plugins.add
, Plugins.all
and Plugins.loaded
.
Use it if you can justify the extra module.
class FooLib::Plugins::Bar < FooLib::Plugins
Doesn't make a lot of sense to me. Bar
is one of the Plugins
in FooLib
, that part looks fine. However, it inherits from Plugins
. Is it inheriting from more than one plugin? It sounds strange to me; the class name shouldn't suggest something that is impossible.
I would second the approach outlined by @jtrim.
Given that the module (i.e. Plugin) is being used for namespacing only, I typically override the new method in the module:
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(...)
Generally, the approach I tend to take is:
module Foo
module Plugin
class Base; end
end
end
class Foo::Plugin::Bar < Foo::Plugin::Base; end
The Base
class for plugins is a convention found all over the place in the RubyOnRails codebase as well as many others. (e.g. ActiveRecord::Base
, ActionController::Base
, etc.)
I disagree with @Matheus Moreira's approach where Foo::Plugin
is used both as the base class and the namespace for plugins.
The only functional reason why this shouldn't be done has to do with convention - in the Ruby community one will find many less instances of classes as namespaces than modules. The only time I really see classes used as a namespace for another class is when the purpose of said class is private to the namespace class and is not used externally.