From: "Ara.T.Howard" Date: 2005-06-11T02:04:09+09:00 Subject: Re: duck-typing allows deeper polymorphism On Sat, 11 Jun 2005, Eric Mahurin wrote: > I don't really like this because: > > a. if you put this all over the place, it will significantly > degrade the code readability i strongly disagree here. in the case of short examples it is roughly equivalent def method argv pa = parseargs(argv){ required_argument 'a' optional_argument 'b' } end four lines def method a, b @a = a @b = b end two lines in the real world, in case where you might actually use parseages, it will shine TWENTY_SIX_KEWORDS_AT_ONCE = ('a' .. 'z').to_a def method argv pa = parsearges(argv){ required_argument 'foobar' keywords TWENTY_SIX_KEWORDS_AT_ONCE } end four lines now, if you write some loop that accepts all those kewords and loads them into a hash, openstruct, or something - and does not allow any other keywords, raising an ArgumentError if they are passed in, and then you duplicate this in all the methods that have that kind of logic, your code will be at least 10 time more verbose and obfusicated. essentially your comment is like saying help = (ARGV.include? '-h' or ARGV.include? '--help') is better/more readable than using optparse or getoplong. true if that's all you are doing (for instance in an example) - otherwise severely false. another example class CascadingStyleSheet class Element FontProperties = %w( font-family font-style font-variant font-weight font-size font ) ColorAndBackgroundProperties = %w( color background-color background-image background-repeat ... ... ) TextProperties = %w( ... ... ) BoxProperties = %w( ... ... ) ClassificationProperties = %w( ... ... ) CSSProperties = FontProperties + ColorAndBackgroundProperties + TextProperties + BoxProperties + ClassificationProperties attr 'selector' CSSProperties.each{|prop| attr prop} def initialize argv pa = parseargs(argv) { required_argument 'selector' keywords CSSProperties } self.selector = pa.selector CSSProperties.each{|prop| send prop, pa.prop} end def font_configure argv pa = parseargs(argv) { keywords FontProperties } ... end def box_configure pa = parseargs(argv) { keywords FontProperties } ... end end end it's this kind of code that spirals out of control with rampant DRY violations unless parseargs or a roll-your-own type argv parsing scheme is devised. > b. efficiency. You've added unnecessary checking. Why not let > the code raise the exception when it doesn't find the method? it's only added if you like. you don't have to use the duck-typing feature at all. besides, you approach is simply not valid for some cases (like nearly all the code i have around here) that do things like def method job, logger job.submit_job_to_queue_that_takes_three_to_five_days logger.info{ "job <#{ job.name }> finished with <#{ job.status }>" end now, if logger doesn't repsond to 'info' or job doesn't respond to 'name' and 'status' i'll blow up and not log a job that just took three days to run. bummer. > c. this may actually hinder some duck typing. In your example above, you > might make the method not always call both upcase and downcase (maybe > another boolean arg might control that). If the caller has enough control, > he could call the method with an object that just responds to one of them. > But parseargs unnecessarily prohibit that. again - it's __experimental__. these kinds of comments are great and precisely what this group is best at. > d. this only starts to capture the true duck-type. absolutely true. remember - it's an arg parsing module not a duck typing toolset. > To really describe it, you would need a more elaborate system which included > conditions when the arguments methods are called, description of the > requirements for the arguments to those methods, and what the duck-type > should be for return values of those methods. absolutely. there are several attempts on the RAA. > If you are able to implement that, then you really are going to make the > first problem even worse - code clutter. which is is why i chose to implement the simplest possible thing that could work and which covers the most common usage. at the very least it's something people might be able to build upon. > I think the description of the duck-type only belongs in the documentation. > I don't really see the advantage of putting it in the code. three days - banking transactions - remote method invocations... there are tons of scenarios where you need to either know your object can do such and such or try to make it if does not because each attempt is expensive in terms of disk, cpu, or network. it's luxurious to be able to write code that can just crash or be run again - but it's not always possible. >> hear hear! > > I guess I really should have said "use pure duck-typing everywhere". What I > mean by that is that methods shouldn't try to categorize or test the > capabilities of their arguments at all - don't use #respond_to?, #class, > etc. I used to use #respond_to? occassionally to make overloaded methods, > but am now convinced to go the pure duck-typing route - splitting overloaded > methods into multiple methods. again - this notion ignores all notion of temporality and cost. what if you were paying for a slot on a super-computer and wouldn't be able to get in again for three weeks and had a pending paper due? cheers. -a -- =============================================================================== | email :: ara [dot] t [dot] howard [at] noaa [dot] gov | phone :: 303.497.6469 | My religion is very simple. My religion is kindness. | --Tenzin Gyatso ===============================================================================