What is the preferred way (better style) to name a namespace in Ruby? Singular or Plural?

蓝咒 提交于 2019-12-02 23:39:02

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.

Matheus Moreira

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.

Chetan Patil

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!