スタック・オーバーフロー Asked on December 24, 2021
ruby で gem の開発をしているとします。 gem の開発なので、以下のようなスタンダードなフォルダ構成になっているとします。
% tree
.
├── Rakefile
├── bin
│ └── hola
├── hola.gemspec
├── lib
│ ├── hola
│ │ └── translator.rb
│ └── hola.rb
└── test
└── test_hola.rb
この際、 lib/hola.rb
から lib/hola/translator.rb
を require するときに、 require_relative
を利用しない理由などありますか?
とくに、 lib
内部の相対参照であるならば:
bin/
や test/
といった、プロジェクトとしてのフォルダ構成の変更の影響を受けることはあまり考えにくいことに加え、特に、 require_relative
することによって、 $LOAD_PATH
から意図しないスクリプトが読み込まれる危険を避けることができます。なので、基本的に require_relative
するべきだと思っています。
しかし一方で、 require_relative
を利用するライブラリや、 require_relative
の利用を推奨するような記事もあまり見掛けないので、自分の認識が違っているのかもりえない、と若干思ったりもします。
lib 内部など、同一LOAD_PATH
エントリー上の、自分のファイルをロードするにあたり、 require_relative
より require
を利用するべき理由などあったりなどしますでしょうか。
推測です。もしかしたら、他の理由かも知れません。
【理由その1】過去とのの互換性
require_relative
はRuby 1.8にはなく、Ruby 1.9からになります。該当のライブラリは1.8の頃からあり、一時は互換性を維持する必要があったライブラリにおいてはrequire_relative
が使えなかったという事情があります。その名残が今も残っているということです。また、その頃からの慣習として、原則require
のみを使うとなっているのかも知れません。
【理由その2】ライブラリの分割に備える
ライブラリが肥大化するなどすれば、どこかでライブラリの分割を検討するかも知れません。今はgemがあるので、gemで依存関係を書いておけば、一部を別のgemにしても、利用者側で何かを変更する必要もありません。互換性が維持しながらいつでも分割できるということです。
ここで問題になるのは、分離してしまったライブラリを読み込む部分です。もし、require_relative
で書いてしまっていたら、分離した部分はもはやそのgem内にはないので、エラーになってしまうでしょう。しかし、require
で書いてあって、ちゃんと依存したgemとして一緒にインストールされるのであれば、何も書き換えなくてもそのまま維持できます。
【理由その3】混ぜるな危険?
次のようなファイル構成を考えています。
./
├─lib/
│ └─sub.rb
├─sub.rb
└─test.rb
lib/sub.rb
puts 'lib/sub.rb'
sub.rb
puts 'sbu.rb'
test.rb
$: << File.join(__dir__, 'lib')
pp(require 'sub')
$: << File.join(__dir__)
pp(require_relative 'sub')
すでにlib/sub.rbは読み込まれているけど、relativeなのでsub.rbも読み込みます。これは特に問題ないように思えますが、そうではありません。もし、subというgemがすでにあって、それを読み込んだ後に、このライブラリのgemを読み込んだ場合、subという名前が被っています。
Rubyではファイル名とその中身のモジュール名やクラス名に強制的な規則はありませんが、通常は、推奨される名前付けを行っています。きっとどちらもSub
というモジュールかクラスを使っていることでしょう。そして、後に読み込まれたものによって前者は上書きされてしまいます。
そもそもモジュール名が被ること自体が問題ですので、あまり起きないかも知れません。それにrequire
に変えたら、逆にsubが読み込まれません。しかし、必要であったからrequire
したのに想定している物が読み込まれなかった場合、すぐにエラーになって気づくことができるでしょう。逆に、二重読み込みは、クラスなら一時的にうまく動くかも知れません。この場合、おかしな部分に対してエラーがすぐに起きないかもしれないことの方が問題です。なぜなら、気づかず、そのままリリースしてしまう恐れがあるからです。
ということで、require_reltaive
よりもrequire
だけを使っていった方が安全と思われます。ただ、ちゃんと名前空間を設定しておけば良いだけの話なので、それほど問題にならない可能性はあります。
Answered by raccy on December 24, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP