Ruby: 既存クラスの拡張モジュールの使用方法・適用タイミングはどうあるべきか

Ruby の URI クラスを拡張するモジュールを作成したのだけど、どのような使用方法だったら利用者が便利なのか、どのようなタイミングで拡張を適用するのがよいかの判断が付かず悩んでいたところ、須藤さんに助言を頂いたのでまとめてみました。 関連: Bug #9045: URIに含まれるエンコードされたID/パスワードがデコードされない https://bugs.ruby-lang.org/issues/9045
1
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

Ruby URI::Component というクラスを作って放置していたのだけど、いくつかバグっていたので直してみた。 http://t.co/lnkfmJNn5t https://t.co/u6SBJ2zGRd

2013-10-23 22:36:59
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

Ruby URI::Component だけど、これが正しいインターフェイス/実装かどうかはまったく自信がないので、ダメ出し受けたい…。とりあえず動く程度のもの。

2013-10-23 22:47:37
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

@ktou ruby-dev 方面の話でしたら、ダメ出しを期待…。どうくっつければ「正しい」のかよくわかってません…。

2013-10-23 22:51:31
@ktou

@satoh_fumiyasu module URI::Generic; include(URI::Component); endで使えるようにする方がよくある書き方な気がします。URI::Component.includedを定義すれば複数のモジュールをincludeできます。

2013-10-23 22:54:06
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

@ktou ありがとうございます! 教えてもらったキーワードで調べて考えてみます。もし、既存クラスを拡張するクラス(?)で手本/参考になりそうなお薦めのものをご存知でしたら教えてもらえると助かります。orz

2013-10-24 01:16:21
@ktou

@satoh_fumiyasu む。どのあたりがピンときませんでした?

2013-10-24 21:11:15
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

@ktou オブジェクト思考やら Ruby の流儀やらに疎いから、というのが一番の理由だったりします…。URI のような Ruby の基本的でメジャーなクラスを拡張する場合、どういった方法・タイミングでそれをやるのがいいのかよくわかってません。

2013-10-24 22:00:50
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

@ktou 例えば、require "uri/component" したら問答無用に URI を拡張してしまってもいいのかもしれませんが、そうするかどうかはユーザーに選択させたい(選択させるべき)なのかとか、どういった手順・方法で選択させたらいいのかとかがわかりません。

2013-10-24 22:03:44
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

@ktou Rails とかは require しただけでガンガン Ruby のクラスを拡張しているっぽい(実際は知らない)し、拡張しても互換性が保てているのであればいいのかどうか。 URI を拡張するのでなく、URI を継承する別クラスにすべきなのかどうか、とか…。

2013-10-24 22:07:09
ふみやす@シェルまおう(自称でない) @satoh_fumiyasu

@ktou 場合によりけりなんでしょうけど、判断材料が自分に不足している状況です。実装方法もあまり知らないし。

2013-10-24 22:08:19
@ktou

@satoh_fumiyasu 一番影響範囲を少なくするならインスタンス毎にextend(URI::Component)するのがRubyっぽいです。全インスタンスで有効にするならURI::Generic.include(URI::Component)するのがRubyっぽいです。

2013-10-24 22:23:19
@ktou

@satoh_fumiyasu 主張が強いライブラリーにしたいならrequireしたらすぐに有効にすればよいと思います。そこまで主張する気がないならrequireしてあkら明示的にincludeしてもらうのがよいと思います。

2013-10-24 22:24:54
@ktou

@satoh_fumiyasu URIを拡張する方法は既存のコードをほぼ変更なしでよいのがメリットで、別クラスの場合は既存のURIへの影響を与えずに済むのがメリットです。デメリットはお互いのメリットの逆です。これらとどのような気持ちでユーザーに使って欲しいかを天秤にかけます。

2013-10-24 22:28:25
@ktou

@satoh_fumiyasu 実装方法は https://t.co/Y0JUQmHwBI のextend(mod)をsend(:include, mod)にします。たとえば、base.send(:include, URI::Component::UserInfo)です。

2013-10-24 22:32:14