ころんころんの話をしよう。もしくはモジュールの名前空間について。

# ころんころん
`::`をどう発音するか自分は寡聞にして知らないのだが、筆者は心のなかで**ころんころん**と呼んでいる。
ちょっとかわいい音感だ。
そんな`ころんころん`に関して、ふだん意識せずに使っている人もいるだろうから、短いながらも`ころんころん`について解説したい。

# ころんころんとは何者か

`::`である。
ここで言うところの`::`は`ruby`の演算子の中で最も優先度の高いスコープ演算子である`ころんころん`だ。
`ruby`では演算子の組み合わせである自己代入演算子は再定義できない。
先刻ご承知の通り再定義に関してはおおらかな`ruby`ではあるが、`ころんころん`も`ころん`と`ころん`な自己代入演算子であるからにして、これもまったき再定義できない[^訳注1]。
つまるところ`ころんころん`は`ruby`という言語に組み込まれた制御構造である。

# ころんころんはどう使うのか
`::` を使うに、あまり卓越していない小輩の身ではあるのだけれど、一例の一つや二つ、二例三例と紹介するには吝かではない。

`::`はスコープ演算子であるのだが、これは名前空間を表すために利用される。
`ruby`ではモジュールもクラスも定義するとその名前を定数として持ったオブジェクトになる。ちなみに`Class`クラスは`Module`クラスのサブクラスである。

```ruby:モジュールの定義
$ Module.class
#=> Class
$ mod = Module.new #無名の module を作成
$ mod.class
#=> Module
```

モジュールを定義したとき、モジュール名と同じ定数にモジュールオブジェクトが代入される。これはクラスを定義した場合も同じである。
まあ上記の例では無名のモジュールクラスを作成しているので名前となるべき定数がない。無名の場合は最初に代入された定数がその名前になる。以下はその用例だが、筆者はこのコードの実際の使用例を見たことがない。

```ruby:無名モジュールの名付け
$ mod.name
#=> nil
$ hoge = mod
$ hoge.name
#=> nil
$ Hoge = mod
#=> Hoge
$ mod.name
#=> "Hoge"
```

話が逸れた。
とにかく`::`は、このモジュールやクラス内で定義された定数名を外部から参照するときに使用されるのだ。

```ruby:階層構造を持ったモジュールの宣言
module Foo
  module Bar; end
end
```

階層構造を持ったモジュールを参照してみよう。

```ruby:階層構造をもったモジュールの呼び出し
$ Foo
#=> Foo
$ Bar
# => NameError: uninitialized constant Bar
$ Foo::Bar
#=> Foo::Bar
```

ついに`::`の用例が出てきたぞ！
`Foo`の中で宣言された`Bar`はそのままでは参照できない。参照するためには正しく`Foo::Bar`とその階層構造通りに場所を示す必要がある。

では以下のように宣言すればどうなるであろうか。

```ruby:階層構造をもった？モジュールの宣言
module Moge
  module ::Piyo; end
end
```
おそらく読者諸兄は上掲の用例を見かけたことが有るであろう。`::`は左辺が省略できるのである。

```ruby:階層構造をもった？モジュールの呼び出し
$ Moge
#=> Moge
$ Piyo
# => Piyo
$ Moge::Piyo
#=> NameError: uninitialized constant Moge::Piyo
```

先ほどと、結果が変わった。`Piyo`は`Moge`の下で宣言したように見えて、`Moge`の配下にはいないのだ。そしてどうやら`Piyo`と`Moge`は同じ階層にいるようなのだ。

それでは`::`の省略された左辺とはなんであろうか、また、`::`を書かずともモジュールを宣言した場合にいったいどこの配下にいるのか。上掲の無名モジュールの用例に続けて、モジュールの定義された場所を参照するためにそのスーパークラスを確認してみよう。

```ruby:無名モジュールのスーパークラス
$ mod.class.superclass
#=> Object
```

