経緯
とある機能の改修で連携先のシステムが公式に提供しているgemを使わねばならず、そのgemを追加したところ変なところでテストが落ちるようになりました🔥
そのgemを追加したことが原因であることは明白だったのですが、どこが悪さをしているかの全くわからない事態に...
実装のマズかった部分
gem内の特定の処理で System.new(uri.host)
といったような形でinitializeされるクラス名が lib
配下にアプリケーション側で定義しているクラス名とたまたま被っており、gem内部の処理がそちらのクラスを参照してしまい、引数の異なるinitiazlieを呼び出して例外が発生していたのがCIが落ちていた原因でした📝
gemとアプリ内のコード例(うまいこと抽象化出来てないが...)
gems/hoge-fuga-gem-1.0.0/lib/core/hoge_fuga.rb
class HogeFuga def initialize(options = nil) super # 何かの処理 end def each(uri = nil) system = System.new(uri.host) end # 何かの処理 end
lib/system.rb
class System # 何かの処理 end
今回じぶんが経験したパターンで言うと System.new(uri.host)
の部分で lib
直下の同名クラスを参照してしまい、 initialize
の引数の数が異なっていることが原因でエラーになってました...
所感
今回の件で、たとえば System
などの一般名詞で名前空間を切らずにクラスを定義してしまうと意図せずにライブラリのコードとぶつかってしまう場合があることを知りました 🙈
広い名前付けは、それが何でも含んでしまうことから責務の境界が曖昧になってしまうなどの弊害は日頃から認識していたものの、 こんな形で表出するとは全く思わず...
改めてコードレビューや自身の実装でもこういった部分に留意したいと思った次第です。