From: David Alan Black Date: 2002-01-14T08:45:45+09:00 Subject: Re: Small Methods - a ramble Hello -- On Mon, 14 Jan 2002, Ron Jeffries wrote: > I noticed in some code that Chet and I were writing that, as > Smalltalkers, we tend to write really tiny methods. Here's a patch > of code to show what I mean. Pay no attention to what it does, just > look at how it looks. > def filesUnderManagement > names = (Dir.entries(@directoryName).select { | each | ! (/.bak/ =~ each) }).sort > names.reject { |each| FileTest.directory?(sourceName(each)) } > end Are you sure you want to use 'each' as the iterator variable name? Memories of naming methods 'test' rear their ugly heads.... [ [1,2], [3,4] ].each {|each| each.each {|each| p each}} Well, it works :-) I find it hard to parse visually, though, and slightly illogical (given the existing role and flavor of the word 'each' in iterator-land). > def archiveFiles > Dir.entries(@directoryName + '/archive').reject { | each | /^\./ =~ each }.sort.reverse > end > > def backup > timeString = Time.now.strftime("%Y%m%d%H%M%S") > filesUnderManagement.each { | each | backupFile(each, timeString)} > end One thing I find hard to judge, when deciding how small to make my methods, is where to stop the abstraction. And maybe there's no real hard-and-fast rule. But anyway -- for example, in #backup, above, you could have done: timeString = Time.now.strftime(timeFormatSpecifier) ... def timeFormatSpecifier "%Y%m%d%H%M%S" end which would have been more encapsulated but perhaps *too* encapsulated and actually less clear. I guess one thing is whether one has hit the end of the line in terms of reuse. In this case, for example, that would mean that it's known for sure that #backup is the only method that's going to need that specifier. In fact, sometimes I find myself overabstracting, and then realizing that all I've done is displace some nitty-gritty thing (like a time format string) onto another method for the sake of abstraction. At that point, inlining it in the method one level of abstraction up (as with the string in your #backup method) is often clearer. [...] > At first when you use Smalltalk, it seems choppy as you have to keep > clicking around to see what's going on, and in a text window you can > sort of do that with your eyes. But take a look at these methods > from the program we're writing. I'm not claiming that the names are > perfect yet -- this is a work in progress. But read my pretend > throughts below and see if you can get what I /like/ about tiny > methods: > > def restore (timeString) > restoreFiles(filesToRestore(timeString)) > end > > hmm, OK, he does a restore by restoring all the files to restore, > based on the time string. I wonder how he restores a file ... > > def restoreFiles(fileList) > fileList.each { | each | restoreFile(each) } > end > > OK, he goes through them all and restores each one ... how does he do that? > > def restoreFile(fileName) (etc.) It's interesting -- you're looking at code as a narrative form, and not narrative in the sense of being executed in a certain order, but more in the sense of containing a story, possibly oblique to the order of execution. (I don't know that I'm adding anything to what you're saying -- I just always find unusual or unexpected narrative forms intriguing.) > Now most of us who read larger methods are used to doing the > reverse. We look at a big blob of code and figure out little chunks > of it. Then maybe we comment the code or make a note or just leave > the figuring out to the next person. > > Tiny methods -- when you get used to them -- are IME /much/ easier > to write and to work with. > > Editor-based languages like Ruby, Java, C++, encourage longer > methods because we have to search with our eyes to figure things > out. > > What does this mean? I don't know. I think it might mean that a > browser for Ruby or Java or C++ would be really good. Visual Age for > Java is really wonderful in the hands of people who learn to work in > the browser mode. I'd certainly expect such a thing for Ruby to be very useful, Smalltalk and code-browser know-nothing though I be. David -- David Alan Black home: dblack@candle.superlink.net work: blackdav@shu.edu Web: http://pirate.shu.edu/~blackdav