Duck Typingは大規模プロジェクトでも大丈夫か?

整数として処理したければ、オブジェクトがto_iという振る舞いを持っていることを期待してなんでもとにかくto_iしてしまうのがDuck Typingなのかなと思いました。

Duck Typing? - 18 til i die (another phase)

なるほど、そうですね。
そういえば、Duck Typingでは「メソッド名がグローバル」になりますね…。ふと思ったのですが「大規模プロジェクトでメソッド名がコンフリクトしてDuck Typingが破綻する」という可能性はあるでしょうか? > 識者のみなさま。
# おお、スケーラビリティの話題じゃん。
想定解答:

  • (0) この問いかけ自体が無意味。なぜなら…(誰かがここを埋める)
  • (1) 大規模プロジェクトでもDuck Typingは破綻しない。なぜなら…(誰かがここを埋める)
  • (2) 大規模プロジェクトでDuck Typingは破綻する可能性はある。でも、その可能性はほかの型機構でも似たり寄ったり。
  • (3) その他。

追記:

「(1)大規模プロジェクトでもDuck Typingは破綻しない。なぜなら…」インスタンスにとって同名のメソッドは一つだけで、かつ実行時にはインスタンスが特定されるから。
かと思うんですが、問題取り違えてる?

満足せる豚。眠たげなポチ。:DuckTyping は破綻しない。。。よねぇ?

反応感謝。問いかけがあいまいですみません。ちょっと話は違っていて、ええとですね…。私がイメージしていたのは、あるコンテナにオブジェクトがどさどさ入っていて、eachで回して各オブジェクトのメソッドfooを呼ぶとします。そのとき、間違って別のセマンティクスのfooメソッドを持つオブジェクトをコンテナに入れちゃったら、そのfooメソッドは呼ばれちゃうなあ、という話です。
あ、もちろん「そんなことやるのがわるい」のは理解しています。でもたとえば、大規模プロジェクトで、異なる流儀のメソッドネーミングコンベンションを持つ複数のクラス群を一緒に使うようなシチュエーションで困ったことは起きないかな、と思ったのでした。困ったことが起きる具体例を挙げられなくてごめんなさい。でも、コンパクトで適切な例を出してもそれはいかにも不自然な例になってしまうのです。大規模プロジェクトという言い方で私がいいたいのはまさに、コンパクトに全貌をつかめないほどの状態になったときのことなので。
私自身は現在、上記の想定解答の(2)ではないだろうか、と想像しているのですが。
追記:
zep716さんからのコメント。

* 間違ったインスタンスが間違った動作をするという意味では問題ないんじゃないか。
* 本来間違っているタイミングで間違っているというのが判明しない可能性があるのは問題。』 (2007/06/13 00:19)

まさにまさに、私もそう思います。で、もう一つ気になることがあって、「間違ったインスタンスが間違った動作をする」ということがわかったときに「対策」があるかどうかなのです。あるコンテナにクラスAのオブジェクトとクラスBのオブジェクトが入るとして、Bのfooメソッドを別な名前にすげかえることができるかという話題。…aliasすればよいだけかも。
追記:
まちゅさんからの反応。

んー。(2)かなぁ。 個人的には大規模かどうかはあんまり関係ない気がしてきた。
Duck Typing を使う基準として、以下の「どちらか」が満たされていると考えてみる。

  • 処理対象となる変数の型がほぼ予測可能であること。例えば、元の例のように整数か文字列のどちらかといった具合。
  • 処理対象のオブジェクトが呼び出すメソッド名が広く使われているものであること。 to_i や to_arr のように。

変数の型が予測可能であれば、別のセマンティクスを持つオブジェクトが紛れ込む可能性は低い。また、広く使われている to_i や to_arr しか使わないのであれば、これまた別のセマンティクスを持つオブジェクトが紛れ込む可能性は低い。

Duck Typing - まちゅダイアリー(2007-06-12)

ふむふむ。まあ、そうですわね。ここに書かれている二点は、どちらも「プログラマの予測が効くかどうか」ということになりますよね。変数の型にせよ、メソッド名にせよ。で、予測が効くんだったら厳密なチェックは不要(必要なら実行時にチェックすればよいし)ということになると思います。その後にまちゅさんがプログラミングRuby言語編(第2版)の第23章から引用されていた件(Duck Typingはスタイルにすぎない)についても了解。
追記:
zorioさんからのコメント。

セマンティクスは同じですが、シグネチャが違って困ったことはありました。
railsのto_jsonを前提に機能拡張したpluginと、rubygemsjsonライブラリのto_jsonで、引数の個数に違いがありました。
子要素について再帰的にto_jsonメソッドを呼ぶ処理で、引数の個数が合わなくなって実行時エラーが発生しました。
その時は、pluginの方を使うのを止めて解決しました。

なるほど!うん、まさにこういう例を思いつきたかった(←何を言っていますか)。この場合は実行時エラーが起きることで「想定外のことが起きたと検出」できたし、pluginを使わないということで「対策」もできたわけですね。なるほど。
追記:
ZnZさんからのコメント。

規模に関係なく、メソッド名が一般的な単語なら破綻する可能性があるのではないかと思いました。
例えばsendはObject#sendだと期待していてもUDPSocket#sendなどで期待が外れてしまいます。sendの場合は__send__を使えばいいということになりますが。
似たようなメソッドとしてはidに対応する__id__とobject_idがあります。
他に衝突していそうな名前としてhashを思いついたのですが、URIの#以降の部分はfragmentになっていたので標準添付ライブラリの中では問題がなさそうでした。
最近だとpというメソッドの話がありました。

http://znz.s1.xrea.com/t/?date=20070612#p01

なるほど。上の「pというメソッド」というのは、すでにfamousな(well knownな)メソッドがあるときにその適用範囲を広げようとしたときの話のようですね。
追記:
考えてみたらPerlも同じか。
参考:

追記:
弾さんからの反応が。

なるほど。確かにPerlの場合には「コンテキスト」が加わりますね。それと「演算子」…ふうむ(眠いので後で考える)。
追記:

ダックタイピングは基本的に型を利用しない。
そうではなく、名前に基づく。
ダックタイピングに対する危惧は、名前による制約の有効性にあると仮定する。

L'eclat des jours(2007-06-30)

そうそう、それそれ。