在Ruby中,命名namespace的首选方式(更好的风格)是单数还是复数?

32

根据您的经验,使用以下内容的利弊是什么:

FooLib::Plugins
FooLib::Plugins::Bar

对比。

FooLib::Plugin
FooLib::Plugin::Bar

命名约定?你会使用什么或正在使用什么?在社区中最常用的是什么?


1
通过查看Rails API,我发现模块中的复数名称比类中的更多(请参见命名空间,位于页面的下半部分)。然而,我对Rails的经验不足,无法确定何时使用其中之一。 - Sony Santos
5个回答

26

使用:

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的方式)。即查看Associations命名空间和所有类都继承自Associations :: Association类(即Associations :: SingularAssociation)的类。

14

对我而言,FooLib::Plugins 看起来像一个模块,被用作一个命名空间,保存了各种插件类。而 FooLib::Plugin 则看起来像是 FooLib 插件的超类。

FooLib::Plugins::Bar 中,Bar 明显看起来像一个插件的名称。但是在 FooLib::Plugin::Bar 中,我会怀疑 Bar 是一个被 Foo::Plugin 使用的辅助类还是一个插件的名称。


这是一个一般性问题,并不与我正在做的事情相关。我对这个话题有一些想法,想看看别人对此的看法。 - Szymon Jeż
FooLib::Plugins::Bar和FooLib::Plugin::Bar哪个更好?在我看来,第二个更像一个对象名称-> Bar是FooLib中的一个插件,第一个不太符合这种推理。 - Szymon Jeż
1
我个人使用FooLib::Plugin作为插件的超类,并将所有子类都保留在其中:class FooLib::Plugin::Bar < FooLib::Plugin。这种方式读起来很自然:BarFooLib中的一个Plugin。我认为在其自己的命名空间中包含特定子类的通用类非常有意义。我在我的所有代码中都使用这种嵌套系统。 - Matheus Moreira

4
假设Plugin是一个基类:
  • 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.


1
提出了许多好的观点,点赞。如果插件没有继承自一个共同的基类,那么FooLib::Plugins看起来非常有吸引力。 - Alex D

2

我赞同@jtrim提出的方法。

鉴于该模块(即插件)仅用于命名空间,我通常会覆盖模块中的new方法:

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(...)

1

一般来说,我倾向于采取的方法是:

module Foo
  module Plugin
    class Base; end
  end
end

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

Base类是插件的约定,它在RubyOnRails代码库以及许多其他地方都可以找到。(例如ActiveRecord::BaseActionController::Base等)

我不同意@Matheus Moreira的方法,其中Foo::Plugin既用作基类,也用作插件的命名空间。

唯一的功能原因是这样做可能会违反惯例-在Ruby社区中,类作为命名空间的实例要比模块少得多。我真正看到类被用作另一个类的命名空间的唯一时间是当所述类的目的是私有于命名空间类并且不被外部使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接