**`Object`クラス！**

そう、`Object`クラスに定義されるのだ。`ころんころん`はたんに`ころんころん`ではなく、`オブジェクトころんころん`だったのだ。
ここに定義されている定数をトップレベルの定数と呼び、そしてこの場所こそが`::`がスコープ演算子として使用された場合の省略された左辺なのである。

# オブジェクトころんころんの名前空間の使い方

前項で`::`の省略された左辺で示す場所とは`Object`クラスの配下であると示した。
また、無名モジュールを宣言した際に`Object`クラスに定義されていることも示した。

ところで先日、筆者は異なる場所でトップレベルの配下に宣言されたモジュールで、複数形と名詞系が同じ語の名前空間が衝突したために、それを解決すべく新しく名前空間を切った。

そしてそれを解決する過程で多くの`オブジェクトころんころん`を目にした。もちろん筆者が過去に書いたものもある。本当は、今いる場所をきちんと考えれば不要なはずなのにだ。申し訳ない。

# オブジェクトころんころんはなるべくやめよう

`Object`クラスの名前空間はすぐに使いやすい定数を入れてしまうので、名前が衝突しやすい。

いつどんな予期せぬ参照が起きるかわからない繊細なものである。

正しく名前空間を切って、どこにも所属しない`オブジェクトころんころん`な定数の宣言を減らし、有限な資源を効率良く使うようにしていくことが肝要なのである[^訳注2]。そういった`ころんころん`といった語感を楽しむ余裕を持ったプログラミングを心がけたいものである。

重要なのは、汎用的な名前を`オブジェクトころんころん`の下でなるべく定義しないことなのだ。

# 付録：「ころんころんの話をしよう。」の翻訳にあたって

筆者がふだん扱うのは巨大な`Rails`プロジェクトであり、一つの大きなドメインに属するものである。
しかしその膨大なコード量、クラス数に比して頻出する用語は少ない。`ruby`に限らずあらゆる言語の名前空間と優先順位戦争もそうであるが、この有限なる「使いやすい名前」という大切な資源を有効活用することがいま求められている。

どこで宣言するか、どんなオブジェクトであって欲しいか、何を期待するのか、プログラミングをするにあたって名付けの悩みは計り知れない。その中であって、名前空間という重要な視点について、読みやすく、多くの用例を持って解説した本稿`「ころんころんの話をしよう。」`が一筋の光明になれば幸いである。

[^訳注1]: * 筆者が`ころんころん`言いたいだけである。
  https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html
[^訳注2]: * `ruby`ではモジュールが既に定義されているとき、さらに同じモジュール名でモジュール定義を書くとモジュールの定義の追加になる。`同じモジュール名での定義の追加`を参照のこと。
 * 上記のとおりなので同じ名前で定義してもメソッドや内部の定数名が被らなければ問題は起きにくい。クラスも同様。
     * であるが、結局解決順が問題になるのでだいたい`Rails`のせいと筆者は思っているようである。
     * **table_name_prefix**とか曲者だけどみんなどうやって対処しているんだろうか。
         * `app/models/`で定義されるので`lib/`と呼び出し順が異なり、名前空間が被ると……。

## 注意書き及び参考文献
* この文章は「るびぃりふぁれんすまにゅある未収録事無有無」（民明書房刊）に収録されたものを原文を尊重しつつ現代語訳し再掲したものです。
* 翻訳の不備については編集リクエストにて対応します。
* 参照した web ページ
 * https://docs.ruby-lang.org/ja/latest/class/Module.html#S_NEW
 * https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#class
 * https://docs.ruby-lang.org/ja/latest/doc/spec=2fdef.html#module

```ruby:同じモジュール名での定義の追加
$ module Hoge
$   module Fuga;end
$ end
$
$ module Hoge
$   module Moga;end
$ end
$ Hoge.constants
#=> [:Fuga, :Moga]
```