From: Robert Klemme Date: 2004-10-14T21:29:39+09:00 Subject: Re: [Q] case based on object class "Markus" schrieb im Newsbeitrag news:1097680148.21256.85.camel@lapdog.reality.com... > > I see we have a quite different understanding of Duck Typing. IMHO with > > Duck Typing you just invoke a method and get bitten by the NoMethodError > > if it's not there. After all, what do you want to do if you discover that > > an instance does not support a method you expect it to? Through testing > > you ensure that the programm is well behaved. And I think, my > > understanding is close on what Dave and others say. > > Sure, if you had only one trick in your trick bag, you would just > call it and hope/expect it to work. That's the old "never test for an > error condition you don't know how to handle" rule. But if (as in the > case in question) you have multiple ways to do what you are trying to > do, some of them appropriate to some kinds of values, some appropriate > to others, you'd be nuts to just use the one and hope the other cases > never arose. > > Instead, you'd either 1) test for method signatures with > responds_to? or 2) implement the most common case and then rescue > NoMethodError and try the rare cases. The first is (IMHO) was cleaner > but I have seen cases where the second was used effectively. You are rigth: this seems to be an application of DT indeed. Although I have to admit, that I find the one trick situation a much more elegant application of DT than the multiple trick situation you describe. In those cases I prefer to switch to a type mapping based approach (although that has it's drawbacks in the light of singleton methods) like I demonstrated in another posting (basically, create a HashMap with classes as keys and lambdas as values). > > > > Now, while this is certainly a good idea for methods like to_s, to_i > > etc. > > > > it's a bad idea for functionality that is special to a part of your > > > > application. For example, if you had a class Foo and defined methods > > > > String#to_foo and Fixnum#to_foo etc. that might come in handy for a > > > > certain lib or module and a lot of libraries do this, class interfaces > > of > > > > standard classes get cluttered with methods totally specific to > > certain > > > > parts of the application. Also the likeliness of name clashes > > increases. > > > > > > This is another thing that is not quite duck typing. > > > > Clearly, as I was not talking about Duck Typing here but instead about > > certain design rationales independent of the typing model. > > So here is a language that gives you many workable ways to > accomplish a reasonable goal, but none of them are usable because they > every one of them violates some design principle or an other? Is it > possible that the set of design principles you are trying to employ is a > tad too restrictive? That may be, but please note that I didn't ban the "modify std class" approach for all cases. I said that this should be done with care for libs and larger apps. > If I want to write a polymorphic routine, but am not supposed to > test the class (since it provides no guarantee of behavour) or the > method signature, am not allowed to extend the core classes or sub class > them, how pray tell is it to be done? See above for an example. However, it's difficult to discuss this without a concrete example. > If the behavior is specific to the application (and added by the > application) it can as well be encapsulated within the application. To > a first approximation, this will be the case simply because the code > which extends them lives in the application. Just note, that I explicitely mentioned large applications and libraries. > If you aren't using it, it > isn't there. (Though looking back, I see that several of your points > seem to assume that this is not the case--e.g., the documentation > point.) If this is still worrisome, you can extend the interface only > of objects turned over to (or created by) your application. You can > even (if you really feel the need to go this far) remove them from any > objects you export. In that case, you can as well use another class internally (possibly by employing delegation). > As for the name space issues, you can, if you like, > package your extensions in a companion object, "under-write" them (with > method missing, use reflection to detect and report collisions before > they occur, etc.) Hm... I prefer a simpler solution. After all, what would you do it you had libA and libB which both add method String#foo and which both are able to detect the name clash and report it? You'll most likely get an exception and can't use libA and libB together. Of course, those libs could be written to automatically choose appropriate names, possibly even with dynamic generated prefix. But this likely becomes unmanageable fast. > All of these precautions can be neatly encapsulated themselves, so > you don't even need to mess with them while you're working on your code. > > It really does seem to me that this is a "rule" rooted more in the > limitations of other languages than abstract software design principles > and not a good match for ruby. I don't think so. Name clashes and building proper components with clean and consistent interfaces (i.e. interfaces that can be used by humans who have to understand them) are not restricted to particular programming languages and I think in fact are quite fundamental to software engineering. > There are too many good ways to deal > with the potential problems to write the whole technique off with an > "almost never" prohibition. As you might have guessed, I don't regard the ways to cope with name clashes of auxiliary methods in std classes as good as you do. :-) But that's a personal judgement and we're all free to differ here. > For my part, I am not saying it is _always_ bad to extend standard > classes, but (if done judiciously) it can be a very useful technique, I couldn't agree more. (Ooops, something wrong here? :-)) > and is no more dangerous than any other language feature of similar > power and generality. I leave that judgement for another thread. :-) Thanks for taking the time to go through all this! I'm sorry that I'm so stubborn about things that I'm convinced of. Kind regards robert