From: "David A. Black" Date: 2004-11-24T00:19:52+09:00 Subject: Re: Generalizing and Organizing Code Hi -- On Tue, 23 Nov 2004, trans. (T. Onoma) wrote: > I am finding it difficult to properly generalize and organize my code. Perhaps > others can offer some advice. Here is a snip two related parts. I have about > five others like these: > > # section > def parse_section_set_tab? ; false ; end > def parse_section_set_tab ; tab ; end > def parse_section?( line, tab ) > true > end > def parse_section_skip? ; false ; end > def parse_section( block ) > text = block.collect{ |line| line.text }.join("\n") > md = /([=]+)[ ]*(.*?)[ ]*[=]+/.match( text ) > raise "Unexpeted match error" unless md > level = md[1].length > title = md[2] > dobj = ArtML::DOM::Section.new( level, title ) > > until level > @document_stack.last.level do > @document_stack.pop > end > @document_stack.last << dobj # add this section to its parent > @document_stack << dobj # and pop it on > end [...] > In the generalized code these are called using #send. Eg. > > if send("parse_#{state}?", line, tab) > send("parse_#{state}", block) > end > > As you can see, I am using a name prefix "trick" to encapsulate these. I > would like to encapsulate them better, but I have a couple of difficulties. > My first problem is the use of @document_stack which they all work on. The > second problem is that I'm not sure what the encapsulation would be --they > consist of both data and code (but not state), yet there is only ever one of > each, so they aren't classes. And yet they don't seem like objects either b/c > the code differs between each of them. Perhaps use a module? That only seems > to adjust the name trick (Paragraph::parse instead of paragraph_parse). Plus, > I then have to do 'class << self', which seems ugly to me. Nor does it seem > like that's how a "module" is meant to be used. I don't think I'd characterize module-wise organization as a name trick of the same kind as hanging things off a method name. Also, don't be squeamish about class << self -- the "<< obj" notation is really just an alternative to the "SomeConstant" notation, designed to work with anonymous classes. Unfortunately it has a reputation as tricky or 3vi1 or whatever, but it really isn't :-) > What is the proper way to handle this in a class-based OOPL? I can't claim definitiveness by any means, but here's a mock-up of one possibility (untested): class Document def Document.stack @stack ||= [] end module SectionLike def parse_set_tab? false end def parse?(line,tab) true end def parse_skip? false end def parse(block) # ... Document.stack.pop # or whatever end end # ... module Section extend SectionLike end end state = Document::Section if state.parse?(line, tab) state.parse(block) end (The separation of SectionLike and Section is in case you can use it to consolidate and cascade from one module to another and save some method definitions.) David -- David A. Black dblack@wobblini.net