16988


Rubyのモジュールですが、`名前空間`の提供と`Mix-in`の提供との2つの機能があるようです。  
  

# 書かれたモジュールの判断

人のソースを読んでいてモジュールが名前の衝突を避けるためといったような`名前空間`のために使っているのか、はたまたクラスの機能を拡張するための`Mix-
in`のために使っているのか雰囲気でわかりますが、なにか明確な指標でわかったりするものなのでしょうか？  
（どこからもincludeされていないかどうかプロジェクト全体で`grep`して、なければ`名前空間`として使用という判断でしょうか？）

# 自分の書いたモジュールが今後どうなるのか

自分が書いたモジュールの場合、自分は`名前空間`のために書いたつもりだったのに、`Mix-
in`としていつまにか使われていたというような事態が起こったりはしないものなのでしょうか？ またその逆で、`Mix-
in`のつもりで書いたのに`名前空間`として使われることとなったということもありえそうなのですが、そういったことにはならいのでしょうか。（そうするとコードの秩序が保てなくなるような気がします。コミニケーションによって起こらないようにするのでしょうか）


CC BY-SA 3.0
2015-09-26T13:47:27.193
16960
2015-09-27T05:14:39.793
2015-09-26T13:53:06.743
9008
9008
question
ruby
Rubyのモジュールを名前空間で使っているのかMix-inで使っているのか


javaのようにアノテーションを使って実装者の意図を示すといったことができないrubyでは、モジュールが名前空間としてしか意味を持たないのか、mix-
inとしての意味として理解させるのかは、チームの規約次第、あるいはコードによって判断、ということになるんじゃないかと思います。


CC BY-SA 3.0
2015-09-26T19:05:53.060
16977
2015-09-26T19:05:53.060
9403
16960
answer


Rubyのモジュールには確かにMixinと名前空間の両方の役割があります。  
ゆえに、「意図しない形で使われる可能性があるんじゃないか？」という心配が出てくるのも理解できます。

最初に確認したいのは、shingoさんは実際に困ったことがあるのか、それとも「この先困ることが出てくるのではないか？」と心配しているのか、どちらなのか？ということです。  
もし前者であれば、実際に困ったときのコードを見せてもらった方が議論しやすいです。

が、僕はなんとなく後者である気がしています。  
なので、ここから先は「この先困るかも？」という心配に対する答えを記述します。

そもそも、何も考えずにモジュールをデタラメにMixinしようとする人は滅多にいないと思います。  
普通であれば、

  1. xxxという機能を実現したい
  2. yyyというモジュールにその機能がある
  3. だからyyyをMixinしよう（＝incudeまたはextendしよう）

というふうに考えるはずです。  
こういう思考回路で実装する限り、「yyyはMixinのためのモジュールである」と確信をもってMixinするはずです。  
「名前空間のためのモジュールを間違ってMixinしてしまった」というのであれば、プログラマの理解力が極端に低いか、モジュールの設計があまりにもわかりづらいかのどちらかになると思います。

なので、勘違いは滅多に起きないだろう、というのが回答になるのですが、Mixinのためのモジュールなのか、名前空間のためのモジュールなのかをあえて客観的に判断したい、ということであれば、だいたい次のようなルールになると思います。

### Mixinのためのモジュールであればインスタンスメソッドが定義されている

つまりこういう実装になっている、ということです。

[code]

    module Foo
      def bar
        "bar!"
      end
    end
    
[/code]

こうなっていればMixinするためのモジュールだと考えて間違いないでしょう。

[code]

    class Hoge
      include Foo
    end
    
    hoge = Hoge.new
    hoge.bar # => "bar!"
    
[/code]

### 名前空間のためのモジュールであれば同じ名前のディレクトリがある

つまり、次のようなディレクトリ構成になっている（Fooというモジュールに対応するfooというディレクトリがある）、ということです。

[code]

    # lib/foo/bar.rb
    module Foo
      module Bar
        def baz
          "baz!"
        end
      end
    end
    
    class Hoge
      include Foo::Bar
    end
    
    hoge = Hoge.new
    hoge.baz # => "baz!"
    
[/code]

ちなみに、Fooが名前空間とMixinの両方の役割になっている場合もあります。

[code]

    # lib/foo.rb
    module Foo
      # ...
    end
    
    # lib/foo/bar.rb
    module Foo
      module Bar
        # ...
      end
    end
    
    class Hoge
      include Foo
    end
    
[/code]

このあたりは自分であれこれ悩むよりも、著名なオープンソースライブラリのモジュール設計を研究してみるのが一番勉強になると思います。

例： [rails/actionview/lib/action_view/helpers at master ·
rails/rails](https://github.com/rails/rails/tree/master/actionview/lib/action_view/helpers)

「いや、こういうケースだと勘違いは十分にありえそうだ」というパターンがあれば、質問に追記してもらえると助かります。

以上、ご参考までに。


CC BY-SA 3.0
2015-09-27T05:14:39.793
16988
2015-09-27T05:14:39.793
85
16960
answer