From: ara.t.howard@... Date: 2006-03-14T01:58:54+09:00 Subject: Re: abstract method in Ruby On Tue, 14 Mar 2006, ilan berci wrote: > A good portion of the GoF patterns rely on abstract methods (visitor, > abstract factory, template method, etc... ) which IMO only shine in > statically typed languages. It would be a shame to port all patterns (and > their required prerequisite: abstract methods) simply because they are > recognized in the static world and therefore would make a good fit in Ruby. > > The additional code needed for the ruby "abstract method" approach doesn't > make the code any more readable. The extra LoC actually slows down the > maintenance developer as she has to wade through more. i disagree strongly here. check out these two snippets that i am working on as we speak: def will_process_holding *a, &b raise NotImplementedError end def process_holding *a, &b raise NotImplementedError end def will_process_incoming(*a, &b) raise NotImplementedError end def process_incoming(*a, &b) raise NotImplementedError end vs abstract_method "will_process_holding" abstract_method "process_holding" abstract_method "will_process_incoming" abstract_method "process_incoming" it's for precisely these kinds of simple repetetive defs that we have 'attr', 'attr_accessor', 'attr_writer', and 'attr_reader'. think about how simple all these methods are to write - but people love the shorthand and the fact that rdoc can grok something meaningful from the metaprogramming is quite beneficial. sure - i could just go full on duck type - but good luck reading the 2000 line satellite image processing library that requires these four methods (and about 20 others) and trying to figure out which ones you need to implement. i nice compact listing like this surely helps out with that task doesn't it? here's another example from the standard lib tsort.rb ... # # Should be implemented by a extended class. # # #tsort_each_node is used to iterate for all nodes over a graph. # def tsort_each_node # :yields: node raise NotImplementedError.new end # # Should be implemented by a extended class. # # #tsort_each_child is used to iterate for child nodes of _node_. # def tsort_each_child(node) # :yields: child raise NotImplementedError.new end ... now, all this starts out at about line 230. this is a little deep is it not? i think it'd be great of rdoc understood and abstract_method hook just like it now supports the 'attr_XXX' hooks but, even without that, i'll take any hint i can get in code like this. ask yourself this: why did the author not just rely on duck-typing? why put these methods into the code at all? > In both solutions, an exception is thrown at runtime. The abstract method > approach will not allow the developer to catch it any earlier than the duck > typed default. unless, using one approach it takes an hour to figure out which methods to impliment and the other way it does not. consider an abstract method module Interface def extra_debugging_info e ... end end used like module Interface def foobar begin ... ... rescue ExceptionThatOccursOncePerMonth => e logger.warn{ extra_debugging_info e} end end end how anoying! you really should have written that method because your code now fails once per month. having an 'abstract_method' hook makes it so, even if the developer didn't comment their code, the code itself clearly showed the list of methods which should be implimented. trust me - i realize this is really a small gain over pure duck typing - but for the kinds of systems i'm writing, with 10,000 lines of ruby code, it's really quite helpful to have this sort of note to myself jump out in the code. that's why i've already written this: class Subscription ... def self::abstract_method m module_eval <<-definition def #{ m }(*a, &b) raise NotImplementedError end definition end ... > The exception proposed although slightly more readable will not in > practice add any value as Ruby developers are used to seeing the > exception and can narrow in on it expediently. agreed. the point is to not get the exception in the first place becausee the code was easier to understand how to hook into. > We should simply rejoice in the power of the mixin and realize that the > abstract specifier was devised prior to (and probably due to the absence > of) this incredibly powerfull construct. > > Lastly, the code becomes somewhat heavier which violates 2 key > principles of Ruby, one being the enjoyable to code principle, and the > other, least surprise principle. i really don't see why people would object to this idea. is it because people are only writing 100 line programs in ruby that might require one abstract method? i just don't understand how someone could think that diving into a complex inheritence hierarchy of 30 classes/modules requiring 20 or so abstract methods would NOT be made easier to grok if one could grep for /abstract_method/ in their editor to get a jump on things... my 2cts. kind regards. -a -- share your knowledge. it's a way to achieve immortality. - h.h. the 14th dali lama