From: Gunnar Andersson Date: 2002-02-15T01:48:43+09:00 Subject: Re: qualms about respond_to? idiom > Hugh Sasse writes: > On Thu, 14 Feb 2002, Dave Thomas wrote: > > A polymorphic way of doing this is to move responsibility > down to the > > stream elements. Say each had a method handle_stack. Then your main > > code could simply call handle_stack on _all_ tags: > > > > e.handle_stack(context) > So is this an example of "Tell, Don't Ask", or is that more about an > object's internal state? It does overcome this > problem, but it also means all the objects have to know how > to handle a > stack. Doesn't that lead to "unnecessary" coupling between objects? Well you have type-dependent behavior so you really only have those choices, I'd say. 1. Either you switch on the type, which is what the original was doing, basically. 2. Or you use the polymorphic approach and make use of dynamic dispatch. Looking at Dave's example, using names like "stack" and "push" works because it is unlikely you'd want to handle your XML tags in a queue. It is clear a stack is the way to go and probably not much to worry about. But in similar cases, if you don't want to pass out the stack, there are other ways, like passing self, the tag calls back on that, and your tag-juggling-object delegates the "push" to the internal stack. (or "store" in the example below) You've coupled the tags and their handler (this is inevitable), but at least not thrown a Stack and it's specific push/pop methods into the mix. class Handler ... foo-juggling-code ... foo.maybe_store_yourself(self) ... # This is called back from the Foos def store(item) # The fact that we use a stack is encapsulated... @stack.push(item) end end # One type does: def maybe_store_yourself(handler) handler.store(self) end # Another type does nothing def maybe_store_yourself(handler) end Adds coupling? You can look at _any_ piece of code and find at least some dependencies. You either add coupling or you add layers of indirection and complexity. At some point you realize that parts of programs are always coupled together to some extent - I mean you can delegate and delegate but at some point you have to actually "solve the original problem" How would you ever write any program without it? It should be ok that objects know about eachother, especially when that relationship is temporary, i.e. it is very common in OO designs to pass a reference to yourself and let the other object call back on it. The Visitor pattern comes to mind. The code that calls back doesn't rely on the specific class of the handler, which is good, or it's internal representation. It needs to know that the callback method exists, sure. Such "coupling" always exists, how would you ever build a program without it? Sometimes you (not *YOU* but all of us, well, maybe not the gurus but anyway... ;-) have a tendency to over-analyze these things because we look at our dogmatic rules and see that either way we seem to break at least one of them. In my experience, after thinking "enough", you try one thing and if that doesn't really work in the long run, it will show (smell) and you refactor. So basically you have those two choices. Should you choose to switch on type, I would prefer doing it in a more explicit way. respond_to? is most likely just a concealed way of switching on type, albeit somewhat more flexible than switching on the object's Class. In some cases (a limited use of) respond_to? makes sense, in others not. I try not to be TOO dogmatic about OO rules like not switching on types. We need to realize some problems are inherently procedural, even when writing an OO program. A lot of times, the OO polymorphic approach is more flexible to future changes but it is often more heavyweight too, and for a simple problem actually more difficult to follow. It's not always the simplest thing that could possible work. And consider the success of functional programming in some fields. A lot of functions are polymorphic, but you also see quite some pattern-matching (=switch on type, more or less) to decide what to actually do. What's one reason to love the Ruby community? Because of the smart people in it! Some of the discussions here are great! I sure learn a lot. Cheers /Gunnar __________________________________________________ Do You Yahoo!? Send FREE Valentine eCards with Yahoo! Greetings! http://greetings.yahoo.com