<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Ruby Best Practices</title><link>http://blog.rubybestpractices.com/</link><description>Increase your productivity -- Write Better Code</description><language>en-us</language><item><title>Practicing Ruby, The Newsletter</title><description>&lt;p&gt;&lt;i&gt;Welcome, Hacker News folks.  If you find the following project worthwhile, I&amp;#8217;d really appreciate an &lt;a href="http://news.ycombinator.com/item?id=1883108"&gt;up vote&lt;/a&gt; so that I can reach a broader audience.  Please read a bit about &lt;a href="http://blog.rubybestpractices.com/posts/gregory/025-ruby-mendicant-university.html"&gt;Ruby Mendicant University&lt;/a&gt; to see what cause this goes to support.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Since the first Ruby Mendicant University session began in August, I&amp;#8217;ve interacted with and mentored roughly 50 students.  The fascinating thing is that despite the wide gradient in skill levels we see at &lt;span class="caps"&gt;RMU&lt;/span&gt;, there are many common obstacles that trip up the majority of students attending our sessions.&lt;/p&gt;
&lt;p&gt;As it turns out, there is a surprisingly wide gap between a foundational book such as David A. Black&amp;#8217;s &lt;a href="http://www.manning.com/black2/"&gt;Well Grounded Rubyist&lt;/a&gt; which is suitable for beginners and my own &lt;a href="http://rubybestpractices.com/"&gt;Ruby Best Practices&lt;/a&gt; book which is designed to help intermediate developers.  At least as far as I&amp;#8217;ve seen, this isn&amp;#8217;t a hole that has been filled in by other resources that aren&amp;#8217;t some kind of interactive training program.  My new project, the &lt;a href="http://letter.ly/practicing-ruby"&gt;Practicing Ruby newsletter&lt;/a&gt; is designed to fill in that gap.&lt;/p&gt;
&lt;p&gt;Each week, I&amp;#8217;ll choose a topic based on things I&amp;#8217;ve noticed tend to trip up intermediate Ruby developers.  Every Tuesday, some background information on the topic along with some discussion points and open questions will be sent out to the readers.  Some time will be given for open discussion on a mailing list made available to subscribers, and then a follow up article will delivered on Thursday which provides some answers to the given questions as well as some practical examples of whatever topic we are studying that week.&lt;/p&gt;
&lt;p&gt;My hope is that this will be a great use of one of the byproducts of running &lt;span class="caps"&gt;RMU&lt;/span&gt;.  Not everyone has the available free time and motivation to spend several weeks in the intense training programs we offer at &lt;span class="caps"&gt;RMU&lt;/span&gt;, and space in our sessions is severely limited.  But a wide range of Ruby developers can benefit by exploring the topics we&amp;#8217;re running into at &lt;span class="caps"&gt;RMU&lt;/span&gt;, especially if we can break them down into something that takes an hour or less a week to study.  If you&amp;#8217;re an intermediate Ruby developer who would rather do your learning in bite-size chunks, this newsletter is for you.&lt;/p&gt;
&lt;p&gt;If this sounds interesting to you, please &lt;a href="http://letter.ly/practicing-ruby"&gt;sign up for Practicing Ruby&lt;/a&gt; now.  The cost is $5 a month, but you can feel good in knowing that the better off this newsletter does, the easier it will be for me to continue dedicating time to the completely free Ruby Mendicant University.  I currently spend more than 30 hours a week on &lt;span class="caps"&gt;RMU&lt;/span&gt;, with about half of that going to student interaction, and would happily dedicate all my time to it if it were possible.  This newsletter might be a way for me to get a little extra revenue to make up for my lost consulting hours, at least until we have a proper non-profit organization in place for supporting &lt;span class="caps"&gt;RMU&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;While I do not have any sample newsletters ready just yet, you can download the whole &lt;a href="http://rubybestpractices.com"&gt;&lt;span class="caps"&gt;RBP&lt;/span&gt; book&lt;/a&gt; for free to get a sense of my writing style.  I can also tell you that the first topic we&amp;#8217;ll be covering will be an exploration of Ruby&amp;#8217;s method lookup path followed up by some practical examples of how to put those ideas into action.  This will help answer some questions about when to use inheritance, mixins, and even per-object behavior.&lt;/p&gt;
&lt;p&gt;Feel free to post any questions or suggestions in the comments section below.  I&amp;#8217;m really excited about this project and would be happy to hear your thoughts!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Mon, 08 Nov 2010 16:43:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/028-practicing-ruby.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/028-practicing-ruby.html</guid></item><item><title>The Ruby Mendicant University Core Skills Course</title><description>&lt;p&gt;&lt;strong&gt;For the tl;dr crowd, there are &lt;a href="#student-projects"&gt;sixteen student projects&lt;/a&gt; and &lt;a href="#exercises"&gt;four sample exercises&lt;/a&gt; from the course towards the end of this document.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;The Original Idea&lt;/h3&gt;
&lt;p&gt;Back when I wrote about the &lt;a href="http://blog.rubybestpractices.com/posts/gregory/025-ruby-mendicant-university.html"&gt;Ruby Mendicant University idea&lt;/a&gt; in June, I didn&amp;#8217;t have a particular plan for it.  I knew I wanted to teach a free online course of some kind, drawing from my life experiences as much as possible to form the learning materials.  Being mentored by &lt;a href="https://twitter.com/#!/jeg2"&gt;James Gray&lt;/a&gt; for the first several years of my career as a software developer really taught me the importance of having a great teacher to guide me while I worked, so I knew that mentorship would be a key part of the program.  The idea behind &lt;span class="caps"&gt;RMU&lt;/span&gt; was mainly to scale that experience from a 1-1 relationship to one that could reach many students.&lt;/p&gt;
&lt;p&gt;While it has been a wild ride so far, the results have been simply amazing.  I&amp;#8217;ll spend the next few days trying to give the Ruby community a sense of what&amp;#8217;s going on within &lt;span class="caps"&gt;RMU&lt;/span&gt;, so they can see the awesomeness of the program for themselves.  I&amp;#8217;ve decided to start by describing the core skills course, which is something every student attending &lt;span class="caps"&gt;RMU&lt;/span&gt; needs to tackle if they wish to continue on in the program.&lt;/p&gt;
&lt;h3&gt;The &lt;span class="caps"&gt;RMU&lt;/span&gt; Core Skills Course&lt;/h3&gt;
&lt;p&gt;In order to become a permanent member of the &lt;span class="caps"&gt;RMU&lt;/span&gt; community and move on to take additional courses, each student must pass an entrance exam and then go on to successfully complete their core skills course.  The entrance exam is mainly used for ensuring that the people joining the program are diligent workers who have sufficient background knowledge to do well in our core skills course.  The core skills course itself though, is something I think is something genuinely unique that you can&amp;#8217;t find anywhere outside of &lt;span class="caps"&gt;RMU&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Each core course starts with roughly 15 students submitting a proposal for a personal project to work on during their session.  This can be anything Ruby related, but typically involves the student building an open source application or library that scratches a particular itch of theirs.  This is the first learning opportunity of the course, as it filters out those who can&amp;#8217;t think of anything to work on.  There isn&amp;#8217;t a list of suggested projects to pick from, students need to come up with an idea themselves.  As each student decides what they want to work on, I work with them to figure out what they can reasonably produce in three weeks which would be useful and show measurable progress.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve found that without some tangible goal to focus on, improving your skills is an abstract, disconnected experience that is only enjoyable until the going gets tough and the novelty wears off.  No &lt;span class="caps"&gt;RMU&lt;/span&gt; student can even begin their session with this mindset, which I think is a key part of why the course can inspire such rapid growth.  But many folks are only likely to volunteer to work on problems which they find sexy on the surface, which isn&amp;#8217;t a good way to master a craft.  That&amp;#8217;s where assigned work comes in.&lt;/p&gt;
&lt;p&gt;While the exercises used in each session are different, I try to include one for each of the following topics:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Integrating with other systems (typically web services)&lt;/li&gt;
	&lt;li&gt;Modeling non-trivial business logic (often a game of some sort)&lt;/li&gt;
	&lt;li&gt;Community Service (contributions to &lt;span class="caps"&gt;RMU&lt;/span&gt; and the community at large)&lt;/li&gt;
	&lt;li&gt;Classical Computer Science / Engineering Knowledge (Patterns, Algorithms, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No matter what the topic is, the end result of the exercises is some sort of real application.  Even when we&amp;#8217;re studying higher level concepts, we don&amp;#8217;t stray too far from things that you could actually use in day to day life.  The varied nature of the assignments insures that all students are challenged in one way or another, regardless of their relative level of experience entering the course.&lt;/p&gt;
&lt;p&gt;While earlier core skills sessions we ran involved some exercises that needed to be done in isolation, the current course is set up in such a way that the exercises can be actively discussed between students without it spoiling the learning experience.  This in itself is invaluable, because most of the lessons learned in &lt;span class="caps"&gt;RMU&lt;/span&gt; are not actually pre-determined by the course materials, but instead, emerge through conversations about the problems.&lt;/p&gt;
&lt;p&gt;Rather than doing lectures, I maintain extensive office hours on &lt;span class="caps"&gt;IRC&lt;/span&gt; and the session mailing list, spending 15-20 hours per week answering student questions and discusses topics as they arise through the session.  This has been extremely time consuming, so I&amp;#8217;ve started to enlist the help of some of our alumni in mentoring session students.  But this is also the area of &lt;span class="caps"&gt;RMU&lt;/span&gt; that I find most special and unique.  I spend three days a week in constant conversation with my students, which means that I learn an incredible amount about each of them and can tailor the program to meet their individual needs and interests.&lt;/p&gt;
&lt;p&gt;Students can submit their assigned work or individual projects for review at any point in time during the three week program.  I approve submissions which don&amp;#8217;t show any obvious gaps in understanding the key points, the others, I provide feedback on and ask them to resubmit when they&amp;#8217;ve made revisions.  Students who make good progress at the end of the course by getting at least three of four assigned projects approved, and by doing good work on their individual project, gain alumni status and are invited to stay involved with &lt;span class="caps"&gt;RMU&lt;/span&gt; for the long haul.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll have to save the alumni responsibilities and benefits for another post.  But it&amp;#8217;s worth noting that so far, 16 of 25 students who have completed a core skills course gained alumni status.  While I&amp;#8217;d like to see that number higher, several of the students who didn&amp;#8217;t successfully complete their session are working with me to find a way to get their status later.  But the great thing is, 100% of our alumni intend to take more courses at &lt;span class="caps"&gt;RMU&lt;/span&gt; in the near future!&lt;/p&gt;
&lt;h3&gt;&lt;a name="student-projects"&gt;Student Projects from August / September&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Below are the sixteen individual projects of our current &lt;span class="caps"&gt;RMU&lt;/span&gt; alumni from our August and September sessions. While many of them are still in their early stages of development, several are quite useful already.  Keep in mind, most of these projects were built in just three weeks!&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com/RubyMoney/google_currency"&gt;google_currency&lt;/a&gt; (Shane Emmons): Ruby Money::Bank interface for the Google Currency exchange data&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/fwoeck/cashmate"&gt;cashmate&lt;/a&gt; (Frank W&#246;ckener): Business proposal management system&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/chipiga/forum_engine"&gt;forum_engine&lt;/a&gt; (Pavel Chipiga): Forum engine built on Rails 3&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/justinramel/groupy"&gt;groupy&lt;/a&gt; (Justin Ramel) ActiveDirectory Group Management Utility&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/soulim/prism"&gt;prism&lt;/a&gt; (Alex Soulim): WebSocket Server for chat&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/ruanwz/gstore"&gt;gstore&lt;/a&gt; (David Ruan): Ruby client library for the Google Storage &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://groups.google.com/group/prawn-ruby/browse_thread/thread/e2c3ac97065db4ca/2fd7a9b4ba60be6d?lnk=gst&amp;amp;q=examples#2fd7a9b4ba60be6d"&gt;Prawn Reference Guide / Examples Refactoring&lt;/a&gt; (Felipe Doria) Soon to be merged upstream&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/lucasefe/themes_for_rails"&gt;themes_for_rails&lt;/a&gt; (Lucas Florio): Theme support for Rails 3&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/morganp/unwatched"&gt;unwatched&lt;/a&gt; (Morgan Prior): Utility for tracking watched media files&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/wpiekutowski/montgomery"&gt;montogomery&lt;/a&gt; (Wojciech Piekutowski): A lightweight object mapper for MongoDB&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/madebydna/vegtastic"&gt;vegtastic&lt;/a&gt; (Andrea Singh): Collaborative vegan/vegetarian recipe collection app&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/jazzu/resourceful"&gt;resourceful&lt;/a&gt; (Jaakko Vallo): Automated work schedule management.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/ignacy/qinfo"&gt;qinfo&lt;/a&gt; (Ignacy Moryc): &lt;span class="caps"&gt;SQL&lt;/span&gt; Query optimization tool&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/tehviking/minivid"&gt;minivid&lt;/a&gt; (Brandon Hays): 60 second video uploading and sharing service&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/afcapel/rallot"&gt;rallot&lt;/a&gt; (Alberto Fern&#225;ndez-Capel): Secure electronic voting system backend&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/ericgj/rmu-alarmclock"&gt;rmu-alarmclock&lt;/a&gt; (Eric Gjertsen): Client/server based reminder system&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While I gave students guidance on their projects throughout the course, my focus was on education, and not on quality assurance, so please do not consider this listing of projects a personal endorsement that they&amp;#8217;ll be suitable for a particular purpose.&lt;/p&gt;
&lt;h3&gt;&lt;a name="exercises"&gt;Released problems from August / September sessions&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re curious about the sorts of problems students worked on during their sessions, you can check out the few that have been released so far.  Eventually all of our materials will be released, and collected nicely in an easy to find location.  For now, feel free to re-distribute these under the terms of the &lt;span class="caps"&gt;GNU&lt;/span&gt; Free Documentation License.&lt;/p&gt;
&lt;p&gt;You can try these on your own, or look through the network graphs to see some student submissions that have been made public.&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://github.com/rmu/s0-e1"&gt;s0-e1&lt;/a&gt; : Prototyping the board game Dominion&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/rmu/s0-e2"&gt;s0-e2&lt;/a&gt; : &lt;span class="caps"&gt;IRC&lt;/span&gt; bot / Web Service mashup&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/rmu/s1-e1"&gt;s1-e1&lt;/a&gt; : Twitter bot / Web Service mashup&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/rmu/s1-e2"&gt;s1-e2&lt;/a&gt; : Prototyping a Github themed achievement system&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lots of other exercises will be released soon, so stay tuned.&lt;/p&gt;
&lt;h3&gt;Please help us with funding!&lt;/h3&gt;
&lt;p&gt;&lt;a href='http://www.pledgie.com/campaigns/13580'&gt;&lt;img alt='Click here to lend your support to: Help Ruby Mendicant University "Grow up" and make a donation at www.pledgie.com !' src='http://www.pledgie.com/campaigns/13580.png?skin_name=chrome' border='0' /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you might imagine based on this article, running &lt;span class="caps"&gt;RMU&lt;/span&gt; is an incredibly labor intensive task.  What started as something I thought I&amp;#8217;d do as a side project after the initial setup work has gone in the opposite direction.  I now spend 30-35 hours per week on &lt;span class="caps"&gt;RMU&lt;/span&gt; related responsibilities, about half of that time is spent interacting with students.  My coworker Jordan Byron spends at least two days a week working on &lt;span class="caps"&gt;RMU&lt;/span&gt;, building out our web application for course management, and my wife Jia spends several hours each week dealing with administrative tasks.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll write more about what goes into running &lt;span class="caps"&gt;RMU&lt;/span&gt; soon, but for now, there is a pledgie open that is meant to bridge us over until we get a proper non-profit organization with a decent revenue model set up.  Your contributions would be greatly appreciated, so &lt;a href="http://pledgie.com/campaigns/13580"&gt;please donate now&lt;/a&gt;, and tell your friends as well.&lt;/p&gt;
&lt;h3&gt;Questions / Thoughts About &lt;span class="caps"&gt;RMU&lt;/span&gt;?&lt;/h3&gt;
&lt;p&gt;We are not accepting new students now, but you are still welcome to discuss the program with us either via irc.freenode.net in the #rmu-public channel, or via the &lt;a href="http://groups.google.com/group/ruby-mendicant-university----public"&gt;&lt;span class="caps"&gt;RMU&lt;/span&gt; Public&lt;/a&gt; google group. We are happy to hear your thoughts and questions!  Also, feel free to leave questions or comments here on this blog post, I&amp;#8217;ll be sure to read them and respond quickly if there is anything on your mind.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 21 Oct 2010 17:35:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/027-ruby-mendicant-university-update.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/027-ruby-mendicant-university-update.html</guid></item><item><title>Complexity</title><description>&lt;p&gt;If I tell you a program has 1,000,000 lines of code you&amp;#8217;ll immediately understand that this must be a complex piece of software.  Why is that?  You implicitly know that nobody copies the same 5 lines 200,000 times to create a long program which is full of redundancy.  This is another term we will have to consider while trying to improve our understanding of complexity.  As a first approximation we can say that a complex piece of software is free of redundancy.  This is of course an oversimplification and for various reasons that we will have to talk about in a minute we will not usually reach that mark in practice.&lt;/p&gt;
&lt;p&gt;This oversimplification however helps us to understand one important &amp;#8211; if not the most important &amp;#8211; task of software engineering: reduction of redundancy.  Assume that someone in an application you are writing you need to output all elements contained in an &lt;code&gt;Array&lt;/code&gt; in a special way (say, as an &lt;span class="caps"&gt;HTML&lt;/span&gt; unordered list).  You would probably write something like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  puts "&amp;lt;ul&amp;gt;"
  
  arr.each do |x|
    puts "  &amp;lt;li&amp;gt;#{x}&amp;lt;/li&amp;gt;"
  end
  
  puts "&amp;lt;/ul&amp;gt;"
&lt;/pre&gt;
&lt;p&gt;I know this is not the best of examples since you normally would be doing this with &lt;span class="caps"&gt;ERB&lt;/span&gt; or your favorite web framework.  Picking the right tools for the job is of course another important task in software engineering but we want to focus on something different which can be nicely demonstrated with this simple toy example.  (Also, you can easily follow by copying and pasting the code to &lt;span class="caps"&gt;IRB&lt;/span&gt; and play with it.)&lt;/p&gt;
&lt;p&gt;What do you do once you discover that you also have to apply the same formatting to a &lt;code&gt;Set&lt;/code&gt; in a different location of your program?  Right, you make it a function and write something like:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def format_list(enum)
  puts "&amp;lt;ul&amp;gt;"
  
  enum.each do |x|
    puts "  &amp;lt;li&amp;gt;#{x}&amp;lt;/li&amp;gt;"
  end
  
  puts "&amp;lt;/ul&amp;gt;"
end
&lt;/pre&gt;
&lt;p&gt;In other words, instead of increasing redundancy of your program you refactor a part of it so you can use this functionality in different locations.  Now you discover that you also need to be able to write to a file.  Instead of writing a second function that has a second argument for the file you want to write to you rather add an argument to this function potentially making it look like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def format_list(enum, out = $stdout)
  out.puts "&amp;lt;ul&amp;gt;"
  
  enum.each do |x|
    out.puts "  &amp;lt;li&amp;gt;#{x}&amp;lt;/li&amp;gt;"
  end
  
  out.puts "&amp;lt;/ul&amp;gt;"
end
&lt;/pre&gt;
&lt;p&gt;Again you avoided increasing redundancy of the application by adding complexity to this function which now is capable of applying the formatting in an even broader range of situations.  Let&amp;#8217;s push this one step further: now we also want to be able to do custom conversions of elements in the &lt;code&gt;Array&lt;/code&gt; instead of just always using &lt;code&gt;#to_s&lt;/code&gt;.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
TO_S = lambda {|o| o.to_s}

def format_list(enum, out = $stdout, &amp;amp;convert)
  convert ||= TO_S
  
  out.puts "&amp;lt;ul&amp;gt;"
  
  enum.each do |x|
    out.puts "  &amp;lt;li&amp;gt;#{convert[x]}&amp;lt;/li&amp;gt;"
  end
  
  out.puts "&amp;lt;/ul&amp;gt;"
end
&lt;/pre&gt;
&lt;p&gt;Now we can call it for a list of &lt;code&gt;Floats&lt;/code&gt; like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  floats = [1.2345, 4.567, 64.3]
  
  format_list floats do |f|
    "%010.3fcm" % f
  end
&lt;/pre&gt;
&lt;p&gt;Again, complexity of this function increased but we gained versatility.  In this case we are particularly lucky because all calls of the initial version of the function still work and produce the exact same result.  We might have to take a bit of runtime overhead because the original string interpolation is likely faster for the general case where only &lt;code&gt;#to_s&lt;/code&gt; is needed.  (Btw, if this program runs on some form of virtual runtime environment (such as the &lt;span class="caps"&gt;JVM&lt;/span&gt;) the situation might be different because the JVM&amp;#8217;s runtime optimization might produce better results if there is just a single function which is called more often than multiple methods that each are called infrequently.)&lt;/p&gt;
&lt;p&gt;I&amp;#8217;d say what we have seen above is a fairly typical evolution of a piece of software.  Instead of increasing redundancy of the program we increased complexity of this function.  It may seem that having different functions for various variants might be better, for example, these functions are certainly easier documented.  So why did we do this and strive to stick with a single function?&lt;/p&gt;
&lt;p&gt;Humans write software and while a piece of software might be bug free humans are not.  More importantly the world keeps &lt;a href="http://en.wikipedia.org/wiki/Heraclitus#Panta_rhei.2C_.22everything_flows.22"&gt;changing all the time&lt;/a&gt; and so do requirements for software.  Either we did not read the spec properly or someone changed his mind and now all of a sudden we need to ouput ordered lists.  That&amp;#8217;s an easy change if we just have a single implementation:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def format_list(enum, out = $stdout, &amp;amp;convert)
  convert ||= TO_S
  
  out.puts "&amp;lt;ol&amp;gt;"
  
  enum.each do |x|
    out.puts "  &amp;lt;li&amp;gt;#{convert[x]}&amp;lt;/li&amp;gt;"
  end
  
  out.puts "&amp;lt;/ol&amp;gt;"
end
&lt;/pre&gt;
&lt;p&gt;The change is so minimal one barely sees it.  Yet, if we have to apply that change to multiple versions of this function potential for new bugs is much higher.  We might forget one of them (remember that all these do not necessarily be located in the same file) or we might misspell in some of them etc.  Also the effort is higher: for this particular change it might not be dramatic but just think about having to check in multiple files into your favourite source control system, having to update documentation for multiple functions, having to adjust unit tests or other test suites etc.&lt;/p&gt;
&lt;p&gt;All in all I think it is fair to say that we gained more than we lost.  We gained developer productivity and paid only a small runtime penalty and complexity of this function.  Up to this point we can say that increased complexity has brought about a better piece of software.  However you might have a premonition of degradation which will start if we add even more features to this function.  Here we have the first reason why we do not have redundancy free applications in software: humans can only handle a certain level of complexity efficiently and so we must avoid too complex systems if we want to be able to maintain the code.&lt;/p&gt;
&lt;p&gt;Another reason why we may end up with different versions of &lt;code&gt;format_list&lt;/code&gt; is the sheer size of an application.  Large applications need multiple authors and it is not too unrealistic that people independently invent similar functions in different parts.  While this would increase redundancy it might actually be desirable to do it: if there is just the one implementation of the function all components that need it must depend on the component that contains it.  Depending on the application and programming language used the price of an additional component dependency may actually be higher than the benefit.&lt;/p&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Today we looked at software complexity caused by adding features to a piece of software to avoid redundancy.  In our daily work we continuously have to make decisions that affect this dimension of software complexity.  We have also seen how we might want to retain some level of redundancy to keep software maintainable.  Next we will look at other dimensions of software complexity.  Hopefully we will eventually come up with a classification of factors that lead to software complexity &amp;#8211; and how to tame them.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Sun, 06 Jun 2010 20:37:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/021-Complexity.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/021-Complexity.html</guid></item><item><title>Ruby Mendicant University is a Go!</title><description>&lt;blockquote&gt;
&lt;p&gt;Born less than 24 hours ago, my &lt;a href="http://blog.rubybestpractices.com/posts/gregory/025-ruby-mendicant-university.html"&gt;Ruby Mendicant University idea&lt;/a&gt; is already more than a third of the way to having its &lt;a href="http://pledgie.com/campaigns/11063"&gt;initial costs  covered.&lt;/a&gt; In less than 12 hours, we&amp;#8217;ve had 35 people &lt;a href="http://spreadsheets.google.com/viewform?formkey=dHlLM2E1ZllqN2hSWWhIWFBXRmthN2c6MQ"&gt;request a copy of the entrance exam.&lt;/a&gt; So now that the idea is validated, it&amp;#8217;s time to begin on the execution.&lt;/blockquote&gt;&lt;/p&gt;
&lt;p&gt;You can keep up on the latest news by following the &lt;a href="http://seacreature.posterous.com/tag/rubymendicant"&gt;rubymendicant&lt;/a&gt; tag at &lt;a href="http://seacreature.posterous.com"&gt;seacreature.posterous.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;small&gt;&lt;i&gt;PS: This morning, I decided that &lt;a href="http://seacreature.posterous.com/19694115"&gt;I want to consolidate my blogging and tweeting,&lt;/a&gt; so most of my content will be posted to my new posterous blog rather than here at &lt;span class="caps"&gt;RBP&lt;/span&gt; blog.   Also, I am moving my twitter account over to &lt;a href="http://twitter.seacreature"&gt;@seacreature&lt;/a&gt; exclusively, rather than using &lt;a href="http://twitter.com/rubypractices"&gt;@rubypractices.&lt;/a&gt;   While this isn&amp;#8217;t quite an announcement of ending the &lt;span class="caps"&gt;RBP&lt;/span&gt; Blog project, it&amp;#8217;s a step in that direction.  Thanks so much for your attention and feedback over the last year or so.  Hope to see you on the other side!&lt;/i&gt;&lt;/small&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 04 Jun 2010 14:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/026-ruby-mendicant-university-is-a-go.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/026-ruby-mendicant-university-is-a-go.html</guid></item><item><title>IDEA: Ruby Mendicant University</title><description>&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:  You can &lt;a href="http://pledgie.com/campaigns/11063"&gt;donate now at Pledgie&lt;/a&gt; / I know this is early, but in the spirit of Ruby Mendicant, I&amp;#8217;m looking for those trusting individuals who will give with altruistic intentions first, I&amp;#8217;ll spend my time convincing everyone else later :)&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt; 2: More details to come, but those who wish to receive a copy of the entrance exam should &lt;a href="http://is.gd/cBNH9"&gt;sign up via this google form.&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Back in 2008, the highlight of my year was the &lt;a href="http://majesticseacreature.com/mendicant/"&gt;Ruby Mendicant&lt;/a&gt; project.  Through some stroke of luck, I ended up getting enough funding from independent community donations to take 22 weeks off of work to focus on building &lt;a href="http://prawn.majesticseacreature.com"&gt;Prawn&lt;/a&gt;, a pure ruby &lt;span class="caps"&gt;PDF&lt;/span&gt; generation library that is now nearing its 1.0 release.&lt;/p&gt;
&lt;p&gt;Now in 2010, I&amp;#8217;d like to do the same thing for Ruby training and education.  Similar to my &lt;a href="http://www.oreillynet.com/ruby/blog/2008/03/id_love_to_quit_my_job_sort_of.html"&gt;original post that spawned Ruby Mendicant&lt;/a&gt;, the details are currently fuzzy in my head, but I have enough of a rough outline to collect some comments on.&lt;/p&gt;
&lt;h3&gt;The Idea&lt;/h3&gt;
&lt;p&gt;I want to run a free online school designed to help intermediate Ruby programmers master their craft.  Each session would include up to 20 or so participants and run for 3 weeks.&lt;/p&gt;
&lt;p&gt;The basic activities would include:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;an entrance exam (basic coding problem and questionnaire)&lt;/li&gt;
	&lt;li&gt;selected readings in freely available Ruby books and online resources&lt;/li&gt;
	&lt;li&gt;individual and group code review&lt;/li&gt;
	&lt;li&gt;realistic problems to work on and discuss&lt;/li&gt;
	&lt;li&gt;Q&amp;amp;A sessions&lt;/li&gt;
	&lt;li&gt;a final exam (which if passed, would earn the student &amp;#8216;alumni&amp;#8217; status)&lt;/li&gt;
	&lt;li&gt;possibly some pre-recorded or live presentations&lt;/li&gt;
	&lt;li&gt;a mailing list for students to discuss questions with me&lt;/li&gt;
	&lt;li&gt;online discussions with guest speakers from our community.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The goal would be to keep these classes going on a rolling basis, so that we could reach a large number of students in the course of a year.  If we did a schedule like 3 weeks on, 1 week off, we could do 13 sessions in a year, allowing me to reach up to 260 students.&lt;/p&gt;
&lt;p&gt;Of the available slots, I would also like to reserve a certain amount of them for &amp;#8220;hardship&amp;#8221; situations.  People who are currently out of work, those who are in tough economic climates, or have some sort of difficulty in their lives that this opportunity could really help them overcome.  I have not yet figured out how to do this without introducing a ton of bias in my selections, and I have no way of verifying these details, but it seems like a good idea in theory to me at least.&lt;/p&gt;
&lt;p&gt;At least some of the sessions would be open to the community at large, and at least some of the material would be released under an open documentation license.  This way, while the core focus would be on affecting big change for small groups at a time, the whole community could benefit from the existence of this program as well.&lt;/p&gt;
&lt;h3&gt;Funding&lt;/h3&gt;
&lt;p&gt;The up front cost of building the material is large, enough where I would need to take a couple days off a week from consulting work for a period of 8 weeks or so to come up with adequate material.  While the replacement cost for that work is pretty high (over 6k), I could probably still get by well enough if I had about $3000 in donations to produce the initial material.&lt;/p&gt;
&lt;p&gt;The promising thing about the above lesson plan is that since a lot of it is interactive and tailored to individual efforts, once I build the core lesson plan, actually running the &amp;#8220;school&amp;#8221; will be comparatively less work.  I won&amp;#8217;t know at all until I actually run it, but I would expect that I could keep the school up and running for about $1500 a month.&lt;/p&gt;
&lt;p&gt;But in the Mendicant spirit, I only would want to keep this thing going if it was of value to the community.  So rather than looking for donations for the running of the school up front, I would only raise money to cover the initial costs of content creation.&lt;/p&gt;
&lt;p&gt;Whether the school lives or dies, grows or shrinks, would be based on the generosity of previous students as well as that of the community at large.&lt;/p&gt;
&lt;h3&gt;Schedule&lt;/h3&gt;
&lt;p&gt;If I could raise enough money by the end of June, I could then shift my schedule around in July and August to allow me to work on content creation.  That would let me start the first class around the first week of September.&lt;/p&gt;
&lt;h3&gt;Why Me?&lt;/h3&gt;
&lt;p&gt;Besides the &lt;a href="http://http://majesticseacreature.com/mendicant/"&gt;Ruby Mendicant&lt;/a&gt; project, I have also taught trainings at the Lone Star Ruby Conference (2008,2009), and am also part of the trio hosting &lt;a href="http://thecompleatrubyist.com/"&gt;The Compleat Rubyist&lt;/a&gt;.  I have written two books that are now completely free for people to download and read.  And other stuff.&lt;/p&gt;
&lt;p&gt;Trust me.  I&amp;#8217;d be good at this :)&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re wondering what&amp;#8217;s in it for me:  I believe that free education is one of the most valuable things in the world, and I also learn a ton by teaching others.  If I can make enough money to offset my costs and maintain a decent house-and-wife life, I feel like this is a super good use of my time.&lt;/p&gt;
&lt;h3&gt;What do you think?&lt;/h3&gt;
&lt;p&gt;Right now, feedback is key.  I only want to take this project on if I think it&amp;#8217;ll be a sure thing.   Please respond, answering these questions:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Would you want to attend this online school?&lt;/li&gt;
	&lt;li&gt;Would you be willing to donate to help with its creation?&lt;/li&gt;
	&lt;li&gt;Would you recommend this program to others?&lt;/li&gt;
	&lt;li&gt;What can I do to make it even more awesome?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Thanks in advance for your suggestions.  Here&amp;#8217;s hoping that we can make this work :)&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;:  You can &lt;a href="http://pledgie.com/campaigns/11063"&gt;donate now at Pledgie&lt;/a&gt; / I know this is early, but in the spirit of Ruby Mendicant, I&amp;#8217;m looking for those trusting individuals who will give with altruistic intentions first, I&amp;#8217;ll spend my time convincing everyone else later :)&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt; 2: More details to come, but those who wish to receive a copy of the entrance exam should &lt;a href="http://is.gd/cBNH9"&gt;sign up via this google form.&lt;/a&gt;&lt;/i&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 03 Jun 2010 14:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/025-ruby-mendicant-university.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/025-ruby-mendicant-university.html</guid></item><item><title>If you want to see the wizard, go to Oz.</title><description>&lt;p&gt;Back in June of 2005, I booked a flight out to Oklahoma City, OK, but it might as well have been to Oz.  I was off to see the wizard who had been teaching me black magic in both Perl and Ruby throughout my high school days.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.grayproductions.net"&gt;James Edward Gray II&lt;/a&gt; and I had somehow convinced Ruby Central, Inc. that a &lt;a href="http://rubyforge.org/projects/gambit"&gt;web game framework&lt;/a&gt; was worth a Codefest grant, and we used the money as a chance to finally meet each other in person.  At the time, we decided to build things from scratch, since Rails 0.12 didn&amp;#8217;t quite have the features we needed :)&lt;/p&gt;
&lt;p&gt;Not counting the friends I talked into studying programming here and there, this was my first time ever working side by side with another hacker.  I didn&amp;#8217;t know what to expect, but by the time I left, I couldn&amp;#8217;t believe that what we had done was possible.  Safe to say, JEG2 blew my mind, in the way that any good wizard can.   Here&amp;#8217;s what I wrote just after returning home in June 2005:&lt;/p&gt;
&lt;blockquote&gt;&lt;i&gt;&lt;br /&gt;
The last nine days were amazing. Exploited undocumented features of WEBRick.&lt;br /&gt;
Making use of circular logic flows, making code do things that it wasn&amp;#8217;t built&lt;br /&gt;
to do. Pushing the limits, building truly clever tools and libraries that will&lt;br /&gt;
make people&amp;#8217;s lives easier, and more fun. &lt;br /&gt;
&lt;br /&gt;
I myself feel like I&amp;#8217;m standing a little taller after all the hard work we&lt;br /&gt;
did. That was hacking in it&amp;#8217;s purest nature, and though I don&amp;#8217;t like to self&lt;br /&gt;
attribute that word, there is nothing else to describe it. Ideas flowed any &lt;br /&gt;
hour of the day, even in our dreams. No one tried to take charge, I didn&amp;#8217;t get &lt;br /&gt;
mad when James replaced bits of my code with something better, and James &lt;br /&gt;
didn&amp;#8217;t get mad when I questioned his logic and pushed him to raise the bar. In &lt;br /&gt;
the rare occasion that I proved James wrong on something, he&amp;#8217;d just shrug his &lt;br /&gt;
shoulders, embrace The Right Way, and go with it.&lt;br /&gt;
&lt;br /&gt;
We joked around a lot referring to certain programming practices as &amp;#8220;The way &lt;br /&gt;
of life&amp;#8221;. Though that is quite silly when it applies to 80 character linewrap &lt;br /&gt;
or a certain tab width, it was something that motivated us. We could look at &lt;br /&gt;
our code, and at a glance see if it was following &amp;#8220;The way&amp;#8221; or not. When it &lt;br /&gt;
wasn&amp;#8217;t, we waited for something better to come along, and then we did what we &lt;br /&gt;
had to do to make it happen.&lt;br /&gt;
&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;Now, I was just a kid at the time, but I knew something important had just happened.  Most importantly I realized that the kind of interaction you can have over the internet, though amazing, pales in comparison to face-to-face interaction.  Here&amp;#8217;s what James had to say shortly after our first meeting:&lt;/p&gt;
&lt;blockquote&gt;&lt;i&gt;&lt;br /&gt;
&amp;#8220;We&amp;#8217;ve just completed nine solid days of development on Gambit. Now&lt;br /&gt;
that&amp;#8217;s a &amp;#8220;Codefest&amp;#8221; alright! I thought I would share a little with&lt;br /&gt;
the curious about how I think it went&amp;#8230;&lt;br /&gt;
&lt;br /&gt;
Greg Brown flew out to my home in Oklahoma so we could work on&lt;br /&gt;
Gambit. It was nice to finally meet face-to-face. We&amp;#8217;ve actually&lt;br /&gt;
programmed together on many projects these last couple of years, but&lt;br /&gt;
this was the first time we didn&amp;#8217;t do it over the Internet. We&amp;#8217;re&lt;br /&gt;
both grateful to the wonderful people at Ruby Central for giving us&lt;br /&gt;
that opportunity.&lt;br /&gt;
&lt;br /&gt;
We&amp;#8217;ve had practice, so we work pretty well together by now. Greg&lt;br /&gt;
would probably say that I&amp;#8217;ve almost beat all his bad habits out of&lt;br /&gt;
him. ;) True or not, I know he&amp;#8217;s always challenging me and pushing&lt;br /&gt;
me to new limits of what I can build. I think we both learned a lot&lt;br /&gt;
from working together on this project.&lt;br /&gt;
&lt;/i&gt;&lt;/blockquote&gt;
&lt;p&gt;While there is a certain amount of altruism involved in mentoring a novice, it is an act that pays you back tenfold.  Every concept that you can teach another person is one that you must master through and through, in ways that you&amp;#8217;d never even scratch the surface of on your own.&lt;/p&gt;
&lt;p&gt;Whether he realizes it or not, James revealed a secret to me during that hackfest, one that is to blame for all of my future successes in programming: &lt;i&gt;Share your experiences and knowledge with others, and you win.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Fast forward to 2010, and obviously JEG2 and I have come a long way.  We&amp;#8217;ve both done talks throughout the US, and James even made it over to Japan last year.  We&amp;#8217;ve both published books on Ruby, and made more friends in the community than we ever imagined possible back in 2005.  While part of me feels indebted to James still, I feel like I&amp;#8217;ve paid it forward through my works.  That made our mentorship role turn into a friendly rivalry, where we both keep pushing each other to get better at what we do, even if indirectly.&lt;/p&gt;
&lt;p&gt;James had a big head start, so he normally beats me to the punch on things.  Up until recently, I had only one thing under my belt that JEG2 didn&amp;#8217;t: I had &lt;a href="http://2007.goruco.com/volunteers/"&gt;helped design and run a Ruby conference&lt;/a&gt;. Not one to be outdone, JEG2 has decided to level that playing field by running &lt;a href="http://reddirtrubyconf.com"&gt;Red Dirt RubyConf&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Red Dirt RubyConf: Your ticket to Oz&lt;/h3&gt;
&lt;p&gt;If you like what I&amp;#8217;ve been doing in Ruby, you now know that I owe it all to JEG2.  Here&amp;#8217;s the good news:  He&amp;#8217;s now inviting all of you to his neck of the woods to spend some time hacking, learning, and sharing.  &lt;b&gt;But you need to act fast, &lt;a href="http://reddirtrubyconf.com/register_to_attend"&gt;registration&lt;/a&gt; closes Friday, April 23!&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Red Dirt RubyConf is a unique two day conference which blends training in with a uniquely themed single track session lineup.  In it, you won&amp;#8217;t just get to meet James, but also some other amazing Ruby people as well, including Dave Thomas and Jim Weirich.&lt;/p&gt;
&lt;p&gt;The conference is run by James, his lovely wife Dana (who I could write a whole other post about), and some other great folks from the Oklahoma Ruby group.  If you head out there, I can promise you that you&amp;#8217;ll have an awesome time, learn a ton, and meet some amazing people.&lt;/p&gt;
&lt;p&gt;Unfortunately, I won&amp;#8217;t be able to attend, but I&amp;#8217;ll sure be there in spirit.  If you do make it there, tell James I said hi, and have a great time!&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;DISCLOSURE&lt;/span&gt;: I told James I&amp;#8217;d be writing something to promote Red Dirt, but he didn&amp;#8217;t ask me to do this, and he had no idea what I&amp;#8217;d come up with.  So I take 100% responsibility for the contents of this article.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Wed, 21 Apr 2010 14:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/024-wizard-of-oz.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/024-wizard-of-oz.html</guid></item><item><title>rubyproblems.com is now live!</title><description>&lt;p&gt;Back on St. Patrick&amp;#8217;s day, I had made the following plug about rubyproblems.com at the bottom of my last post:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This site will provide realistic exercises that test your Ruby and general coding skills, along with detailed tutorials written in the style of &lt;span class="caps"&gt;RBP&lt;/span&gt; explaining possible solutions to the problems. The exercises will be free and open to everyone, the solutions we&#8217;ll be selling as nicely typeset, professionally edited, &lt;span class="caps"&gt;DRM&lt;/span&gt;-free &lt;span class="caps"&gt;PDF&lt;/span&gt; download&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I am pleased to announce that this service did indeed launch yesterday, and that you can give it a try by heading over to &lt;a href="http://rubyproblems.com"&gt;rubyproblems.com&lt;/a&gt; now.  If you need a bit more information, consider checking out &lt;a href="http://rubybestpractices.com/rubyproblems-teaser.swf"&gt;this screencast&lt;/a&gt; or &lt;a href="http://rubyproblems.blogspot.com/2010/04/were-live.html"&gt;this announcement&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While this is still a bit of an experiment for us, we&amp;#8217;re really excited to see how things turn out.  Those who liked my book should love this site, which is why I&amp;#8217;m announcing it here.&lt;/p&gt;
&lt;p&gt;But now, the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog should return to its non-marketing-hype self.  In fact, I really want to find the time to write about why I think this is the most horrible syntax ever:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
describe Array do
  its(:length) { should == 0 }
end
&lt;/pre&gt;
&lt;p&gt;But I suppose that bit of flame bait will need to wait until a later day :)&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Wed, 07 Apr 2010 14:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/023-rubyproblems.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/023-rubyproblems.html</guid></item><item><title>Full Book Now Available For Free!</title><description>&lt;p&gt;The last few weeks have been a wild ride.  Starting in January, I&amp;#8217;ve been releasing a chapter at a time here on the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog, and many of those chapters were pretty well commented on.  Just for the sake of completeness, here&amp;#8217;s a link back to each of those posts:&lt;/p&gt;
&lt;ul&gt;
   &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;Chapter 1: Driving Code Through Tests&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;Chapter 2: Designing Beautiful &lt;span class="caps"&gt;APIS&lt;/span&gt; / Chapter 3: Mastering the Dynamic Toolkit&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html"&gt;Chapter 4: Text Processing and File Management&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html"&gt;Chapter 5: Functional Programming Techniques&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/020-rbp-ch6.html"&gt;Chapter 6: When Things Go Wrong&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/021-rbp-ch7.html"&gt;Chapter 7: Reducing Cultural Barriers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this point, I&amp;#8217;d like to invite you to just &lt;a href="http://sandal.github.com/rbp-book/pdfs/rbp_1-0.pdf"&gt;grab the whole thing&lt;/a&gt; and read it at your leisure.  This includes the final chapter &amp;#8220;Skillful Project Maintenance&amp;#8221;, as well as the three appendixes: &amp;#8220;Writing Backwards Compatible Code&amp;#8221;, &amp;#8220;Leveraging Ruby&amp;#8217;s Standard Library&amp;#8221;, and &amp;#8220;Ruby Worst Practices&amp;#8221;.&lt;/p&gt;
&lt;p&gt;Since the book is now open source, if you find something you don&amp;#8217;t like about it, it&amp;#8217;s your responsibility to help make it better!  But if you do like it as it is, it might be more pleasant to read in print or on your Kindle, so you might want to pick it up from &lt;a href="http://oreilly.com/catalog/9780596523015/"&gt;O&amp;#8217;Reilly&lt;/a&gt; or &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;Amazon&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Manuscript and Production Files&lt;/h3&gt;
&lt;p&gt;You can find the details about the &lt;a href="http://github.com/sandal/rbp-book"&gt;manuscript and production files on github&lt;/a&gt;, now released under a Creative Commons license.  It might be a little while before I can put some time into making this contributor friendly, but those looking to experiment or explore a bit are certainly welcome.  The manuscript is written using the &lt;a href="http://www.methods.co.nz/asciidoc/"&gt;amazing asciidoc toolchain&lt;/a&gt;, which means the plaintext files you see in the git repository actually are what I used to generate something very close to the final print version of &lt;span class="caps"&gt;RBP&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;So that&amp;#8217;s pretty much it.  While this will soon mark a new beginning, this figuratively and literally marks the last chapter in the history of &lt;span class="caps"&gt;RBP&lt;/span&gt; being &amp;#8220;my book&amp;#8221;.  It&amp;#8217;s yours now, do what you want with it.  If you have interesting ideas that you want to run by me, I&amp;#8217;d be happy to help however I can.  Otherwise, enjoy and have fun!&lt;/p&gt;
&lt;h3&gt;But I finished the &lt;span class="caps"&gt;RBP&lt;/span&gt; book and I want more!  What should I do?&lt;/h3&gt;
&lt;p&gt;Okay, you got me.  I&amp;#8217;ve been trying to take the &amp;#8220;spirit&amp;#8221; of &lt;span class="caps"&gt;RBP&lt;/span&gt; and apply it to two new projects, both a little more interactive in nature.  For those who enjoyed the book, you may be interested in these two resources, both on the horizon.&lt;/p&gt;
&lt;p&gt;The first is &lt;a href="http://rubyproblems.com"&gt;rubyproblems.com&lt;/a&gt;.  This site will provide realistic exercises that test your Ruby and general coding skills, along with detailed tutorials written in the style of &lt;span class="caps"&gt;RBP&lt;/span&gt; explaining possible solutions to the problems.  The exercises will be free and open to everyone, the solutions we&amp;#8217;ll be selling as nicely typeset, professionally edited, &lt;span class="caps"&gt;DRM&lt;/span&gt;-free &lt;span class="caps"&gt;PDF&lt;/span&gt; downloads.  We launch April 6th, 2010, but if you &lt;a href="http://rubyproblems.com/login"&gt;register now&lt;/a&gt;, you&amp;#8217;ll get a free solution download when the site goes live.  Whether you plan on buying content or not, the exercises themselves should provide great learning opportunities.  If you liked &lt;span class="caps"&gt;RBP&lt;/span&gt;, you&amp;#8217;ll definitely like Ruby Problems.&lt;/p&gt;
&lt;p&gt;The second chance to bolster what you&amp;#8217;ve learned in &lt;span class="caps"&gt;RBP&lt;/span&gt; is to attend a &lt;a href="http://thecompleatrubyist.com/"&gt;Compleat Rubyist&lt;/a&gt; training event.  This is a joint venture between David A. Black, Jeremy McAnally, and myself that&amp;#8217;s designed to provide a crash course in going from &amp;#8220;knowing Ruby&amp;#8221; to &amp;#8220;being awesome at Ruby&amp;#8221;.  We did one of these in Tampa, FL in January, and it was blast.  Our next one is scheduled for the Chicago area on June 18-19.  We plan to do this as a regular thing, so if you can&amp;#8217;t make it out to the Midwest, let us know where we should be going to find you!  If you want a little more detail, you can check out &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/359006"&gt;my RubyTalk announcement about the upcoming event&lt;/a&gt;, and perhaps take a look at the &lt;a href="http://blog.rubybestpractices.com/posts/gregory/014-the-compleat-rubyist.html"&gt;Tampa retrospective&lt;/a&gt; here on the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog.&lt;/p&gt;
&lt;h3&gt;Disclaimer&lt;/h3&gt;
&lt;p&gt;While I typically hate direct marketing, I am absolutely excited about the above two things, and so I felt compelled to mention them as good &amp;#8216;next steps&amp;#8217; as you go beyond &lt;span class="caps"&gt;RBP&lt;/span&gt;.  Doing these as commercial projects won&amp;#8217;t ever make me rich, but it does allow me to take time away from billable work and really focus on producing awesome content and engaging with those who could learn something from it.  So just know that whenever you send a bit of cash my way, you&amp;#8217;re supporting a fellow hacker who will keep giving back at every opportunity.&lt;/p&gt;
&lt;p&gt;But for those a bit weary of marketing gimmicks, the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog will be going back to its pristine &amp;#8220;no fluff, just stuff&amp;#8221; program after today.  It is a little hard to keep new content flowing, but we&amp;#8217;ll do the best we can.  Until then, happy hacking!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Wed, 17 Mar 2010 16:50:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/022-rbp-now-open.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/022-rbp-now-open.html</guid></item><item><title>Ruby Tuesdays: RBP Chapter 7</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;h3&gt;Progress To Date&lt;/h3&gt;
&lt;p&gt;We&amp;#8217;ve already released the first five chapters, and discussion has been great.  Be sure to check out these previous posts if you haven&amp;#8217;t already:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
   &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;Chapter 1: Driving Code Through Tests&lt;/a&gt;&lt;/li&gt;,&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;Chapter 2: Designing Beautiful &lt;span class="caps"&gt;APIS&lt;/span&gt; / Chapter 3: Mastering the Dynamic Toolkit&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html"&gt;Chapter 4: Text Processing and File Management&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html"&gt;Chapter 5: Functional Programming Techniques&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/020-rbp-ch6.html"&gt;Chapter 6: When Things Go Wrong&lt;/a&gt;&lt;/li&gt;&lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;These discussions should give you a sense of the wide range of ideas our readers have been sharing as a result of this ongoing book study.&lt;/p&gt;
&lt;h3&gt;How To Read &lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Readers are encouraged to &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;fight &lt;span class="caps"&gt;RBP&lt;/span&gt; as they read it&lt;/a&gt;, rather than just soaking up the information.  Although I claim this book is about &amp;#8220;Best Practices&amp;#8221;, the only reason that is true is that it&amp;#8217;s a result of countless conversations with folks who are deep in the Ruby trenches getting stuff done.  The only way for &lt;span class="caps"&gt;RBP&lt;/span&gt; to remain current and relevant is to continue these discussions, using its content as a jumping off point for fresh ideas.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;In 2010, programmers no longer have an excuse for not having a baseline understanding of multilingualization and localization techniques.  But for those who have not yet taken a crash course, this chapter on &amp;#8220;Reducing Cultural Barriers&amp;#8221; provides a primer that should be good enough to get you started.&lt;/p&gt;
&lt;p&gt;Go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch07.pdf"&gt;download Chapter 7 now&lt;/a&gt;.  You&amp;#8217;re encouraged to participate in the discussion here once you&amp;#8217;ve had a chance to play with some of the ideas from the book. Don&amp;#8217;t worry if it takes you more than a few days finish reading it, you can come back and comment any time.&lt;/p&gt;
&lt;p&gt;Enjoy, and come back next Tuesday (2010.03.16) for the final chapter, &amp;#8220;Skillful Project Maintenance&amp;#8221;, which covers Ruby&amp;#8217;s built in project management tools, and some of the techniques surrounding them.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet (though I&amp;#8217;m getting closer now, finally!)&lt;/p&gt;
&lt;p&gt;If you like what you see, please buy the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  I imagine that seeing decent sales numbers will encourage O&amp;#8217;Reilly to keep moving towards making their content openly available, which would totally rock.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents for the manuscript are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 09 Mar 2010 14:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/021-rbp-ch7.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/021-rbp-ch7.html</guid></item><item><title>Ruby Tuesdays: RBP Chapter 6</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;h3&gt;Progress To Date&lt;/h3&gt;
&lt;p&gt;We&amp;#8217;ve already released the first five chapters, and discussion has been great.  Be sure to check out these previous posts if you haven&amp;#8217;t already:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
   &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;Chapter 1: Driving Code Through Tests&lt;/a&gt;&lt;/li&gt;,&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;Chapter 2: Designing Beautiful &lt;span class="caps"&gt;APIS&lt;/span&gt; / Chapter 3: Mastering the Dynamic Toolkit&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html"&gt;Chapter 4: Text Processing and File Management&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html"&gt;Chapter 5: Functional Programming Techniques&lt;/a&gt;&lt;/li&gt;&lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;These discussions should give you a sense of the wide range of ideas our readers have been sharing as a result of this ongoing book study.&lt;/p&gt;
&lt;h3&gt;How To Read &lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Readers are encouraged to &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;fight &lt;span class="caps"&gt;RBP&lt;/span&gt; as they read it&lt;/a&gt;, rather than just soaking up the information.  Although I claim this book is about &amp;#8220;Best Practices&amp;#8221;, the only reason that is true is that it&amp;#8217;s a result of countless conversations with folks who are deep in the Ruby trenches getting stuff done.  The only way for &lt;span class="caps"&gt;RBP&lt;/span&gt; to remain current and relevant is to continue these discussions, using its content as a jumping off point for fresh ideas.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;This chapter on what to do &amp;#8220;When Things Go Wrong&amp;#8221; turned out to be one of the most enjoyable ones to write.  Having a strong ability to troubleshoot and debug code is a powerful skill to have, and I do my best to share all my secrets here.&lt;/p&gt;
&lt;p&gt;Go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch06.pdf"&gt;download Chapter 6 now&lt;/a&gt;.  You&amp;#8217;re encouraged to participate in the discussion here once you&amp;#8217;ve had a chance to play with some of the ideas from the book. Don&amp;#8217;t worry if it takes you more than a few days finish reading it, you can come back and comment any time.&lt;/p&gt;
&lt;p&gt;Enjoy, and come back next Tuesday (2010.03.09) for Chapter 7, &amp;#8220;Reducing Cultural Barriers&amp;#8221;, which covers multilingualization (m17n) and localization (L10n) techniques.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet (though I&amp;#8217;m getting closer now, finally!)&lt;/p&gt;
&lt;p&gt;If you like what you see, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  I imagine that seeing decent sales numbers will encourage O&amp;#8217;Reilly to keep moving towards making their content openly available, which would totally rock.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents for the manuscript are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 02 Mar 2010 07:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/020-rbp-ch6.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/020-rbp-ch6.html</guid></item><item><title>Code Massage</title><description>&lt;p&gt;This article started out as a mental experiment and led to a surprising result.  I post this mostly for the fun of it.  But of course you can take something away from it.  With that I do mean not only technical solutions.  I believe firmly that a certain level of playfulness actually helps finding better solutions.  The other ingredient you need is a certain eagerness for improvement which means to not be be content too early.  OK, let&amp;#8217;s start.&lt;/p&gt;
&lt;p&gt;The scenario I started out was this: suppose you want to anonymize email addresses because you want to publish an email but not expose addresses to spam harvesting.  Yet, you want to make sure that every address is always represented with the same replacement address in order to not change the meaning.  You might immediately answer &amp;#8220;We&amp;#8217;ll need a Hash so we can efficiently find addresses that have been replaced already&amp;#8221; &amp;#8211; and so did I.&lt;/p&gt;
&lt;h3&gt;Java Style&lt;/h3&gt;
&lt;p&gt;If you are familiar with the Java standar library you know that &lt;code&gt;java.util.Map&lt;/code&gt; has methods to check whether a key is present, to set values and to retrieve values.  So after switching to Ruby you might be tempted to do it like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
subst = {}

puts email.gsub(ADDR) {|match|
  if subst.has_key? match
    subst[match]
  else
    subst[match] = "&amp;lt;&amp;lt;MAIL #{subst.size}&amp;gt;&amp;gt;"
  end
}
&lt;/pre&gt;
&lt;p&gt;Whenever we encounter an email address we must first check whether we have generated a replacement string for this address already.  If not, we create a new one.  No rocket science.&lt;/p&gt;
&lt;h3&gt;A little more sophisticated&lt;/h3&gt;
&lt;p&gt;You might find documumentation of method &lt;a href="http://ruby-doc.org/ruby-1.9/classes/Hash.html#M000380"&gt;Hash#fetch&lt;/a&gt; when reading the library documentation which comes in handy because the block is invoked if the key is not present in the &lt;code&gt;Hash&lt;/code&gt;.  The code now looks a little shorter already:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
subst = {}

puts email.gsub(ADDR) {|match|
  subst.fetch(match) {|k| subst[k] = "&amp;lt;&amp;lt;MAIL #{subst.size}&amp;gt;&amp;gt;" }
}
&lt;/pre&gt;
&lt;h3&gt;O||=erator&lt;/h3&gt;
&lt;p&gt;A similar thing can be achieved with the ubiquituous operator &lt;code&gt;||=&lt;/code&gt; which allows for conditional execution.  In case you are not yet familiar with it you&amp;#8217;ll find plenty of discussions in ruby-talk that revolve around this.  The short summary is that &lt;code&gt;a ||= b&lt;/code&gt; is equivalent to &lt;code&gt;a || a = b&lt;/code&gt; and &lt;em&gt;not&lt;/em&gt; &lt;code&gt;a = a || b&lt;/code&gt; as you might be tempted to believe.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
subst = {}

puts email.gsub(ADDR) {|match|
  subst[match] ||= "&amp;lt;&amp;lt;MAIL #{subst.size}&amp;gt;&amp;gt;"
}
&lt;/pre&gt;
&lt;p&gt;The code has become even more shorter.  But we are not finished yet!&lt;/p&gt;
&lt;h3&gt;Outsourcing&lt;/h3&gt;
&lt;p&gt;If you need that replacement in multiple places of your code you&amp;#8217;ll likely put it into a method.  However, if you want to replace different things (i.e. you need different regular expressions) which can match the same string you might want to outsource the generation of the replacement string so you can use it with different calls of &lt;code&gt;gsub&lt;/code&gt;.  You can of course do it with an additional method but there is a more elegant way to do it:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
subst = Hash.new {|h,k| h[k] = "&amp;lt;&amp;lt;MAIL #{h.size}&amp;gt;&amp;gt;"}

puts email.gsub(ADDR) {|match| subst[match]}
&lt;/pre&gt;
&lt;p&gt;We simply use &lt;code&gt;Hash's&lt;/code&gt; default proc functionality for this.  This is basically the same the fetch block does but now the code is attached to the &lt;code&gt;Hash&lt;/code&gt; instance and not to the &lt;code&gt;#fetch&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;You might wonder, how much further can we get?  And indeed, this solution is probably the most idiomatic one and the one you see most frequent in seasoned Ruby developers&amp;#8217; code.  It turns out though, that we can drive this further if we are prepared to use some newer Ruby features.&lt;/p&gt;
&lt;h3&gt;Getting tricky&lt;/h3&gt;
&lt;p&gt;Since Ruby 1.8.7 you can use &lt;em&gt;anything&lt;/em&gt; as a block parameter to a method provided it implements a method &lt;code&gt;to_proc&lt;/code&gt; which returns a &lt;code&gt;Proc&lt;/code&gt;.  Namely class &lt;code&gt;Symbol&lt;/code&gt; implements this method in the following way: it returns a proc which needs at least one argument when called and invokes the given method with the remaining arguments on that instance.  This allows for convenient operations like mapping data:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; (1..3).map &amp;amp;:to_s
=&amp;gt; ["1", "2", "3"]
&lt;/pre&gt;
&lt;p&gt;One thing that bugged me was that the block handed to &lt;code&gt;gsub&lt;/code&gt; above does nothing more than basically only forward the &lt;code&gt;Hash&lt;/code&gt; lookup.  With the new feature it should be possible to make the code a bit more concise.  Luckily there are some core classes that implement &lt;code&gt;to_proc&lt;/code&gt; already:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
$ ruby -e 'ObjectSpace.each_object(Module) {|m| p m if m.instance_methods.include? "to_proc"}'
Method
Proc
Symbol

$ ruby19 -e 'ObjectSpace.each_object(Module) {|m| p m if m.instance_methods.include? :to_proc}'
Method
Proc
Symbol
&lt;/pre&gt;
&lt;p&gt;We can exploit this fact and now we can write the code like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
subst = Hash.new {|h,k| h[k] = "&amp;lt;&amp;lt;MAIL #{h.size}&amp;gt;&amp;gt;"}

puts email.gsub(ADDR, &amp;amp;subst.method(:[]))
&lt;/pre&gt;
&lt;p&gt;&lt;i&gt;Note: code changed after arthurschreiber&amp;#8217;s comment.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Now, that looks ugly, doesn&amp;#8217;t it?  We should be able to do something about that, because after all we love Ruby for its elegance and clear syntax.  Yes, we can!&lt;/p&gt;
&lt;h3&gt;Even shorter with a general solution&lt;/h3&gt;
&lt;p&gt;Since we can use &lt;em&gt;any&lt;/em&gt; object why not provide a general mechanism for this case?  Not only &lt;code&gt;Hash&lt;/code&gt; but also &lt;code&gt;Array&lt;/code&gt; and a lot more classes provide method &lt;code&gt;[]&lt;/code&gt; as a general hook for lookup or exeution:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
$ ruby19 -e 'ObjectSpace.each_object(Module) {|m| p m if m.instance_methods.include? :[]}'
Thread
Method
Proc
Struct::Tms
MatchData
Struct
Hash
Array
Bignum
Fixnum
Symbol
String
&lt;/pre&gt;
&lt;p&gt;Now, let&amp;#8217;s allow all these to be simply used as block parameters!&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Object
  def to_proc(m = :[])
    method(m).to_proc
  end
end

subst = Hash.new {|h,k| h[k] = "&amp;lt;&amp;lt;MAIL #{h.size}&amp;gt;&amp;gt;"}

puts email.gsub(ADDR, &amp;amp;subst)
&lt;/pre&gt;
&lt;p&gt;Now we can just pass any &lt;code&gt;Hash&lt;/code&gt; instance to &lt;code&gt;gsub&lt;/code&gt;.  The working logic for calculating our replacement string is now completely restricted to the &lt;code&gt;Hash&lt;/code&gt; creation.  This is a really elegant solution!&lt;/p&gt;
&lt;h3&gt;Golf&lt;/h3&gt;
&lt;p&gt;We can reduce the number of characters to type a bit more by throwing out the variable declaration and effectively turn this into a one liner:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
puts email.gsub(ADDR, &amp;amp;Hash.new {|h,k| h[k] = "&amp;lt;&amp;lt;MAIL #{h.size}&amp;gt;&amp;gt;"})
&lt;/pre&gt;
&lt;p&gt;I don&amp;#8217;t think this is an improvement over the last variant but sometimes it helps driving things as far as possible to find out where in the process we reached the optimum.&lt;/p&gt;
&lt;h3&gt;The fun begins&lt;/h3&gt;
&lt;p&gt;Some classes do also implement method &lt;code&gt;[]&lt;/code&gt; &amp;#8211; we should be able to make good use of that as well.  We might be tempted to create a lot of &lt;code&gt;Struct&lt;/code&gt; instances via this method.  It can be done but we have to do some tweaking because &lt;code&gt;Struct.[]&lt;/code&gt; does not splat a single &lt;code&gt;Array&lt;/code&gt; argument so we have to redefine it a bit:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
Name = Struct.new :forename, :surname

# unfortunately this does not work with the default Struct.[]
def Name.[](a)
  new(*a)
end

p [
  ["John", "Doe"],
  ["John", "Cleese"],
  ["Mickey", "Mouse"],
].map(&amp;amp;Name)

# maybe a bit better:
def Name.create(a)
  new(*a)
end

p [
  ["John", "Doe"],
  ["John", "Cleese"],
  ["Mickey", "Mouse"],
].map(&amp;amp;Name.to_proc(:create))
&lt;/pre&gt;
&lt;p&gt;I hope you had some fun reading this and more importantly playing around yourself.  Trying out all things will certainly help you discover new ways and improve your skills.&lt;/p&gt;
&lt;p&gt;As usually I have placed the &lt;a href="http://gist.github.com/317580"&gt;code at github&lt;/a&gt; .  If you look at it, please don&amp;#8217;t get yourself hung up on the regular expression for matching email addresses.  This is a whole topic of its own and I just hacked something together to make the code work.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Sun, 28 Feb 2010 13:32:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/020-Code_Massage.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/020-Code_Massage.html</guid></item><item><title>Ruby Tuesdays: RBP Chapter 5</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;h3&gt;Progress To Date&lt;/h3&gt;
&lt;p&gt;We&amp;#8217;ve already released the first four chapters, and discussion has been great.  Be sure to check out these previous posts if you haven&amp;#8217;t already:&lt;br /&gt;
&lt;ul&gt;&lt;br /&gt;
   &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;Chapter 1: Driving Code Through Tests&lt;/a&gt;&lt;/li&gt;,&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;Chapter 2: Designing Beautiful &lt;span class="caps"&gt;APIS&lt;/span&gt; / Chapter 3: Mastering the Dynamic Toolkit&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;
  &lt;li&gt;&lt;a href="http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html"&gt;Chapter 4: Text Processing and File Management&lt;/a&gt;&lt;/li&gt;&lt;/p&gt;
&lt;/ul&gt;

&lt;p&gt;These discussions should give you a sense of the wide range of ideas our readers have been sharing as a result of this ongoing book study.&lt;/p&gt;
&lt;h3&gt;How To Read &lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Readers are encouraged to &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;fight &lt;span class="caps"&gt;RBP&lt;/span&gt; as they read it&lt;/a&gt;, rather than just soaking up the information.  Although I claim this book is about &amp;#8220;Best Practices&amp;#8221;, the only reason that is true is that it&amp;#8217;s a result of countless conversations with folks who are deep in the Ruby trenches getting stuff done.  The only way for &lt;span class="caps"&gt;RBP&lt;/span&gt; to remain current and relevant is to continue these discussions, using its content as a jumping off point for fresh ideas.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re willing to participate in the discussion afterwards, go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch05.pdf"&gt;download Chapter 5 now&lt;/a&gt;.  Don&amp;#8217;t worry if it takes you more than a few days finish reading it, you can come back and comment any time.&lt;/p&gt;
&lt;p&gt;This chapter was supposed to be my &amp;#8220;fun&amp;#8221; topic, but turned out to be more practical than I expected.  I had originally started out writing about how to do functional programming in Ruby, but later realized that was an incredibly bad idea.   Ruby isn&amp;#8217;t a great functional programming language, but certain functional programming techniques do still pay off.  This chapter is about those techniques.&lt;/p&gt;
&lt;p&gt;Enjoy, and come back next Tuesday (2010.03.02) for Chapter 6, &amp;#8220;When Things Go Wrong&amp;#8221;.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet.  So if you like what you see, and want to be able to read it all now instead of waiting several more weeks for it, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  While I do make a little more money when you buy from O&amp;#8217;Reilly, I wasn&amp;#8217;t expecting to get rich off of &lt;span class="caps"&gt;RBP&lt;/span&gt;, so don&amp;#8217;t feel bad buying the discounted copies from Amazon.  But I&amp;#8217;m pretty sure that seeing a spike in sales would encourage them to do more open source books, so&amp;#8230; keep that in mind.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 23 Feb 2010 15:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/019-rbp-ch5.html</guid></item><item><title>The Complete Numeric Class</title><description>&lt;p&gt;As announced in the &lt;a href="018-Complete_Class.html"&gt;previous article&lt;/a&gt; we will look at a complete number class today.  I will use the example of a integer number which, when printed, will show up as hex number (as opposed to the decimal presentation of &lt;code&gt;Fixnum&lt;/code&gt; and relatives).  As before the main point is not sophisticated logic or usefulness of the class.  Instead I will keep the logic simple so we can focus on the aspects I try to convey with today&amp;#8217;s article:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;conversions into &lt;code&gt;HexNum&lt;/code&gt;&lt;/li&gt;
	&lt;li&gt;conversions of &lt;code&gt;HexNum&lt;/code&gt; to other types&lt;/li&gt;
	&lt;li&gt;equivalence vs. comparability&lt;/li&gt;
	&lt;li&gt;type coercion&lt;/li&gt;
	&lt;li&gt;math and operator overloading&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For completeness reasons other aspects mentioned in the previous article will be implemented as well but I won&amp;#8217;t discuss them in detail here.&lt;/p&gt;
&lt;h3&gt;Conversions into &lt;code&gt;HexNum&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The first step into the world of &lt;code&gt;HexNum&lt;/code&gt; is creation of a new object of course.  This part is not that much interesting and so I will only gloss over the implementation.  I have provided a few ways:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;constructor&lt;/li&gt;
	&lt;li&gt;conversion methods (&lt;code&gt;to_hex&lt;/code&gt;),&lt;/li&gt;
	&lt;li&gt;explicit method (similar to &lt;code&gt;Integer()&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are shown in the code snippet below:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class HexNum &amp;lt; Numeric

  # Create a new instance from an int or String.
  def initialize(val)
    case val
    when String
      @i = parse_string(val)
      @s = val.frozen? ? val : val.dup.freeze
    when Numeric
      @i = val.to_i
    else
      raise ArgumentError, 'Cannot convert %p' % val
    end
  end

end

# more conversions

def HexNum(i)
  HexNum.new(Integer(i))
end

class Object
  def to_hex
    HexNum.new(to_i)
  end
end
&lt;/pre&gt;
&lt;p&gt;As you can see, a &lt;code&gt;HexNum&lt;/code&gt; consists of an integer value and optionally a &lt;code&gt;String&lt;/code&gt;.  The integer value is the mandatory part which will be used in most methods while the &lt;code&gt;String&lt;/code&gt; is just an helper intended to make conversions to &lt;code&gt;String&lt;/code&gt; more efficient (I did not make any measurements though &amp;#8211; I mainly wanted to make the class a tad more interesting).&lt;/p&gt;
&lt;p&gt;Method &lt;code&gt;Object.to_hex&lt;/code&gt; is based on the presence of method &lt;code&gt;to_i&lt;/code&gt;.  This is debatable.  Basing this conversion on method &lt;code&gt;to_int&lt;/code&gt; is as reasonable &lt;span class="caps"&gt;IMHO&lt;/span&gt;.  As you can see, the set of classes which implement &lt;code&gt;to_i&lt;/code&gt; differs from those which implement &lt;code&gt;to_int&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):002:0&amp;gt; s1 = []; s2 = []
=&amp;gt; []
irb(main):003:0&amp;gt; ObjectSpace.each_object(Module) do |m|
irb(main):004:1* s1 &amp;lt;&amp;lt; m if m.instance_methods.include? :to_i
irb(main):005:1&amp;gt; s2 &amp;lt;&amp;lt; m if m.instance_methods.include? :to_int
irb(main):006:1&amp;gt; end
=&amp;gt; 407
irb(main):007:0&amp;gt; s1
=&amp;gt; [Complex, Rational, Process::Status, Time, File, ARGF.class, IO, Bignum, Float, Fixnum, Integer, String, NilClass]
irb(main):008:0&amp;gt; s2
=&amp;gt; [Complex, Rational, Bignum, Float, Fixnum, Integer, Numeric]
&lt;/pre&gt;
&lt;p&gt;The rationale behind this is that only types which can be used as integers should implement &lt;code&gt;to_int&lt;/code&gt;.  Method &lt;code&gt;to_i&lt;/code&gt; is merely a conversion method which turns &amp;#8220;something&amp;#8221; into an int.  I chose to base &lt;code&gt;to_hex&lt;/code&gt; on &lt;code&gt;to_i&lt;/code&gt; because this increases the number of cases where you can immediately use a &lt;code&gt;HexNum&lt;/code&gt;.  If you need more strict argument checks, you can use &lt;code&gt;HexNum()&lt;/code&gt; (the method) which is modeled similar to &lt;code&gt;Integer()&lt;/code&gt; and in fact uses it internally in order to benefit from its argument checking.&lt;/p&gt;
&lt;p&gt;You might have expected &lt;code&gt;HexNum&lt;/code&gt; to inherit &lt;code&gt;Integer&lt;/code&gt;.  Actually, that&amp;#8217;s what I would have done, too.  But, it turns out, if you make a class inherit &lt;code&gt;Integer&lt;/code&gt; you cannot create instances of it any more:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):007:0&amp;gt; class X &amp;lt; Integer
irb(main):008:1&amp;gt; end
=&amp;gt; nil
irb(main):009:0&amp;gt; X.new
NoMethodError: undefined method `new' for X:Class
        from (irb):9
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'
irb(main):010:0&amp;gt; class X;end
=&amp;gt; nil
irb(main):011:0&amp;gt; def X.new; allocate; end
=&amp;gt; nil
irb(main):012:0&amp;gt; X.new
TypeError: allocator undefined for X
        from (irb):11:in `allocate'
        from (irb):11:in `new'
        from (irb):12
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'
irb(main):013:0&amp;gt; Integer.class
=&amp;gt; Class
irb(main):014:0&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This is a bit unfortunate since &lt;code&gt;Integer&lt;/code&gt; would be the proper base class for our &lt;code&gt;HexNum&lt;/code&gt;.  Inheriting &lt;code&gt;Numeric&lt;/code&gt; is the second best we can do.&lt;/p&gt;
&lt;h3&gt;Conversions to other types&lt;/h3&gt;
&lt;p&gt;These conversions are done by the typical set of &lt;code&gt;to_xyz&lt;/code&gt; methods:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # conversions

  def to_s
    @s ||= (@i &amp;lt; 0 ? '-0x%x' % -@i : '0x%x' % @i).freeze
  end

  def to_i
    @i
  end

  alias to_int to_i

  def to_hex
    self
  end
&lt;/pre&gt;
&lt;p&gt;Please note that for efficiency reasons class &lt;code&gt;HexNum&lt;/code&gt; also contains a method &lt;code&gt;to_hex&lt;/code&gt;.  Other than that there are really no surprises here.  Conversion to string may look a bit complicated but it&amp;#8217;s really just the different treatment of negative and positive values plus caching of the converted &lt;code&gt;String&lt;/code&gt;.  The #freeze just ensures that changes of the cached value outside the class cannot backfire.  If we weren&amp;#8217;t using &lt;code&gt;#freeze&lt;/code&gt; here, we would have to create a new &lt;code&gt;String&lt;/code&gt; instance for every &lt;code&gt;to_s&lt;/code&gt; invocation which would defy the whole point of caching the value.&lt;/p&gt;
&lt;h3&gt;Mutability&lt;/h3&gt;
&lt;p&gt;An important point to note is that the class is immutable.  While this is not mandatory creating a mutable class does not blend well with how Ruby handles arithmetic operators.  If you implement operator + as in place modification you will get all the issues typically caused by aliasing, i.e. using the same instance from different places in code.  As they say, &amp;#8220;When in Rome do as the Romans do&amp;#8221; &amp;#8211; so we will stick with the convention used throughout Ruby&amp;#8217;s core library and make our &lt;code&gt;HexNum&lt;/code&gt; immutable too.  That way we can use instances of &lt;code&gt;HexNum&lt;/code&gt; where we would otherwise have used &lt;code&gt;Fixnums&lt;/code&gt; or &lt;code&gt;Bignums&lt;/code&gt;.  And after all this was the aim of the exercise: to demonstrate how to create a class that seemlessly blends with all the other numeric types of Ruby&amp;#8217;s core and standard library.&lt;/p&gt;
&lt;h3&gt;Equivalence vs. Comparability&lt;/h3&gt;
&lt;p&gt;Now we slowly get to the more interesting topics.  Every class has comparison for equivalence through method &lt;code&gt;#eql?&lt;/code&gt; and operator &lt;code&gt;==&lt;/code&gt; (see also the discussion of the topic in the &lt;a href="018-Complete_Class.html"&gt;previous article&lt;/a&gt;).  For seamless blending of &lt;code&gt;HexNum&lt;/code&gt; with other numeric types comparison with &lt;code&gt;==&lt;/code&gt; should only look at the numerical value so that &lt;code&gt;HexNum(1)&lt;/code&gt; and &lt;code&gt;1.0&lt;/code&gt; compare &lt;code&gt;true&lt;/code&gt;.  However since we do not have influence on &lt;code&gt;Fixnum's&lt;/code&gt; and &lt;code&gt;Float's&lt;/code&gt; implementation of &lt;code&gt;===&lt;/code&gt; and since equivalence is a symmetric relation (i.e. &lt;code&gt;a == b&lt;/code&gt; must return the same as &lt;code&gt;b == a&lt;/code&gt;) we can only establish equivalence with other &lt;code&gt;HexNum&lt;/code&gt; instances.  I think this is unfortunate.  I can only speculate about Matz&amp;#8217;s reasons to not use &lt;code&gt;#coerce&lt;/code&gt; in this situation: I assume he did it this way for performance reasons since these types of comparisons are very frequent in a program.&lt;/p&gt;
&lt;p&gt;So, this is how equivalence checking code looks like:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # equivalence

  def eql?(num)
    self.class.equal?(num.class) &amp;amp;&amp;amp; @i == num.to_i
  end

  alias == eql?
&lt;/pre&gt;
&lt;p&gt;No big surprises here.  You&amp;#8217;ll note the type check which is necessary because of the aforementioned implementation details of core classes.&lt;/p&gt;
&lt;p&gt;Things stand dramatically different with respect to comparison operator &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt;.  The definition of this operator&amp;#8217;s semantics was nicely presented by Marc in &lt;a href="http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html#comment-21155640"&gt;his comments&lt;/a&gt; to the last article.  Basically, &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; must return &lt;code&gt;nil&lt;/code&gt; if classes of compared instances are differnt.  But what is this?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; 1 &amp;lt;=&amp;gt; 1.0
=&amp;gt; 0
irb(main):002:0&amp;gt; 1 &amp;lt;=&amp;gt; 1.5
=&amp;gt; -1
irb(main):003:0&amp;gt; 0.5 &amp;lt;=&amp;gt; 1
=&amp;gt; -1
irb(main):004:0&amp;gt; 0.5 &amp;lt;=&amp;gt; 1 &amp;lt;&amp;lt; 40
=&amp;gt; -1
irb(main):005:0&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Numeric classes allow for comparison across a wide range ot types.  Can we make &lt;code&gt;HexNum&lt;/code&gt; blend in here?  It turns out, that we can.  This is the time to introduce a functionality that took me a while understand initially.  But this is at the heart of Ruby&amp;#8217;s operator overloading and probably the single most important point to consider when implementing numeric types.&lt;/p&gt;
&lt;h3&gt;What&amp;#8217;s this &lt;code&gt;#coerce&lt;/code&gt; thingy?&lt;/h3&gt;
&lt;p&gt;When talking about equivalence it might have occurred to you that the behavior of &lt;code&gt;==&lt;/code&gt; should depend not on a single class but actually on the type of &lt;em&gt;both&lt;/em&gt; arguments.  The rule whether two objects are equivalent include&amp;#8217;s both object&amp;#8217;s class and statements about state of both instances (in case of &lt;code&gt;HexNum&lt;/code&gt; for example, both must have the same integer value).  Now, Ruby &amp;#8211; like many object oriented languages &amp;#8211; has &amp;#8216;single &lt;a href="http://en.wikipedia.org/wiki/Dynamic_dispatch"&gt;dispatch&lt;/a&gt;&amp;#8217; which means only the type of the receiver (the object to the left of the dot in a method call or &lt;code&gt;self&lt;/code&gt;) determines which method is actually used.  This works remarkably well most of the time but there are cases where you rather want to make the dispatch (and thus the decision which code is executed) depend on the receiver and one or more of the method&amp;#8217;s arguments.  Binary operators are a typical case of this.&lt;/p&gt;
&lt;p&gt;The usual solution in other languages is to overload a method based on argument types and in Ruby you would likely employ some form of type checking similar to what I have done in &lt;code&gt;HexNum's&lt;/code&gt; method &lt;code&gt;#initialize&lt;/code&gt;.  However, this approach has a fundamental drawback: when writing class A the author must know all classes B, C and D that are used as argument types.  This hurts extensibility seriously since for every new numeric type the code of older types needs adjustment.  While this would be possible due to Ruby&amp;#8217;s dynamic nature this is on the one hand tedious and it would have performance implications on the other hand because you would likely be implementing those &amp;#8220;enahancements&amp;#8221; in Ruby (and not C) and methods would have to check for more and more types.&lt;/p&gt;
&lt;p&gt;Ruby&amp;#8217;s solution to this is very elegant (as many other aspects of the language): whenever a methods receives a type different from its own type it asks that type to do a conversion so the operation can finally be handled.  It does that via method &lt;code&gt;#coerce&lt;/code&gt; which receives the &lt;em&gt;caller&lt;/em&gt; as argument so the other (presumably newer) type can find an adequate conversion.  That way, only types written later need to know about older types (e.g. everything in the core and standard library).  Let&amp;#8217;s look at how &lt;code&gt;#coerce&lt;/code&gt; works by using it on some standard types:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; 1.coerce 2
=&amp;gt; [2, 1]
irb(main):002:0&amp;gt; 2.0.coerce 1
=&amp;gt; [1.0, 2.0]
irb(main):003:0&amp;gt; 1.coerce 2.0
=&amp;gt; [2.0, 1.0]
&lt;/pre&gt;
&lt;p&gt;The result of invoking &lt;code&gt;#coerce&lt;/code&gt; has two interesting properties:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;The types of returned values are identical.&lt;/li&gt;
	&lt;li&gt;The return value is really an &lt;code&gt;Array&lt;/code&gt; with the order reversed compared to the invocation (the receiver is the &lt;em&gt;second&lt;/em&gt; object in the array).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;While we immediately see the usefulness of 1 (every class should know how to handle instances of itself) the second property irritated me at first.  But it does make sense if you consider that the argument to &lt;code&gt;#coerce&lt;/code&gt; is really the original receiver of the method call.&lt;/p&gt;
&lt;p&gt;I don&amp;#8217;t want to hide some inconsistencies of the standard functionality from you:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):004:0&amp;gt; 1.coerce 1&amp;lt;&amp;lt;40
=&amp;gt; [1099511627776.0, 1.0]
irb(main):005:0&amp;gt; (1&amp;lt;&amp;lt;40).coerce 2
=&amp;gt; [2, 1099511627776]
irb(main):006:0&amp;gt; (1&amp;lt;&amp;lt;40).coerce 3.0
TypeError: can't coerce Float to Bignum
        from (irb):6:in `coerce'
        from (irb):6
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'
irb(main):007:0&amp;gt; 3.0.coerce 1&amp;lt;&amp;lt;40
=&amp;gt; [1099511627776.0, 3.0]
irb(main):008:0&amp;gt; 1&amp;lt;&amp;lt;40
=&amp;gt; 1099511627776
irb(main):009:0&amp;gt; (1&amp;lt;&amp;lt;40) + 3.0
=&amp;gt; 1099511627779.0
&lt;/pre&gt;
&lt;p&gt;You can add &lt;code&gt;Bignum&lt;/code&gt; and &lt;code&gt;Float&lt;/code&gt; but &lt;code&gt;#coerce&lt;/code&gt; fails on one direction.  If anybody can provide a sensible explanation of this please let us know.  For the moment I am inclined to believe that it&amp;#8217;s due to the fact that implementations of core types are done in C and there are probably some corners cut.&lt;/p&gt;
&lt;p&gt;Now look at a simple example which demonstrates the mechanics of &lt;code&gt;#coerce&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
$ ruby19 &amp;lt;&amp;lt;CODE
&amp;gt; a = 1
&amp;gt; b = Object.new
&amp;gt; def b.coerce(x) [x,2] end
&amp;gt; p b
&amp;gt; set_trace_func lambda {|*a| p a}
&amp;gt; puts a + b
&amp;gt; CODE
#&amp;lt;Object:0x10028284&amp;gt;
["c-return", "-", 5, :set_trace_func, #&amp;lt;Binding:0x10027dd0&amp;gt;, Kernel]
["line", "-", 6, nil, #&amp;lt;Binding:0x10027adc&amp;gt;, nil]
["c-call", "-", 6, :+, #&amp;lt;Binding:0x10027724&amp;gt;, Fixnum]
["call", "-", 3, :coerce, #&amp;lt;Binding:0x1002721c&amp;gt;, #&amp;lt;Object:0x10028284&amp;gt;]
["line", "-", 3, :coerce, #&amp;lt;Binding:0x10026e48&amp;gt;, #&amp;lt;Object:0x10028284&amp;gt;]
["return", "-", 3, :coerce, #&amp;lt;Binding:0x10026924&amp;gt;, #&amp;lt;Object:0x10028284&amp;gt;]
["c-call", "-", 6, :+, #&amp;lt;Binding:0x100263e4&amp;gt;, Fixnum]
["c-return", "-", 6, :+, #&amp;lt;Binding:0x10025fbc&amp;gt;, Fixnum]
["c-return", "-", 6, :+, #&amp;lt;Binding:0x10025a28&amp;gt;, Fixnum]
["c-call", "-", 6, :puts, #&amp;lt;Binding:0x10025424&amp;gt;, Kernel]
["c-call", "-", 6, :puts, #&amp;lt;Binding:0x10024f54&amp;gt;, IO]
["c-call", "-", 6, :to_s, #&amp;lt;Binding:0x10024854&amp;gt;, Fixnum]
["c-return", "-", 6, :to_s, #&amp;lt;Binding:0x10023db8&amp;gt;, Fixnum]
["c-call", "-", 6, :write, #&amp;lt;Binding:0x10023878&amp;gt;, IO]
3["c-return", "-", 6, :write, #&amp;lt;Binding:0x10022f9c&amp;gt;, IO]
["c-call", "-", 6, :write, #&amp;lt;Binding:0x10022ae8&amp;gt;, IO]

["c-return", "-", 6, :write, #&amp;lt;Binding:0x10022768&amp;gt;, IO]
["c-return", "-", 6, :puts, #&amp;lt;Binding:0x1002227c&amp;gt;, IO]
["c-return", "-", 6, :puts, #&amp;lt;Binding:0x10021b0c&amp;gt;, Kernel]
&lt;/pre&gt;
&lt;p&gt;As you can see in line 6 &lt;code&gt;Fixnum's&lt;/code&gt; operator &lt;code&gt;+&lt;/code&gt; is invoked.  Since &lt;code&gt;Fixnum&lt;/code&gt; does not know how to add an &lt;code&gt;Object&lt;/code&gt; it invokes its &lt;code&gt;#coerce&lt;/code&gt;.  For simplicity reasons we always return a fixed value of 2 for the &lt;code&gt;Object&lt;/code&gt; instance and as you can see &lt;code&gt;Fixnum's&lt;/code&gt; operator &lt;code&gt;+&lt;/code&gt; is invoked again and now returns immediately.  The final result is properly calculated as 3.&lt;/p&gt;
&lt;p&gt;Now let&amp;#8217;s look at &lt;code&gt;HexNum's&lt;/code&gt; method &lt;code&gt;#coerce&lt;/code&gt; given the long introduction it looks surprisingly simple:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # coercion

  def coerce(o)
    [HexNum.new(o.to_int), self]
  end

  # comparability

  include Comparable

  def &amp;lt;=&amp;gt;(o)
    case o
    when HexNum
      @i &amp;lt;=&amp;gt; o.to_i
    when Numeric
      @i &amp;lt;=&amp;gt; o
    else
      a, b = o.coerce(self)
      a &amp;lt;=&amp;gt; b
    end rescue nil
  end
&lt;/pre&gt;
&lt;p&gt;We just try to create a new &lt;code&gt;HexNum&lt;/code&gt; if the other type can be converted to an integer and go from there.  In other cases you might have to check argument types to apply specific conversions but for our &lt;code&gt;HexNum&lt;/code&gt; this is enough to ensure functionality.&lt;/p&gt;
&lt;p&gt;Now you can also see how comparison works for &lt;code&gt;HexNum&lt;/code&gt;: if the type is known we rely on comparison functionality of the standard library.  And in order to make &lt;code&gt;HexNum&lt;/code&gt; also work with classes written later &lt;code&gt;#coerce&lt;/code&gt; is invoked on all other arguments.  A last detail: if &lt;code&gt;#coerce&lt;/code&gt; fails it is supposed to throw an exception.  Since the contract of &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; prohibits that we add a &lt;code&gt;rescue nil&lt;/code&gt; so we always end up with a proper comparison result.&lt;/p&gt;
&lt;h3&gt;Math and Operator Overloading&lt;/h3&gt;
&lt;p&gt;Now that we understand which role &lt;code&gt;#coerce&lt;/code&gt; plays in Ruby&amp;#8217;s operator land we can implement all the operators available in a way as to ensure we always get proper results.  In our case this means, we always want to have a &lt;code&gt;HexNum&lt;/code&gt; result with proper int math.&lt;/p&gt;
&lt;p&gt;There is one thing that we need to ensure for all operators: they must handle their own type directly.  If we fail to do that, we may end up in infinite recursion:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; class X
irb(main):002:1&amp;gt;   def +(o)
irb(main):003:2&amp;gt;     case o
irb(main):004:3&amp;gt;     when Integer
irb(main):005:3&amp;gt;       o + 1
irb(main):006:3&amp;gt;     else
irb(main):007:3*       a, b = o.coerce(self)
irb(main):008:3&amp;gt;       a + b
irb(main):009:3&amp;gt;     end
irb(main):010:2&amp;gt;   end
irb(main):011:1&amp;gt;
irb(main):012:1*   def coerce(o)
irb(main):013:2&amp;gt;     [X.new, self]
irb(main):014:2&amp;gt;   end
irb(main):015:1&amp;gt; end
=&amp;gt; nil
irb(main):016:0&amp;gt; x = X.new
=&amp;gt; #&amp;lt;X:0x10145c50&amp;gt;
irb(main):017:0&amp;gt; x + 1
=&amp;gt; 2
irb(main):018:0&amp;gt; 1 + x
SystemStackError: stack level too deep
        from (irb):7:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
... 7229 levels...
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):18:in `+'
        from (irb):18
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'irb(main):019:0&amp;gt; x + x
SystemStackError: stack level too deep
        from (irb):7:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
... 7229 levels...
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):8:in `+'
        from (irb):19
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'irb(main):020:0&amp;gt;
irb(main):021:0*
&lt;/pre&gt;
&lt;p&gt;So let&amp;#8217;s look at operator &lt;code&gt;+&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def +(o)
    case o
    when Integer
      HexNum.new(@i + o)
    when Numeric
      HexNum.new(@i + o.to_i)
    else
      a, b = o.coerce(self)
      a + b
    end
  end
&lt;/pre&gt;
&lt;p&gt;We know that all &lt;code&gt;Integer&lt;/code&gt; instances do return an &lt;code&gt;Integer&lt;/code&gt; instance from their implementation of operator &lt;code&gt;+&lt;/code&gt; so we can simply use that on our instance varible containing the numerical value.  For all other &lt;code&gt;Numeric&lt;/code&gt; instances (including &lt;code&gt;HexNum&lt;/code&gt; itself) we can work with the instance value converted to int.  All others are responsible for returning appropriate values for themself and the &lt;code&gt;HexNum&lt;/code&gt; instance so the math can work properly.&lt;/p&gt;
&lt;p&gt;Operator &lt;code&gt;*&lt;/code&gt; works a bit differently because for proper results of multiplication we need to use the numeric value as isand convert later:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def *(o)
    case o
    when HexNum
      HexNum.new(@i * o.to_i)
    when Numeric
      HexNum.new(@i * o)
    else
      a, b = o.coerce(self)
      a * b
    end
  end
&lt;/pre&gt;
&lt;p&gt;Of course we could refactor common parts into an operator implementing method but I did not want to get too fancy here and rather demonstrate how particular math operations might need different treatment.  For other operators we rely on the argument&amp;#8217;s compatibility to an integer since other types do not really make sense here:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # asymmetric binary operators

  def &amp;lt;&amp;lt;(o)
    HexNum.new(@i &amp;lt;&amp;lt; o.to_int)
  end

  # bit operators

  def &amp;amp;(o)
    HexNum.new(@i &amp;amp; o.to_int)
  end
&lt;/pre&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;We have seen how a numeric class needs to be implemented differently from &lt;a href="018-Complete_Class.html"&gt;other classes&lt;/a&gt; that try to be complete.  The major point is to provide &lt;code&gt;#coerce&lt;/code&gt; with meaningful semantics and implement all operators.  As always you can find the complete code &lt;a href="http://gist.github.com/309694"&gt;at github&lt;/a&gt;.  Have fun playing around with it!&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Sat, 20 Feb 2010 14:25:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/019-Complete_Numeric_Class.html</guid></item><item><title>Ruby Tuesdays: RBP Chapter 4</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;h3&gt;Progress To Date&lt;/h3&gt;
&lt;p&gt;We&amp;#8217;ve already released the first three chapters, and discussion has been great.  If you haven&amp;#8217;t seen them already, check out the first week&amp;#8217;s &lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;discussion on testing&lt;/a&gt;, and then head over and look at the &lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;double header on &lt;span class="caps"&gt;API&lt;/span&gt; design and metaprogramming&lt;/a&gt;.  These discussions should give you a sense of the wide range of ideas our readers have been sharing as a result of this book study.&lt;/p&gt;
&lt;h3&gt;How To Read &lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;Readers are encouraged to &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;fight &lt;span class="caps"&gt;RBP&lt;/span&gt; as they read it&lt;/a&gt;, rather than just soaking up the information.  Although I claim this book is about &amp;#8220;Best Practices&amp;#8221;, the only reason that is true is that it&amp;#8217;s a result of countless conversations with folks who are deep in the Ruby trenches getting stuff done.  The only way for &lt;span class="caps"&gt;RBP&lt;/span&gt; to remain current and relevant is to continue these discussions, using its content as a jumping off point for fresh ideas.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re willing to participate in the discussion afterwards, go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch04.pdf"&gt;download Chapter 4 now&lt;/a&gt;.  Don&amp;#8217;t worry if it takes you more than a few days finish reading it, you can come back and comment any time.&lt;/p&gt;
&lt;p&gt;While chapters 2 and 3 were about somewhat subtle features, this chapter is as concrete as they come.  Those with some Perl blood in them should find it familiar, as it&amp;#8217;s all about how to munge text and move stuff around on your filesystem.  But those who struggle with the scripting side of Ruby should find a number of techniques that will make their job easier.&lt;/p&gt;
&lt;p&gt;Enjoy, and come back next Tuesday (2010.02.23) for Chapter 5, &amp;#8220;Functional Programming Techniques&amp;#8221;.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet.  So if you like what you see, and want to be able to read it all now instead of waiting several more weeks for it, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  While I do make a little more money when you buy from O&amp;#8217;Reilly, I wasn&amp;#8217;t expecting to get rich off of &lt;span class="caps"&gt;RBP&lt;/span&gt;, so don&amp;#8217;t feel bad buying the discounted copies from Amazon.  But I&amp;#8217;m pretty sure that seeing a spike in sales would encourage them to do more open source books, so&amp;#8230; keep that in mind.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 16 Feb 2010 15:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/018-rbp-ch4.html</guid></item><item><title>RBP is useless without you</title><description>&lt;p&gt;&lt;em&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt; 2010.02.13: Lots of folks have taken the initiative to comment after reading this, and others have pointed out that they indeed need more time before they can comment.  But since people seem generally interested in seeing Ch4 sooner rather than later, I&amp;#8217;ll release it on Tuesday.  Coincidentally, there is a great post I found on HN that does a better job than I did summarizing how tech books (especially &lt;span class="caps"&gt;RBP&lt;/span&gt;) ought to be read.  If you haven&amp;#8217;t seen it yet, go read &lt;a href="http://jsomers.net/blog/kenjitsu"&gt;Kenjitsu&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Since I&amp;#8217;ve posted the &lt;a href="http://github.com/sandal/rbp-book/tree/gh-pages/pdfs/"&gt;first three chapters&lt;/a&gt;, my amazon ratings have gone way up, and I&amp;#8217;ve seen lots of people mention the book on twitter.  This is great for marketing, but as you may know, I care much more about the actual content here.&lt;/p&gt;
&lt;p&gt;Things started out great!  We had an &lt;a href="http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;awesome discussion about testing&lt;/a&gt; two weeks ago and I expected to see the same on &lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;APIs and metaprogramming&lt;/a&gt;.  But as it turned out, only two brave souls offered up their thoughts, even though lots of people downloaded the content.  That was a big disappointment to me, and now I&amp;#8217;m trying to guess at what went wrong.&lt;/p&gt;
&lt;p&gt;One possibility is that I&amp;#8217;ve oversaturated folks, so I&amp;#8217;m giving everyone an extra week to &lt;a href="http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html"&gt;comment on Ch2-3&lt;/a&gt; before I put out the &amp;#8220;Text Processing and File Management&amp;#8221; chapter.  Hopefully, by next Friday we&amp;#8217;ll have a good discussion going there, and the Ch4 release will just keep the ball rolling.&lt;/p&gt;
&lt;p&gt;But far more grave, is my fear that some folks might be too timid to express their thoughts about the material, perhaps because it&amp;#8217;s in book form rather than written up in some generic blog post.  This to me, is exactly what will prevent them from getting anything worthwhile out of my book.  So if you&amp;#8217;ve been holding back comments just because you didn&amp;#8217;t want to challenge RBP&amp;#8217;s &amp;#8220;bookiness&amp;#8221; out in the open, please don&amp;#8217;t.  I can handle all sorts of criticism, and the book will benefit as a result of it.&lt;/p&gt;
&lt;p&gt;I am very serious about the idea that &amp;#8220;Best Practices&amp;#8221; really don&amp;#8217;t have much value in a vacuum. I&amp;#8217;m certain that the benefits that my book can offer its readers are maximized in open conversation.  This is why I made sure to build an eventual open content licensing into RBP&amp;#8217;s contract, and why I&amp;#8217;m releasing free chapters now.&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;RBP&lt;/span&gt; is useless without you, so please, participate.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 12 Feb 2010 05:24:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/017-rbp-useless.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/017-rbp-useless.html</guid></item><item><title>Weekend Reading: RBP Chapters 2-3</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;p&gt;If you missed &lt;a href="http://www.blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html"&gt;last week&amp;#8217;s post&lt;/a&gt;, which introduces chapter 1, you&amp;#8217;ll want to check that out.  There was some great discussion among readers that add a lot to what I had to say in the book.  I expect we&amp;#8217;ll see the same thing happen this time around.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topics&lt;/h3&gt;
&lt;p&gt;This week, I&amp;#8217;m releasing two chapters, &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch02.pdf"&gt;Designing Beautiful APIs&lt;/a&gt; and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch03.pdf"&gt;Mastering the Dynamic Toolkit&lt;/a&gt;.  Incase the latter sounds familiar, it is indeed the book&amp;#8217;s sample chapter.  But it also happens to be my favorite chapter in the book, so I didn&amp;#8217;t want to skip over it without a chance for discussion.&lt;/p&gt;
&lt;p&gt;So remember, if you click those links, your responsibility is to participate in the discussion here by offering up your thoughts about what you&amp;#8217;ve read.  Best practices cannot be rules that are simply absorbed and followed if they are to be of any use&amp;#8230; instead, they must be extracted from and influenced by those who work with the real problems that they are meant to solve.&lt;/p&gt;
&lt;p&gt;It would be great to hear your experiences with the topics these chapters cover, even if they&amp;#8217;re not directly related to the book content.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet.  So if you like what you see, and want to be able to read it all now instead of waiting eight weeks for it, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  While I do make a little more money when you buy from O&amp;#8217;Reilly, I wasn&amp;#8217;t expecting to get rich off of &lt;span class="caps"&gt;RBP&lt;/span&gt;, so don&amp;#8217;t feel bad buying the discounted copies from Amazon.  But I&amp;#8217;m pretty sure that seeing a spike in sales would encourage them to do more open source books, so&amp;#8230; keep that in mind.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Anyway that&amp;#8217;s all for now, enjoy the chapters and let me know what you think!&lt;/em&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 05 Feb 2010 14:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/rbp-ch2-3.html</guid></item><item><title>Sexp for Rubyists</title><description>&lt;p&gt;&lt;em&gt;Sorry to interrupt you, but you&amp;#8217;ve totally lost me. What &lt;strong&gt;is&lt;/strong&gt; this &amp;#8220;Sexp&amp;#8221;&lt;br /&gt;
you&amp;#8217;re speaking of? I&amp;#8217;ve heard it before, but never quite understood it&amp;#8230;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Oh, don&amp;#8217;t feel sorry!  It&amp;#8217;s still quite esoteric for Rubyists.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Yeah&amp;#8230;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Okay.  Let&amp;#8217;s start at the beginning.  Lisp!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;With all the parenthesis?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Bingo!  Have you tried it?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Not really.  It seems a little too &amp;#8220;hardcore&amp;#8221;, if you know what I mean?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Ah, yes. It&amp;#8217;s just a neat little language, nothing to be afraid of. Let me&lt;br /&gt;
show you an example:&lt;/p&gt;
&lt;pre&gt;
(define (plus-five n)
  (+ n 5))
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;It&amp;#8217;s a method that adds five to the argument?  Like this:&lt;/em&gt;&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def plus_five(n)
  n + 5
end
&lt;/pre&gt;
&lt;p&gt;Yep, but more importantly: It&amp;#8217;s also an example of S-expressions. Because Sexp&lt;br /&gt;
is really just a data format.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Data format?  Like &lt;span class="caps"&gt;YAML&lt;/span&gt;?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Just like &lt;span class="caps"&gt;YAML&lt;/span&gt;.  It has support for numbers, symbols, pairs, lists and nil.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Really?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let me explain a few more things. You see, Lisp wasn&amp;#8217;t originally supposed to&lt;br /&gt;
be programmed in S-expression. Nope, the idea was to have complex,&lt;br /&gt;
human-readable &lt;em&gt;M-expressions&lt;/em&gt; which should manipulate data in S-expressions.&lt;/p&gt;
&lt;pre&gt;
    Data  =  S-expressions
    Code  =  M-expressions
&lt;/pre&gt;
&lt;p&gt;Another idea was that M-expressions could easily be compiled into&lt;br /&gt;
S-expressions. So the computer itself would only work with S-expressions,&lt;br /&gt;
while humans could focus on M-expressions.&lt;/p&gt;
&lt;pre&gt;
    M-expressions  --&amp;gt;   S-expressions
&lt;/pre&gt;
&lt;p&gt;However, the first Lisp implementations only accepted S-expressions since it&lt;br /&gt;
was easier to start from there and rather add M-expression support later.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;So what happend with these M-expressions?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;They were &amp;#8220;receded into the indefinite future&amp;#8221; as the creator, John McCarthy,&lt;br /&gt;
said. It turned out that S-expressions were readable enough.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Go on, please.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Now Lisp suddenly used S-expressions for both code and data. The interesting&lt;br /&gt;
thing is how code was represented in Lisp. It&amp;#8217;s in fact very simple: The first&lt;br /&gt;
element in the list is the operator/function and the rest is the&lt;br /&gt;
operands/arguments:&lt;/p&gt;
&lt;pre&gt;
    (+ 1 2)
    (plus-five 5)
    (factorial 10)
&lt;/pre&gt;
&lt;p&gt;This makes Lisp a very simple language to implement. You need very few&lt;br /&gt;
primitives before you have a fully working Lisp system. In fact, I would&lt;br /&gt;
recommend watching James Coglan&amp;#8217;s screencast. There isn&amp;#8217;t any audio since he&lt;br /&gt;
used it in a talk he gave, but it&amp;#8217;s still fairy interesting.&lt;/p&gt;
&lt;p&gt;&lt;object width="581" height="421"&gt;&lt;param name="allowfullscreen" value="true" /&gt;&lt;param name="allowscriptaccess" value="always" /&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=4339116&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=00ADEF&amp;amp;fullscreen=1" /&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=4339116&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=00ADEF&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="581" height="421"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;a href="http://vimeo.com/4339116"&gt;Scheme interpreter in 15 minutes&lt;/a&gt; from &lt;a href="http://vimeo.com/jcoglan"&gt;James Coglan&lt;/a&gt; on &lt;a href="http://vimeo.com"&gt;Vimeo&lt;/a&gt;.&lt;/p&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Wow.  I must definitely check out Lisp.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Indeed. He&amp;#8217;s also written a &amp;#8220;real&amp;#8221; Lisp implementation in Ruby if you&amp;#8217;re&lt;br /&gt;
interested: &lt;a href="http://github.com/jcoglan/heist"&gt;Heist&lt;/a&gt;. Oh, and I&amp;#8217;ll also have to&lt;br /&gt;
recommend &lt;a href="http://www.ccs.neu.edu/home/matthias/BTLS/"&gt;The Little Schemer&lt;/a&gt; by&lt;br /&gt;
Daniel P. Friedman and Matthias Felleisen, it has inspired me in several&lt;br /&gt;
ways&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I will, but back to Sexp?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;No.  Let&amp;#8217;s talk about &lt;span class="caps"&gt;AST&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;span class="caps"&gt;AST&lt;/span&gt;? While &lt;strong&gt;I&lt;/strong&gt; certainly appreciate these digressions, (&lt;/em&gt;whispers_) others&lt;br /&gt;
might be a little bored, you know?_&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t worry, this is pretty essential. An Abstract Syntax Tree is a tree&lt;br /&gt;
representation of source code. Compilers and interpreters never work directly&lt;br /&gt;
on the source code, but parses it into an &lt;span class="caps"&gt;AST&lt;/span&gt; which is much easier work with.&lt;br /&gt;
Your Ruby example above could look something like:&lt;/p&gt;
&lt;pre&gt;
[Def,
  plus_five
  [n]
  [Call, n, +, [[Lit, 5]]]]
&lt;/pre&gt;
&lt;p&gt;The basic idea here is that we only deal with &lt;em&gt;nodes&lt;/em&gt; like Def, Call and Lit,&lt;br /&gt;
and every node has a set of &lt;em&gt;children&lt;/em&gt;. In this tree the nodes are built like&lt;br /&gt;
this:&lt;/p&gt;
&lt;pre&gt;
[Def, method_name, arguments, body] # =&amp;gt; def method_name(*arguments); body; end
[Lit, number]                       # =&amp;gt; (integer)
[Call, receiver, method_name, arguments] # =&amp;gt; receiver.method_name(*arguments)
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;I think I get your point.  This is very similar to S-expressions!&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;
(def plus_five (n)
  (call n + 5))
&lt;/pre&gt;
&lt;p&gt;Yes! It turns out that S-expressions are excellent to represent abstract&lt;br /&gt;
syntax trees. And when compiler gurus talk about S-expressions, they don&amp;#8217;t&lt;br /&gt;
talk about the file format, they talk about the way Lisp represent it&amp;#8217;s code:&lt;br /&gt;
The first element in the list is the operator/function and the rest are the&lt;br /&gt;
operands/arguments.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;So S-expressions themselves aren&amp;#8217;t very exciting, it all depends on what you&lt;br /&gt;
put in them?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Exactly.  The Sexp-class basically looks like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Sexp &amp;lt; Array
  def sexp_type
    self[0]
  end
  
  def sexp_body
    self[1..-1]
  end
end
&lt;/pre&gt;
&lt;p&gt;A glorified Array.  That&amp;#8217;s all there is to it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;And what do people put in these Sexps?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let me show you an example. First, &lt;code&gt;gem install ruby_parser&lt;/code&gt;. Then:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
require 'ruby_parser'
require 'pp'

pp RubyParser.new.parse(&amp;lt;&amp;lt;-EOF)
def plus_five(n)
  n + 5
end
EOF
&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;Interesting:&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;
s(:defn,
 :plus_five,
 s(:args, :n),
 s(:scope,
   s(:block,
     s(:call, s(:lvar, :n), :+, s(:arglist, s(:lit, 5))))))
&lt;/pre&gt;
&lt;p&gt;This is the &lt;em&gt;syntatic&lt;/em&gt; strucure of our code. It&amp;#8217;s not possible to reconstruct&lt;br /&gt;
the original snippet character-by-character; you only get what the&lt;br /&gt;
compiler/interpreter/virtual machine actually sees. And often that&amp;#8217;s exactly&lt;br /&gt;
the only thing we want.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Aha.  Who decided this structure and these names by the way?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Well, I&amp;#8217;m not quite certain, but I believe ParseTree by Ryan Davis started it&lt;br /&gt;
all.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Oh, ParseTree sounds familiar.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It extracts the raw &lt;span class="caps"&gt;AST&lt;/span&gt; that Ruby 1.8 uses internally. It&amp;#8217;s not very elegant,&lt;br /&gt;
so Ryan also wrote UnifiedRuby which cleans it up a bit. RubyParser returns&lt;br /&gt;
such a cleanup up Sexp.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;And what do people use these cleaned up Sexps for?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s plenty of projects floating around, here&amp;#8217;s some I&amp;#8217;ve heard of:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;a href="http://ruby.sadi.st/Flog.html"&gt;Flog&lt;/a&gt; analyzes your code and shows how complex your methods are, and which you should refactor.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://ruby.sadi.st/Flay.html"&gt;Flay&lt;/a&gt; analyzes your code for structural similarities, ready to be DRYed out!&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/martinjandrews/roodi"&gt;Roodi&lt;/a&gt; warns you about design issues.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/kevinrutherford/reek"&gt;Reek&lt;/a&gt; detects code smells.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://saikuro.rubyforge.org/"&gt;Saikuro&lt;/a&gt; is a &amp;#8220;cyclomatic complexity analyzer&amp;#8221;.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://ambition.rubyforge.org/"&gt;Ambition&lt;/a&gt; let&amp;#8217;s you write &lt;span class="caps"&gt;SQL&lt;/span&gt; statements as Ruby blocks.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/judofyr/parkaby"&gt;Parkaby&lt;/a&gt; compiles Markaby-like code into super-fast code.&lt;/li&gt;
	&lt;li&gt;&lt;a href="http://github.com/raganwald/rewrite_rails"&gt;RewriteRails&lt;/a&gt; adds syntactic abstractions (like Andand) to Rails projects without monkey-patching.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Cool, that&amp;#8217;s more than I thought.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;And if more people knew about them, I guess there would be even more.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Let me recap:&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For Rubyists, Sexp is an Array-ish list where the first element is the&lt;br /&gt;
operator/function and the rest is the operands/arguments. The arguments can&lt;br /&gt;
also contain other Sexp. When I think about it, that&amp;#8217;s probably the most&lt;br /&gt;
important thing: They are nested.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;I guess it&amp;#8217;s mostly useful when we&amp;#8217;re actually manipulating code that&lt;br /&gt;
executes. Like source code or templates?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Exactly!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Ah, excellent.  Why were we talking about Sexps again?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hm.. Now that&amp;#8217;s a good question. I simply don&amp;#8217;t remember. Let&amp;#8217;s talk about it&lt;br /&gt;
another time, shall we?&lt;/p&gt;</description><author>judofyr@gmail.com (Magnus Holm)</author><pubDate>Thu, 04 Feb 2010 21:00:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/judofyr/sexp-for-rubyists.html</link><guid>http://blog.rubybestpractices.com/posts/judofyr/sexp-for-rubyists.html</guid></item><item><title>Weekend Reading: RBP Chapter 1</title><description>&lt;p&gt;If you&amp;#8217;re reading this blog, you probably know that the &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;Ruby Best Practices&lt;/a&gt; book exists.  Even if you haven&amp;#8217;t read it, you might have a sense for the sort of topics we cover based on the content you&amp;#8217;ve seen on this blog. But now, everyone is going to get a chance to read &lt;span class="caps"&gt;RBP&lt;/span&gt; the way its meant to be read: as a conversation.&lt;/p&gt;
&lt;p&gt;For the next 8 weeks, I will post a chapter from &lt;span class="caps"&gt;RBP&lt;/span&gt; every Friday.  You don&amp;#8217;t need to pay me a cent if you download it, but what I do want you to do is leave a comment here sharing your thoughts once you&amp;#8217;ve finished reading.  This way, we can use RBP&amp;#8217;s content as a jumping off point for conversation, rather than treating it like some sort of static rulebook. Through this process, we can discover what our common practices really are.  Over time, I will incorporate these ideas back into the manuscript, helping to keep the book up to date and relevant.&lt;/p&gt;
&lt;h3&gt;Today&amp;#8217;s Topic&lt;/h3&gt;
&lt;p&gt;The first chapter I am releasing is &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch01.pdf"&gt;Driving Code Through Tests&lt;/a&gt;,  which covers a number testing philosophies and techniques.  It aims to be framework agnostic, but leans on the Test::Unit &lt;span class="caps"&gt;API&lt;/span&gt; for its examples.  The core idea of this chapter is to expose folks to the &amp;#8220;spirit&amp;#8221; of testing, rather than just the mechanics of it.&lt;/p&gt;
&lt;p&gt;Upon re-reading this chapter in the winter of 2010 having written it in the spring of 2008, there are definitely a couple things I think differently about now.  But as it turns out, I was more surprised by how much hasn&amp;#8217;t changed, and how well this chapter seems to have stood the test of time.  Of course, you may disagree, and I encourage you to tell me so if that&amp;#8217;s the case. :)&lt;/p&gt;
&lt;p&gt;Ready to get started?  Go ahead and &lt;a href="http://sandal.github.com/rbp-book/pdfs/ch01.pdf"&gt;download the chapter&lt;/a&gt; now.  Remember, if you click that link, I&amp;#8217;m expecting you to post back here with your thoughts (or alternatively, write a response on your own blog and send me a link).  If you find a technical error, you can report it via &lt;a href="http://github.com/sandal/rbp-book/issues"&gt;Github issues&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;For Your Consideration&lt;/h3&gt;
&lt;p&gt;O&amp;#8217;Reilly is being really nice to me by letting me give away my book, especially considering that I haven&amp;#8217;t quite cleared my advance yet.  So if you like what you see, and want to be able to read it all now instead of waiting eight weeks for it, please consider buying the book.  You can get it &lt;a href="http://oreilly.com/catalog/9780596523015"&gt;directly from the publisher&lt;/a&gt; or via &lt;a href="http://www.amazon.com/Ruby-Best-Practices-Gregory-Brown/dp/0596523009"&gt;amazon&lt;/a&gt;.  While I do make a little more money when you buy from O&amp;#8217;Reilly, I wasn&amp;#8217;t expecting to get rich off of &lt;span class="caps"&gt;RBP&lt;/span&gt;, so don&amp;#8217;t feel bad buying the discounted copies from Amazon.  But I&amp;#8217;m pretty sure that seeing a spike in sales would encourage them to do more open source books, so&amp;#8230; keep that in mind.&lt;/p&gt;
&lt;p&gt;For those wishing to do interesting things with this material, note that it is released under the &lt;a href="http://creativecommons.org/licenses/by-nc-sa/3.0/"&gt;Creative Commons NC-SA&lt;/a&gt; license.  This will become immensely more useful once the source documents are posted in late March, but if you&amp;#8217;ve got any questions at all about this, you can ask me, and I&amp;#8217;ll ask my publisher, and we&amp;#8217;ll get back to you.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Anyway that&amp;#8217;s all for now, enjoy the chapter and let me know what you think!&lt;/em&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 29 Jan 2010 14:32:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/015-rbp-ch1.html</guid></item><item><title>Reflections from "The Compleat Rubyist"</title><description>&lt;p&gt;Ever since 2005, I&amp;#8217;ve been attending and speaking at Ruby events.  But the one thing I always wanted to do was run training sessions.  Thankfully, over the last couple years, &lt;span class="caps"&gt;LSRC&lt;/span&gt; has allowed me to get my feet wet &amp;#8212; but only as one of many excellent choices in a lineup of Ruby&amp;#8217;s best and brightest.  Until last weekend, I had never participated in professional training event that stood on its own.&lt;/p&gt;
&lt;p&gt;What eventually became &amp;#8220;The Compleat Rubyist&amp;#8221; training, was originally an idea for &amp;#8220;The Compleat Rubyist&amp;#8221; book promotion.  Jeremy McAnally, David A. Black, and myself have all written Ruby books, and they seem to compliment each other well.  But in doing this, we realized that it would be more valuable, and more fun, to bring our show out on the open road rather than package it up in a box set.&lt;/p&gt;
&lt;p&gt;Thus, our training event was born, and we set our sights on Tampa, FL for its first incarnation.&lt;/p&gt;
&lt;h3&gt;The Training&lt;/h3&gt;
&lt;p&gt;Instead of having a linear, specific set of bullet points to teach from, we broke our training into four half-day sessions that are representive of some of the most important topics in the Ruby ecosystem.  This gave us a lot of leeway to adjust our materials and discussions based on individual student needs.   The topics we picked were &amp;#8220;Ruby Versions and Implementations&amp;#8221;, &amp;#8220;Metaprogramming&amp;#8221;, &amp;#8220;Testing&amp;#8221;, and &amp;#8220;Style and Substance&amp;#8221;.   Though these may seem a bit amorphous on first sight, they do a pretty good job of covering four key topics that a budding Rubyist must understand and come to appreciate.&lt;/p&gt;
&lt;p&gt;Here are just a few thoughts from each of the modules, after seeing how things played out in class.&lt;/p&gt;
&lt;h4&gt;Ruby Versions and Implementations&lt;/h4&gt;
&lt;p&gt;One of the main things that keep people from trying out the alternative Ruby implementations and the various versions of Ruby is that they&amp;#8217;re understandably afraid of messing up their systems.  So David took a three-pronged approach to helping students overcome that fear.&lt;/p&gt;
&lt;p&gt;The easiest stepping stone, perhaps, was to use &lt;a href="http://ruby-versions.net/"&gt;ruby-versions.net&lt;/a&gt;.  This great resource (maintained by David), lets you try out all sorts of ruby versions and implementations via a shell account so that you don&amp;#8217;t need to worry about touching anything on your own machine.  While this isn&amp;#8217;t meant to be a long term solution, it&amp;#8217;s probably the easiest way that you can try out pretty much any version of Ruby without having to go hunt down, install, and configure their packages.&lt;/p&gt;
&lt;p&gt;In addition to this, David showed folks how to make use of multiruby (a tool that&amp;#8217;s part of ZenTest).  My favorite example of the whole day was one showing that using Ruby 1.8.7, it&amp;#8217;s possible to write code that works on neither 1.8.6 nor 1.9.1, which lead into a whole other interesting discussion:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  $ multiruby -e "p 'hello'.map(&amp;amp;:upcase)"

  VERSION = 1.8.6-p388
  CMD     = ~/.multiruby/install/1.8.6-p388/bin/ruby -e p 'hello'.map(&amp;amp;:upcase)

  -e:1: wrong argument type Symbol (expected Proc) (TypeError)

  RESULT = pid 3988 exit 1

  VERSION = 1.8.7-p249
  CMD     = ~/.multiruby/install/1.8.7-p249/bin/ruby -e p 'hello'.map(&amp;amp;:upcase)

  ["HELLO"]

  RESULT = pid 3991 exit 0

  VERSION = 1.9.1-p378
  CMD     = ~/.multiruby/install/1.9.1-p378/bin/ruby -e p 'hello'.map(&amp;amp;:upcase)

  -e:1:in `&amp;lt;main&amp;gt;': undefined method `map' for "hello":String (NoMethodError)

  RESULT = pid 3995 exit 1

  TOTAL RESULT = 2 failures out of 3

  Passed: 1.8.7-p249
  Failed: 1.8.6-p388, 1.9.1-p378
&lt;/pre&gt;
&lt;p&gt;We also took a look at &lt;a href="http://rvm.beginrescueend.com/"&gt;rvm&lt;/a&gt; , which is another neat tool for managing multiple Ruby versions.  While not necessarily a tool for every possible need, it is a very easy way of managing multiple rubies side by side without trashing your system-wide configurations.&lt;/p&gt;
&lt;p&gt;Between these three tools, the students ended up with all they needed to explore the different implementations and versions for themselves.   But that was really just the beginning.   David then went on to discuss the various peculiarities across the board, and was sure to discuss where certain implementations or versions excel, and where they fall behind.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m happy to say that while very few of the students in our class had even tried Ruby 1.9 before our training, every one of them had the opportunity to do so before this session ended.&lt;/p&gt;
&lt;h4&gt;Meta-programming&lt;/h4&gt;
&lt;p&gt;At one point in time, everyone using Ruby thought meta-programming was some sort of magic.  But in a post-Rails world, it is increasingly easy to help folks understand that all of this &amp;#8220;voodoo&amp;#8221; we do is really just making use of public method calls provided by Ruby objects that allow you to modify Ruby itself.  Once a decent understanding of Ruby&amp;#8217;s object model is established, all of the rest of the puzzle pieces just seem to fall into place.&lt;/p&gt;
&lt;p&gt;This session had a lot of great discussions, and several exercises to encourage students to actively learn the tricks of the trade.   Along the way, we stumbled across this interesting distinction between &lt;tt&gt;undef_method&lt;/tt&gt; and &lt;tt&gt;remove_method&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class A
    def foo
      "bar"
    end
  end

  class B &amp;lt; A
    def foo
      "baz"
    end

    remove_method :foo
  end

  class C
    def foo 
      "bar"
    end
  end

  class D &amp;lt; C
    def foo
      "baz"
    end

    undef_method :foo
  end

  p B.new.foo # "bar"

  p D.new.foo # raise NoMethodError
&lt;/pre&gt;
&lt;h4&gt;Testing&lt;/h4&gt;
&lt;p&gt;Fortunately, virtually all of our students had experience with test driven development of some sort or another.  I think that&amp;#8217;s a big difference between the Ruby ecosystem today and of say, 5 years ago.  But similar to versions and implementations, there are so many choices out there that it&amp;#8217;s hard to know what&amp;#8217;s what.  Jeremy kicked off this module with a state of the union address, breaking down the various different philosophies and toolchains there are out there, and what each of them bring to the table.&lt;/p&gt;
&lt;p&gt;Once we got people thinking about the different options for testing out there, we decided to give them a glimpse behind the curtain to realize just how non-magical testing could be.  To do this, we demonstrated not one, but two minimal testing frameworks that we built in less than a page or two of code to demonstrate the key concepts.  While neither of these tools would be sensible to use in production, they both show how non-magical a test runner is under the hood.&lt;/p&gt;
&lt;p&gt;Finally, David gave an open ended testing exercise that was a big hit.   Pizza came, but some of our students ignored it until we reminded them to take a break.   Many kept working on through lunch, all pairing together and actively discussing all sorts of language questions that went far beyond the scope of the exercise.&lt;/p&gt;
&lt;h4&gt;Style and Substance&lt;/h4&gt;
&lt;p&gt;This was my topic, and it went way better than I could have expected it to.  I had a lot more content prepared than what I ended up getting to, mainly because we decided to collect some of the open questions that had come up in class and discuss those before running our scheduled content.  The infamous class variable problem was discussed in great detail, and while I thought I had mastered their weaknesses, I even managed to mess up one of my assumptions about their behavior.  Incase you&amp;#8217;ve never been exposed to this fun before:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class A
    @@foo = "from A"
  end
   
  class B &amp;lt; A
    @@foo = "from B"
  end
   
  # What's the value of @@foo in A now...?
   
  class A
    puts @@foo
  end
   
  # =&amp;gt; from B
   
  # They're shared up the hierarchy?? BOOOO!!!
  # What's even worse? This -&amp;gt;
   
  class C
  end
   
  class D &amp;lt; C
    @@bar = "Magically different..."
  end
   
  class C
    @@bar = "And delicious."
  end
   
  class D
    puts @@bar
    # =&amp;gt; Magically different...
  end
   
  class C
    puts @@bar
    # =&amp;gt; And delicious.
  end
   
  # ZOMG THEY'RE NOT SHARED NOW.
&lt;/pre&gt;
&lt;p&gt;Of course, the only sensible style advice here is to not use class variables at all, and since class instance variables can do the job just as well, that&amp;#8217;s not really a big deal.  We discussed how to do that, and then moved on to the regularly scheduled content.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;m not sure whether we had an especially strong set of students or if people are just starting to &amp;#8220;get&amp;#8221; basic Ruby style idioms, but based on the first day and a half, it was evident that our students didn&amp;#8217;t need to be told these basic things.   Instead, I talked about &amp;#8220;Ruby Style and Substance&amp;#8221; at a more philosophical and design-oriented level, which is where I think our community tends to be weakest.  Without giving too much away, a lot of my examples stemmed from discussions we&amp;#8217;ve been having about refactoring Prawn before it&amp;#8217;s 1.0 release, so you can check out our mailing list for a whole bunch of interesting design discussions if you want access to some of the raw materials I used for this session.&lt;/p&gt;
&lt;p&gt;In the end, we gave everyone a chance to try their hand at basic &lt;span class="caps"&gt;API&lt;/span&gt; design for a fictional library we cooked up.  I&amp;#8217;m proud to say that every one of our students produced something that would be passable in an open source project.  Ideally speaking, I&amp;#8217;d like to say some of them took inspiration from what they learned in class, but no matter how they ended up there, I&amp;#8217;m happy to see people writing code that looks like it comes from Ruby. This is especially encouraging considering that every one of our students came to Ruby after Rails was popularized.&lt;/p&gt;
&lt;h3&gt;The Event&lt;/h3&gt;
&lt;p&gt;We wanted &amp;#8220;The Compleat Rubyist&amp;#8221; to be not just a training, but an &amp;#8220;event&amp;#8221; as well.  Because we were trying to keep registration costs low, we didn&amp;#8217;t have much officially scheduled for this, but Tampa.rb really helped us pull through.  Folks congregated at the nearby bar and restaurant Bahama Breeze from the time class ended until late into the evening Friday night.   It was nice to have a mixture of students from the training and locals who just stopped by to hang out and say hi.  I can honestly say that the sort of conversations I was having that night were on par with any I&amp;#8217;ve had at the various conferences I&amp;#8217;ve been at, but without all the associated commotion.&lt;/p&gt;
&lt;p&gt;Pizza lunch on Saturday was a great way for us to leave a large chunk of semi-unscheduled time to discuss whatever topics students had on their mind.  With a relatively small class size, I was able to get to know a number of the attendees, unlike my experience at most conferences these days.&lt;/p&gt;
&lt;p&gt;While I expected to have a good time, I ended up having a blast.  Based on my discussions with Jeremy and David, and the feedback from our students, I gather most others did as well.&lt;/p&gt;
&lt;h3&gt;The Future&lt;/h3&gt;
&lt;p&gt;While the Tampa, FL Compleat Rubyist event is now a thing of the past, we&amp;#8217;re already thinking about how we can bring this session to other places.  I was a little worried before the event that I wouldn&amp;#8217;t want to just go somewhere else and do the same show, but now I know that every one of these is going to be different, since so much of the content was based on interaction with our attendees.&lt;/p&gt;
&lt;p&gt;So, if the stuff I&amp;#8217;ve said here interests you, you should follow &lt;a href=http://twitter.com/compleatrubyist&gt;compleatrubyist on twitter&lt;/a&gt;.  We used our account actively during the event to share various little tips, and probably will continue to do that over time.  But that&amp;#8217;s also the place where you&amp;#8217;ll see announcements about upcoming events, or ask us any questions you might have.&lt;/p&gt;
&lt;p&gt;While I don&amp;#8217;t typically like to use this blog for active marketing, I can honestly say that &amp;#8220;The Compleat Rubyist&amp;#8221; was a lot of fun, and that I think our students learned a ton.  If folks like these summaries, I&amp;#8217;ll try to get one out after each event.  But it will be more fun, of course, if you come join us!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Mon, 25 Jan 2010 15:36:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/014-the-compleat-rubyist.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/014-the-compleat-rubyist.html</guid></item><item><title>Learning From Bad Ideas</title><description>&lt;p&gt;When we know something is ugly or &amp;#8220;evil&amp;#8221;, we&amp;#8217;re quick to replace it with what we know to be a better solution.  But if we don&amp;#8217;t know &lt;strong&gt;why&lt;/strong&gt; the solution is better, it makes it hard for us to investigate those things that look reasonable on the surface, yet have weaknesses just beneath the skin.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll run through a quick example of what I mean, and then, it&amp;#8217;ll be your turn to run with it and report back here.  While I don&amp;#8217;t use this approach all the time, I find it&amp;#8217;s a neat tool to have handy when you&amp;#8217;re trying to push your understanding of your code just a little bit farther.&lt;/p&gt;
&lt;h3&gt;Continuations are Evil?&lt;/h3&gt;
&lt;p&gt;It&amp;#8217;s pretty common knowledge that continuations in Ruby are evil.  But let&amp;#8217;s pretend we didn&amp;#8217;t know that.  We might end up catching ourselves writing code like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  table.each do |row|
    call_cc do |next_row|
      row.each do |field|
        if field.valid?
          do_something_with(field)
        else
          STDERR.puts "skipping a bad row"
          next_row[]
        end 
      end
    end
  end
&lt;/pre&gt;
&lt;p&gt;The continuation approach actually doesn&amp;#8217;t look so bad.  All we&amp;#8217;re doing is iterating over a two-dimensional structure and skipping ahead to the next row if there is a problem with any of the fields. But having to pass along the &lt;tt&gt;next_row&lt;/tt&gt; callback seems a bit heavy handed, and also makes one wonder what sort of magic it might be concealing.  Preserving the same basic flow, we could be using &lt;tt&gt;catch&lt;/tt&gt; / &lt;tt&gt;throw&lt;/tt&gt; instead, lowering the conceptual baggage:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  table.each do |row|
    catch(:next_row) do
      row.each do |field|
        if field.valid?
          do_something_with(field)
        else
          STDERR.puts "skipping a bad row"
          throw :next_row
        end 
      end
    end
  end
&lt;/pre&gt;
&lt;p&gt;So, now, we have something that looks more-or-less like a transactional block, which gets aborted when you throw &lt;tt&gt;:next_row&lt;/tt&gt;.  Not too bad, but if you&amp;#8217;re like me, you probably get annoyed about having your eyes bounce up and down while you trace the flow, in both of these examples.  We can fix that, of course:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def process(row)
    row.each do |field|
      if field.valid?
        do_something_with(field)
      else
        STDERR.puts "skipping a bad row"
        return
      end
    end
  end
  
  table.each { |row| process(row) }
&lt;/pre&gt;
&lt;p&gt;Now this is more like it!  This code is probably the same as what a beginner might write, but it&amp;#8217;s also the clearest out of what we&amp;#8217;ve seen here.  But without it as a point of reference, neither the &lt;tt&gt;catch&lt;/tt&gt; / &lt;tt&gt;throw&lt;/tt&gt; or &lt;tt&gt;callcc&lt;/tt&gt; solutions would look terrible.&lt;/p&gt;
&lt;p&gt;Through this quick little set of examples, I found a good reason &lt;strong&gt;not&lt;/strong&gt; to use continuations for this particular use case.  Arriving back at a simple solution by starting with a &amp;#8220;clever&amp;#8221; one and reducing it down to the fundamentals was a refreshing experience for me.&lt;/p&gt;
&lt;h3&gt;Your Homework&lt;/h3&gt;
&lt;p&gt;Now it&amp;#8217;s your turn.  I&amp;#8217;m encouraging you to ignore &amp;#8220;Best Practices&amp;#8221; and the common idioms that we often accept as gospel.&lt;/p&gt;
&lt;p&gt;Pick one technique that&amp;#8217;s typically considered a no-no and do the best you can to use it in a somewhat reasonable way.  You don&amp;#8217;t want to waste your time with something that not even the most muddy-eyed coder would touch with a ten-foot pole, as you won&amp;#8217;t learn much that way.  Instead, work with something that looks fine or even clever at a first glance.&lt;/p&gt;
&lt;p&gt;Then, try to fix up what you built by using more idiomatic, simpler code.  Your goal is to create something that still looks good, but isn&amp;#8217;t as much as a liability (conceptually) as what you started with.  If you fail to do so, the worst thing that could happen is that you may have come across a new idiom worth sharing with others.  But more likely, with a little effort you&amp;#8217;ll have no trouble uncovering the wisdom behind whatever idiom you were putting to the test.&lt;/p&gt;
&lt;p&gt;What&amp;#8217;s the difference?  Now, something that used to be a somewhat arbitrary rule to you is now common sense.  As contexts shift, you may need to conduct new experiments, but repeat this exercise often enough and you&amp;#8217;ll start to see a powerful intuition develop that allows you to internalize your design decisions rather than running through a punch list of patterns.  And at least for me, I find that experience a lot more fun.  I hope you will, too.&lt;/p&gt;
&lt;p&gt;If you try out this exercise, please share what you&amp;#8217;ve done, either via a link to your own blog, or a &lt;a href="http://gist.github.com"&gt;gist&lt;/a&gt;.  I&amp;#8217;m interested in how many bad ideas we can rack up here. :)&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Sun, 22 Nov 2009 22:57:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/013-good-to-be-bad.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/013-good-to-be-bad.html</guid></item><item><title>The Complete Class</title><description>&lt;p&gt;&lt;i&gt;A remark: we enabled comment moderation because the blog was recently target of spam.  You probably have not seen much of it because we were pretty quick in removing it manually.  So if your comment does not show up please be patient.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;There are some basic concepts (often called &amp;#8220;aspects&amp;#8221;) that need to be implemented for many classes although not all classes need all (or even any) of them:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;initialization&lt;/li&gt;
	&lt;li&gt;conversion to a printable string&lt;/li&gt;
	&lt;li&gt;equivalence&lt;/li&gt;
	&lt;li&gt;hash code calculation&lt;/li&gt;
	&lt;li&gt;comparability&lt;/li&gt;
	&lt;li&gt;cloning (&lt;code&gt;clone&lt;/code&gt; and &lt;code&gt;dup&lt;/code&gt;)&lt;/li&gt;
	&lt;li&gt;freezing&lt;/li&gt;
	&lt;li&gt;customized persistence (&lt;code&gt;Marshal&lt;/code&gt; and &lt;code&gt;Yaml&lt;/code&gt;)&lt;/li&gt;
	&lt;li&gt;matching&lt;/li&gt;
	&lt;li&gt;math and operator overloading&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which of these is needed for a particular class depends of course completely on the circumstances.  Classes which are never written to disk or used in a DRb context will not need customized persistence handling.  For other classes there might not be a reasoable ordering.&lt;/p&gt;
&lt;p&gt;We will look at these concepts individually in subsequent sections.  For the sake of this presentation I will create a slightly artificial class which will have particular properties in order to be able to show all the concepts:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;mutable fields&lt;/li&gt;
	&lt;li&gt;redundant fields, i.e. fields which carry cached values that can be derived from other fields&lt;/li&gt;
	&lt;li&gt;at least two fields for ordering priorities&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Class &lt;code&gt;Album&lt;/code&gt; implements a music album with a title, interpret, sequence of tracks and a fixed pause duration between tracks.  I picked a slightly different approach than Eric in &lt;a href="http://blog.segment7.net/articles/2008/12/17/friendly-ruby-objects"&gt;his article&lt;/a&gt; in two ways:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Eric has a stronger focus on collaboration with standard library classes while my guiding question was &amp;#8220;what does a class need to be complete and consistent?&amp;#8221;,&lt;/li&gt;
	&lt;li&gt;I present all the features in a single class to show how aspects play together.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You will likely never implement all these aspects in a single class.  Even for those aspects you do use, you might not use the same implementations I will present.  That&amp;#8217;s OK.  The implementations presented in this article are intended to cover aspects thoroughly even though you will not always have to do that in practice.  For example, certain code is there in order to make the class work properly as part of an inheritance hierarchy.  If you write a one off class for a script which is never intended for inheritance you can simplify many of the presented methods.&lt;/p&gt;
&lt;p&gt;I left out the topic of math and operator overloading since that does not mix well with the concept of music album.  Instead I will cover that in the next article in the blog which will present a class that shows how to override operators in Ruby and that plays well with Ruby&amp;#8217;s built in numeric classes.&lt;/p&gt;
&lt;h3&gt;Initialization&lt;/h3&gt;
&lt;p&gt;Implementing method &lt;code&gt;initialize&lt;/code&gt; is typically one of the first things I do when implementing a new class unless I can use the default implementation of &lt;code&gt;Struct&lt;/code&gt;.  There are a few things though that are worth considering.&lt;/p&gt;
&lt;p&gt;First of all, who owns arguments to &lt;code&gt;initialize&lt;/code&gt;?  It is important to make clear what happens to arguments that are provided to the call to &lt;code&gt;new&lt;/code&gt;.  There are three cases&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;the value is immutable (like &lt;code&gt;Fixnum&lt;/code&gt;) or&lt;/li&gt;
	&lt;li&gt;the caller retains ownership or&lt;/li&gt;
	&lt;li&gt;ownership is transferred to the new instance.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Case 1 is the simple one: basically you do not need care thinking about who owns the object as there are no bad effects which can be caused by &lt;a href="http://en.wikipedia.org/wiki/Aliasing_(computing)"&gt;aliasing&lt;/a&gt;.  If the instance is mutable these effects can show up.  If you want to make your code as robuts as possible you must ensure you got your own copy of the instance (typically via copying it, for example by using &lt;code&gt;dup&lt;/code&gt;).  The downside of this is of course that this costs performance as you&amp;#8217;ll likely copy too many objects.  In practice you will probably most of the time do nothing special and keep the code as simple as an assignment.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Album

  def initialize(title, interpret, pause = 0)
    super()

    # main properties
    self.title = title
    self.interpret = interpret
    @tracks = []

    # additional properties
    self.pause = pause

    # redundant properties
    # left out
  end

  def title=(t)
    @title = t.dup.freeze
  end

  def interpret=(i)
    @interpret = i.dup.freeze
  end

  def pause=(time)
    @pause = time
    @duration = nil
  end

end
&lt;/pre&gt;
&lt;p&gt;The other important aspect is inheritance.  Most classes that are written probably do not have a &lt;code&gt;super&lt;/code&gt; in their &lt;code&gt;initialize&lt;/code&gt; method.  If there are chances that you reopen the class and add mixin modules you should include &lt;code&gt;super()&lt;/code&gt; right from the start because even if you only implicitly inherit &lt;code&gt;Object&lt;/code&gt; and &lt;code&gt;initialize&lt;/code&gt; in Object does nothing you may later reopen the class and add a mixin module which has an &lt;code&gt;initialize&lt;/code&gt; method itself.  If you inherit another class than &lt;code&gt;Object&lt;/code&gt; you should explicitly mention arguments with &lt;code&gt;super&lt;/code&gt; and not rely on having the same argument list as the super class initializer.  That way you are making the call more explicit and are robust against changes in your &lt;code&gt;initialize&lt;/code&gt; method.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class CdAlbum &amp;lt; Album
  attr_accessor :bar_code

  def initialize(t, i, code)
    super(t, i, 2)

    self.bar_code = code
  end
end
&lt;/pre&gt;
&lt;p&gt;While we&amp;#8217;re at it: if you write a module which is intended as mixin and needs initialization itself the initializer should simply pass on all arguments in order to be compatible with arbitrary inheritance chains:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
module AnotherMixin
  # Prepare internal state and pass on all
  # arguments to the super class
  def initialize(*a, &amp;amp;b)
    super
    @list = []
  end
end
&lt;/pre&gt;
&lt;h3&gt;Conversion to a printable String&lt;/h3&gt;
&lt;p&gt;Often it is desirable to be able to convert an instance to a human readable string.  Which representation is most appropriate depends on the uses of the class.  One policy is to create a string representation so the instance can be later reconstructed given this string as is the case for all the numeric types from the standard library.  In the case of our sample class we will provide all interesting information:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def to_s
    "Album '#{title}' by '#{interpret}' (#{tracks.size} tracks)"
  end
&lt;/pre&gt;
&lt;p&gt;If you want to reuse a string field as external representation you could copy it in order to avoid bad effects from aliasing.  However, since typically &lt;code&gt;to_s&lt;/code&gt; is invoked for printing and no references are held I would say most of the time it is safe to not explicitly copy the field in these cases.&lt;/p&gt;
&lt;h3&gt;Equivalence&lt;/h3&gt;
&lt;p&gt;There are two methods that deal with object equivalence &lt;code&gt;eql?&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt;.  (Method &lt;code&gt;equal?&lt;/code&gt; tests for object &lt;em&gt;identity&lt;/em&gt; and should &lt;strong&gt;not&lt;/strong&gt; be overridden.)  Some core classes do have different equivalence relations implemented:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):003:0&amp;gt; 2 == 2.0
=&amp;gt; true
irb(main):004:0&amp;gt; 2.eql? 2.0
=&amp;gt; false
&lt;/pre&gt;
&lt;p&gt;But most of the time both methods will implement the same equivalence relation.  This also helps avoid confusion.  Note that &lt;code&gt;eql?&lt;/code&gt; is special because it is used by &lt;code&gt;Hash&lt;/code&gt; and &lt;code&gt;Set&lt;/code&gt; to test for instance equivalence.  We will come to that in a minute when we look at hash code calculation.&lt;/p&gt;
&lt;p&gt;Equivalence of instances must be tested against significant fields and should ignore redundant fields.  Looking at derived field values does not add anything to equivalence and makes the process slower at best.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def eql?(album)
    self.class.equal?(album.class) &amp;amp;&amp;amp;
      title == album.title &amp;amp;&amp;amp;
      interpret == album.interpret &amp;amp;&amp;amp;
      tracks == album.tracks
  end

  alias == eql?
&lt;/pre&gt;
&lt;p&gt;Now here you see a test for class identity which you likely have not seen in other classes.  Why is it there?  &lt;a href="http://en.wikipedia.org/wiki/Equivalence_relation"&gt;Mathematical equivalence&lt;/a&gt; is a symmetric relation which means that if &lt;code&gt;a.eql? b&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt; so should &lt;code&gt;b.eql? a&lt;/code&gt;.  Implementing &lt;code&gt;eql?&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt; that way also helps prevent strange effects when working with &lt;code&gt;Hash&lt;/code&gt; instances.  So if you are going to compare two instances of a class and a subclass then you might get &lt;code&gt;true&lt;/code&gt; when called on the super class instance and false on the subclass instance.  The same happens for two completely unrelated classes where the set of fields of one instance is a subset of those of the other instance.  You may actually be tricked into thinking they are equivalent because the common fields are equivalent while the two instances represent completely different concepts.  The only way to remedy this is to check for identity of the class.&lt;/p&gt;
&lt;p&gt;The reason that omitting the class identity check does not cause issues most of the time is simple: usually you stuff uniform instances into a &lt;code&gt;Hash&lt;/code&gt; or &lt;code&gt;Set&lt;/code&gt; and even if you mix different classes most of the time they will have different fields and different field values.  Still it is good to remember the point in case you experience unexpected effects with &lt;code&gt;Hash&lt;/code&gt; keys.&lt;/p&gt;
&lt;p&gt;Note that I omitted the test for self identity which you might be used to from Java classes.  I believe this is a premature optimization because most of the time you are going to test different instances for equivalence so most of the time you pay the penalty of the failing identity check and win only in rare circumstances.&lt;/p&gt;
&lt;h3&gt;Hash Code Calculation&lt;/h3&gt;
&lt;p&gt;This topic is closely related to instance equivalence: classes &lt;code&gt;Hash&lt;/code&gt;, &lt;code&gt;Array&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt; and other core classes rely on the fact that equivalent instances also return the same hash code.  Note that this is not symmetric: instances wich have the same hash code may actually not be equivalent.  But if the hash code differs they must not be equivalent.&lt;/p&gt;
&lt;p&gt;An instance&amp;#8217;s hash code should be based on the same fields that are used for determining equivalence.  Our class &lt;code&gt;Album&lt;/code&gt; has more fields and it is advisable to do some bit operations (often involving &lt;span class="caps"&gt;XOR&lt;/span&gt;) to combine all member hash codes into a single value in order to ensure better diversity of these values.  If you base the hash code only on a single field you increase the likelyhood that non equivalent instances fall into the same bucket of the &lt;code&gt;Hash&lt;/code&gt; which makes additional equivalence checks via &lt;code&gt;eql?&lt;/code&gt; necessary.  You can find more about how hash tables work on &lt;a href="http://en.wikipedia.org/wiki/Hash_table"&gt;Wikipedia&lt;/a&gt;.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def hash
    title.hash ^
      interpret.hash ^
      tracks.hash
  end
&lt;/pre&gt;
&lt;h3&gt;Comparability&lt;/h3&gt;
&lt;p&gt;Many classes have a natural ordering such as integers which are ordered by their numeric value.  If your class does also have a natural order you can implement operator &lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt; and include module &lt;code&gt;Comparable&lt;/code&gt; to get implementations of &lt;code&gt;&amp;lt;&lt;/code&gt;, &lt;code&gt;&amp;lt;=&lt;/code&gt; etc. for free.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  include Comparable

  def &amp;lt;=&amp;gt;(o)
    self.class == o.class ?
      (interpret &amp;lt;=&amp;gt; o.interpret).nonzero? ||
      (title &amp;lt;=&amp;gt; o.title).nonzero? ||
      (tracks &amp;lt;=&amp;gt; o.tracks).nonzero? ||
      (pause &amp;lt;=&amp;gt; o.pause) || 
      0 :
      nil
  end
&lt;/pre&gt;
&lt;h3&gt;Cloning&lt;/h3&gt;
&lt;p&gt;When cloning or duping an instance the default mechanism sets all fields of the new instance to refer to the same objects as the cloned instance.  While this is not an issue with immutable instances (e.g. &lt;code&gt;Fixnum&lt;/code&gt; or instances which are frozen) bad things can happen if you have a mutable instance (for example &lt;code&gt;Array&lt;/code&gt; or &lt;code&gt;String&lt;/code&gt;) which is suddenly referenced by two instances which both believe they are the sole owner of it.  All bad effects can happen including violation of class invariants and the instance state likely becomes inconsistent.  Do deal with such cases even for shallow copies such as &lt;code&gt;#clone&lt;/code&gt; and &lt;code&gt;#dup&lt;/code&gt; you need to copy a bit more.  Fortunately Ruby provides a hook (&lt;code&gt;#initialize_copy&lt;/code&gt;) which is invoked after the instance has been copied and which can make appropriate adjustments.  In our case we only need top copy the &lt;code&gt;Array&lt;/code&gt; of &lt;code&gt;Track&lt;/code&gt; instances because all other fields are immutable:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def initialize_copy(source)
    super
    @tracks = @tracks.dup
  end
&lt;/pre&gt;
&lt;p&gt;There is a &lt;a href="http://groups.google.com/group/comp.lang.ruby/browse_frm/thread/8a24226a54e79d24/9667453664f2633d#9667453664f2633d"&gt;recent discussion on comp.lang.ruby&lt;/a&gt; that started out with the subject of deep cloning but uncovered some general aspects of cloning.&lt;/p&gt;
&lt;h3&gt;Freezing&lt;/h3&gt;
&lt;p&gt;For freezing similar reasoning applies as for cloning: immutable fields need no additional attention as you cannot change those objects anyway.  For others you need to decide how deep you want the freeze to go.  In case of class &lt;code&gt;Album&lt;/code&gt; we certainly want to prevent addition of more tracks after an album has been frozen.  We also explicitly trigger calculation of &lt;code&gt;duration&lt;/code&gt; so to avoid errors when accessing the duration on the frozen instance; the value cannot change any more anyway.  This also makes it important to invoke &lt;code&gt;super&lt;/code&gt; as last method.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def freeze
    # unless frozen?
    @tracks.freeze 
    duration
    # end

    super
  end
&lt;/pre&gt;
&lt;p&gt;Note that the code is robust against multiple invocations of &lt;code&gt;#freeze&lt;/code&gt; because duration is calculated only once (on first transition from unfrozen to frozen).  If you have more complex calculations going on that involve state changes of the instance you should place &lt;code&gt;unless frozen?&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt; around the custom freeze code.&lt;/p&gt;
&lt;h3&gt;Custom Persistence&lt;/h3&gt;
&lt;p&gt;If you want to serialize the complete state of your instance there is nothing more to do: you can simply use &lt;code&gt;Marshal&lt;/code&gt; and &lt;code&gt;YAML&lt;/code&gt; from scratch.  However, if you have redundant data (such as field &lt;code&gt;duration&lt;/code&gt; in our case) which you want to omit from the serialization you have to adjust the process yourself.&lt;/p&gt;
&lt;p&gt;For &lt;code&gt;Marshal&lt;/code&gt; the proper approach is to use the newer approach which invoves writing methods &lt;code&gt;marshal_dump&lt;/code&gt; and &lt;code&gt;marshal_load&lt;/code&gt;.  The former is supposed to return something which is serialized instead of the current instance and the latter is invoked on a new empty object and handed the deserialized object so fields can be initialized properly.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def marshal_dump
    a = (super rescue [])
    a.push(@title, @interpret, @pause, @tracks)
  end

  def marshal_load(dumped)
    super rescue nil
    @title, @interpret, @pause, @tracks = *dumped.shift(4)
  end
&lt;/pre&gt;
&lt;p&gt;For &lt;span class="caps"&gt;YAML&lt;/span&gt; it is even simpler: you basically just need to ensure &lt;code&gt;to_yaml_properties&lt;/code&gt; returns a list of symbols containing only those members that you want serialized.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def to_yaml_properties
    a = super
    a.delete :@duration
    a
  end
&lt;/pre&gt;
&lt;p&gt;Both approaches do have their own strengths: with &lt;code&gt;Marshal&lt;/code&gt; it is easier to completely replace an object with something else.  While that can be done with &lt;code&gt;YAML&lt;/code&gt; as well it is not as simple and elegant as in the case of &lt;code&gt;Marshal&lt;/code&gt;.  &lt;code&gt;YAML&lt;/code&gt; on the other hand shines because you need to override only a single method.&lt;/p&gt;
&lt;p&gt;One word about the implementations: while these methods could look simpler I picked an approach which also works when inheritance comes into play.  You can repeat the pattern of &lt;code&gt;marshal_dump&lt;/code&gt;, &lt;code&gt;marshal_load&lt;/code&gt; and &lt;code&gt;to_yaml_properties&lt;/code&gt; throughout a class hierarchy and still have each method only deal with fields of the class in which it is defined.  That makes it easier to deal with later additions or removals of fields in some class in the hierarchy.  This is even more so important when dealing with mixin modules, which can happen on a per instance basis (via &lt;code&gt;#extend&lt;/code&gt;).&lt;/p&gt;
&lt;h3&gt;Matching&lt;/h3&gt;
&lt;p&gt;I use the term &amp;#8220;matching&amp;#8221; for the functionality of the three equals operator (&lt;code&gt;===&lt;/code&gt;) and for the matching operator (&lt;code&gt;=~&lt;/code&gt;).  The first is used in &lt;code&gt;case&lt;/code&gt; statements and with &lt;code&gt;Array#grep&lt;/code&gt; while the latter is usually used only explicitly.&lt;/p&gt;
&lt;p&gt;The semantic is completely up to the class at hand and there are no general guidelines that could be given.  Implement it when it is reasonable for your class.  If you want to elegantly use instances of your class in &lt;code&gt;case&lt;/code&gt; expressions you have to implement &lt;code&gt;===&lt;/code&gt; doing something meaningful.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # Check whether we have that track or track title by title.
  def ===(track_or_title)
    t = (track_or_title.title rescue track_or_title)
    tracks.find {|tr| t == tr.title}
  end

  # Match title against regular expression.
  def =~(rx)
    rx =~ title
  end
&lt;/pre&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Today we looked at a class which implements various common aspects that you will meet over and over again when coding Ruby.  Many of these are in fact present in other programming languages as well: Java has serialization, &lt;code&gt;equals&lt;/code&gt; and hash code calculation.  C++ also has an equivalence operator and other operators that can be overloaded to implement ordering etc.  You can find the &lt;a href="http://gist.github.com/217641"&gt;full code of the class&lt;/a&gt; at github.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Sat, 24 Oct 2009 18:05:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html</guid></item><item><title>Structs inside out</title><description>&lt;p&gt;Today we&amp;#8217;re back to normal blog mode, where each article stands for itself.  Muppet Labs are closed and we will be continuing our journey across the Ruby universe starting with an indepth look at Ruby&amp;#8217;s &lt;code&gt;Struct&lt;/code&gt; class &amp;#8212; Ruby&amp;#8217;s Swiss army knife for structured data.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Struct&lt;/code&gt; can be used without any additional &lt;code&gt;require&lt;/code&gt; statement &amp;#8212; it&amp;#8217;s just there.  This means it comes with zero additional overhead during initial interpreter startup &amp;#8212; one of the many advantage of using &lt;code&gt;Struct&lt;/code&gt;.  But first let&amp;#8217;s look at the basics.&lt;/p&gt;
&lt;h3&gt;Data Container&lt;/h3&gt;
&lt;p&gt;Class &lt;code&gt;Struct&lt;/code&gt; is a strange beast if you are confronted with it the first time: it has a method &lt;code&gt;new&lt;/code&gt; like other classes.  But that method does not return an instance of &lt;code&gt;Struct&lt;/code&gt; but rather a class which is a subclass of class &lt;code&gt;Struct&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; pnt = Struct.new :x, :y
=&amp;gt; #&amp;lt;Class:0x101c3d68&amp;gt;
irb(main):002:0&amp;gt; pnt.class
=&amp;gt; Class
irb(main):003:0&amp;gt; pnt.ancestors
=&amp;gt; [#&amp;lt;Class:0x101c3d68&amp;gt;, Struct, Enumerable, Object, Kernel, BasicObject]
&lt;/pre&gt;
&lt;p&gt;Arguments to &lt;code&gt;Struct.new&lt;/code&gt; are names of fields that the generated class will have.  These names must be provided as &lt;code&gt;Symbols&lt;/code&gt; which makes sense, because these field names are basically identifier you hardcode into the program.  (I will explain later why this is an accurate assessment when I look at &lt;code&gt;Struct&lt;/code&gt; vs. &lt;code&gt;OpenStruct&lt;/code&gt; vs. &lt;code&gt;Hash&lt;/code&gt;.)  You must provide them as &lt;code&gt;Symbols&lt;/code&gt; because of another peculiarity of &lt;code&gt;Struct&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; Struct.constants
=&amp;gt; [:Tms]
irb(main):002:0&amp;gt; s = Struct.new "Point", :x, :y
=&amp;gt; Struct::Point
irb(main):003:0&amp;gt; Struct.constants
=&amp;gt; [:Tms, :Point]
irb(main):004:0&amp;gt; t = Struct.new "doesNotWork", :x, :y
NameError: identifier doesNotWork needs to be constant
        from (irb):5:in `new'
        from (irb):5
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'
&lt;/pre&gt;
&lt;p&gt;I have to say I never used this feature of &lt;code&gt;Struct&lt;/code&gt; because&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;I don&amp;#8217;t want all my custom classes in a single namespace because that leads to potential issues,&lt;/li&gt;
	&lt;li&gt;I prefer explicit assignment to constants which makes clearer what&amp;#8217;s happening.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If someone knows advantages of this auto constantification which I overlooked please let us know via the &lt;a href="#disqus_thread"&gt;comment function&lt;/a&gt;.  Otherwise I suggest to rely on standard constant magic if you want to name your &lt;code&gt;Struct&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):053:0&amp;gt; pnt.name
=&amp;gt; nil
irb(main):054:0&amp;gt; Point = pnt
=&amp;gt; Point
irb(main):055:0&amp;gt; pnt.name
=&amp;gt; "Point"
&lt;/pre&gt;
&lt;h3&gt;Behavior&lt;/h3&gt;
&lt;p&gt;A &lt;code&gt;Struct&lt;/code&gt; generated Ruby class is more similar to a C++ struct than to a C struct because it does not only carry data but also functionality.  Some of that is already predefined when &lt;code&gt;Struct.new&lt;/code&gt; returns:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; pnt = Struct.new :x, :y
=&amp;gt; #&amp;lt;Class:0x101c2fa0&amp;gt;
irb(main):002:0&amp;gt; puts pnt.instance_methods(false)
x
x=
y
y=
=&amp;gt; nil
irb(main):003:0&amp;gt; puts Struct.instance_methods(false)
==
eql?
hash
to_s
inspect
to_a
values
size
length
each
each_pair
[]
[]=
select
values_at
members
=&amp;gt; nil
&lt;/pre&gt;
&lt;p&gt;These can be devided into two categories:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;methods which originally deal with struct members.&lt;/li&gt;
	&lt;li&gt;methods that allow an instance to mimic behavior of other classes.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Struct Member Behavior&lt;/h4&gt;
&lt;p&gt;First of all there are attribute accessors (those defined in the &lt;code&gt;Struct&lt;/code&gt; generated class, irb listing position 2).  Then there are those methods that make a &lt;code&gt;Struct&lt;/code&gt; instance usable as &lt;code&gt;Hash&lt;/code&gt; key:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;eql?&lt;/li&gt;
	&lt;li&gt;hash&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are defined in such a way that two &lt;code&gt;Struct&lt;/code&gt; instances are equivalent if all of their fields are:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):014:0&amp;gt; a = pnt.new 1,2
=&amp;gt; #&amp;lt;struct x=1, y=2&amp;gt;
irb(main):015:0&amp;gt; b = pnt.new 1,2
=&amp;gt; #&amp;lt;struct x=1, y=2&amp;gt;
irb(main):016:0&amp;gt; a.eql? b
=&amp;gt; true
irb(main):017:0&amp;gt; a.hash
=&amp;gt; -1066353017
irb(main):018:0&amp;gt; b.hash
=&amp;gt; -1066353017
&lt;/pre&gt;
&lt;p&gt;Method &lt;code&gt;==&lt;/code&gt; also implements a similar equivalence relation but with a twist:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):019:0&amp;gt; b = pnt.new 1.0,2
=&amp;gt; #&amp;lt;struct x=1.0, y=2&amp;gt;
irb(main):020:0&amp;gt; a.eql? b
=&amp;gt; false
irb(main):021:0&amp;gt; a == b
=&amp;gt; true
&lt;/pre&gt;
&lt;p&gt;It uses method &lt;code&gt;==&lt;/code&gt; of field values internally in the same way as &lt;code&gt;eql?&lt;/code&gt; uses &lt;code&gt;eql?&lt;/code&gt; of field values.  By providing these methods &lt;code&gt;Struct&lt;/code&gt; can save you a lot of tedious typing of pretty dull code that you would hack manually otherwise.  As we all know, the less code we have to write the less errors we can do&amp;#8230;&lt;/p&gt;
&lt;h4&gt;Mimicry&lt;/h4&gt;
&lt;p&gt;A &lt;code&gt;Struct&lt;/code&gt; can &amp;#8212; within certain limits &amp;#8212; mimic an &lt;code&gt;Array&lt;/code&gt; as well as a &lt;code&gt;Hash&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
# Array alike
irb(main):027:0&amp;gt; a.to_a
=&amp;gt; [1, 2]
irb(main):028:0&amp;gt; a[0]
=&amp;gt; 1
irb(main):029:0&amp;gt; a[1]
=&amp;gt; 2
irb(main):030:0&amp;gt; a.values_at 1,0
=&amp;gt; [2, 1]
irb(main):031:0&amp;gt; a.length
=&amp;gt; 2
irb(main):032:0&amp;gt; a.size
=&amp;gt; 2
irb(main):033:0&amp;gt; a.each {|e| p e}
1
2
=&amp;gt; #&amp;lt;struct x=1, y=2&amp;gt;
irb(main):034:0&amp;gt; a.select {|e| e % 2 == 0}
=&amp;gt; [2]
irb(main):035:0&amp;gt; a &amp;lt;&amp;lt; "more" # of course not
NoMethodError: undefined method `&amp;lt;&amp;lt;' for #&amp;lt;struct x=1, y=2&amp;gt;
        from (irb):41
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'

# Hash alike
irb(main):036:0&amp;gt; a[:x]
=&amp;gt; 1
irb(main):037:0&amp;gt; a["x"]
=&amp;gt; 1
irb(main):038:0&amp;gt; a.each_pair {|k,v| printf "%p =&amp;gt; %p\n",k,v}
:x =&amp;gt; 1
:y =&amp;gt; 2
=&amp;gt; #&amp;lt;struct x=1, y=2&amp;gt;
irb(main):039:0&amp;gt; a.keys # not quite
NoMethodError: undefined method `keys' for #&amp;lt;struct x=1, y=2&amp;gt;
        from (irb):38
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'
irb(main):040:0&amp;gt; a.members
=&amp;gt; [:x, :y]
irb(main):041:0&amp;gt; a[:y]=123
=&amp;gt; 123
irb(main):042:0&amp;gt; a
=&amp;gt; #&amp;lt;struct x=1, y=123&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Btw. the generated class also exposes some interesting methods, which do not really need additional explanation:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):049:0&amp;gt; pnt.members
=&amp;gt; [:x, :y]
irb(main):050:0&amp;gt; pnt[10,20] # for lazy typers
=&amp;gt; #&amp;lt;struct x=10, y=20&amp;gt;
&lt;/pre&gt;
&lt;h4&gt;Custom Behavior&lt;/h4&gt;
&lt;p&gt;From time to time you will want additional methods in your &lt;code&gt;Struct&lt;/code&gt; class.  Well, there is a &amp;#8220;hidden&amp;#8221; feature &amp;#8212; the documentation does not mention it but you can pass a block to &lt;code&gt;Struct.new&lt;/code&gt; which will be used as class body:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; Point = Struct.new :x, :y do
irb(main):002:1*   def distance(point)
irb(main):003:2&amp;gt;     Math.sqrt((point.x - self.x) ** 2 +
irb(main):004:3*       (point.y - self.y) ** 2)
irb(main):005:2&amp;gt;   end
irb(main):006:1&amp;gt; end
=&amp;gt; Point
irb(main):007:0&amp;gt; Point[3,4].distance Point[0,0]
=&amp;gt; 5.0
&lt;/pre&gt;
&lt;p&gt;This obsoletes the frequently seen idiom which uses inheritance from a &lt;code&gt;Struct&lt;/code&gt; generated class to add more methods:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):001:0&amp;gt; class Point &amp;lt; Struct.new(:x, :y)
irb(main):002:1&amp;gt;   def distance(point)
irb(main):003:2&amp;gt;     Math.sqrt((point.x - self.x) ** 2 +
irb(main):004:3*       (point.y - self.y) ** 2)
irb(main):005:2&amp;gt;   end
irb(main):006:1&amp;gt; end
=&amp;gt; nil
irb(main):007:0&amp;gt; Point[3,4].distance Point[0,0]
=&amp;gt; 5.0
&lt;/pre&gt;
&lt;p&gt;When using inheritance like this you are wasting resources (a class in this case) and so far I see only one advantage: changing the constructor is a bit easier because the old implementation is available via &lt;code&gt;super&lt;/code&gt; without having to resort to &lt;code&gt;alias&lt;/code&gt; or reimplementing member initialization.  If you want to have multiple subclasses of a &lt;code&gt;Struct&lt;/code&gt; class then inheritance is OK of course.  But in that case I would rather make the super class a named class by assigning it to a constant and use that later when subclassing.&lt;/p&gt;
&lt;h3&gt;Struct vs. OpenStruct vs. Hash&lt;/h3&gt;
&lt;p&gt;All three classes offer functionality with some similarities and overlap.  Sometimes you can use them interchangeably.  Still there are some guidelines you can use to decide when to use which of these.  As always &amp;#8212; take these recommendations with a grain of salt.  If you have your own different rules of thumb let us know.&lt;/p&gt;
&lt;p&gt;Use &lt;code&gt;Struct&lt;/code&gt; if&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;you need a data container and fields are fixed and known beforehand (i.e. at time of writing of the code),&lt;/li&gt;
	&lt;li&gt;you need a structured &lt;code&gt;Hash&lt;/code&gt; key,&lt;/li&gt;
	&lt;li&gt;you want to quickly define a class with a few fields,&lt;/li&gt;
	&lt;li&gt;you need to detect errors caused by misspelled field names.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use &lt;code&gt;OpenStruct&lt;/code&gt; if&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;the number of fields is fixed at runtime but varies frequently during development time (this is often the case for objects that should hold the result of command line option parsing),&lt;/li&gt;
	&lt;li&gt;you need a mock or a want to quickly have objects at hand which can be filled via usual attribute setters and getters.  You might want to replaced with a proper class (or &lt;code&gt;Struct&lt;/code&gt;) later &amp;#8212; with explicit attribute declarations via &lt;code&gt;attr_accessor&lt;/code&gt; and relatives.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use &lt;code&gt;Hash&lt;/code&gt; if&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;the number of fields is unknown at coding time,&lt;/li&gt;
	&lt;li&gt;there is a potentially unlimited number of fields (e.g. when reading key values from a file as is often the case for script based text processing).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now it also becomes apparent why I indicated that &lt;code&gt;Symbols&lt;/code&gt; are appropriate for naming &lt;code&gt;Struct&lt;/code&gt; fields: when defining a &lt;code&gt;Struct&lt;/code&gt; you are actually declaring attributes much the same way as with an ordinary class.  Still, &lt;code&gt;Struct&lt;/code&gt; is a bit inconsistent here when it allows &lt;code&gt;Symbols&lt;/code&gt; and &lt;code&gt;Strings&lt;/code&gt; as keys for the &lt;code&gt;Hash&lt;/code&gt; like access via &lt;code&gt;[]&lt;/code&gt; and &lt;code&gt;[]=&lt;/code&gt;.  The convenience of being able to use both probably outweighs this inconsistency.  Overall that &lt;code&gt;Hash&lt;/code&gt; likelyness is probably one of the less important features of &lt;code&gt;Struct&lt;/code&gt;.  You are likely going to use it when refactoring from / to real &lt;code&gt;Hashes&lt;/code&gt; of if you have an application that has to deal with several &lt;code&gt;Structs&lt;/code&gt; in a uniform way and needs to use metadata (obtained via #members) to access fields.&lt;/p&gt;
&lt;h3&gt;Deficiencies, any?&lt;/h3&gt;
&lt;p&gt;My whishlist for &lt;code&gt;Struct&lt;/code&gt; is pretty short.  The only thing that I am missing is an equally quick and elegant way to add &lt;code&gt;Comparable&lt;/code&gt; functionality to a generated &lt;code&gt;Struct&lt;/code&gt; class.  That could be achieved by having something like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Struct
  def self.comparable
    define_method :&amp;lt;=&amp;gt; do |o|
      members.each do |m|
        c = self[m] &amp;lt;=&amp;gt; o[m]
        return c unless c == 0
      end
      0
    end
    include Comparable
  end
end
&lt;/pre&gt;
&lt;p&gt;Now we can do&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):014:0&amp;gt; Point = Struct.new(:x, :y).comparable
irb(main):015:0&amp;gt; puts points = (1..5).map {Point[rand(4), rand(4)]}
#&amp;lt;struct Point x=3, y=3&amp;gt;
#&amp;lt;struct Point x=1, y=3&amp;gt;
#&amp;lt;struct Point x=2, y=3&amp;gt;
#&amp;lt;struct Point x=1, y=0&amp;gt;
#&amp;lt;struct Point x=0, y=0&amp;gt;
=&amp;gt; nil
irb(main):016:0&amp;gt; puts points.sort
#&amp;lt;struct Point x=0, y=0&amp;gt;
#&amp;lt;struct Point x=1, y=0&amp;gt;
#&amp;lt;struct Point x=1, y=3&amp;gt;
#&amp;lt;struct Point x=2, y=3&amp;gt;
#&amp;lt;struct Point x=3, y=3&amp;gt;
=&amp;gt; nil
&lt;/pre&gt;
&lt;h3&gt;Summary&lt;/h3&gt;
&lt;p&gt;Today we looked at various aspects of Ruby&amp;#8217;s built in class &lt;code&gt;Struct&lt;/code&gt;.  &lt;code&gt;Struct&lt;/code&gt; allows you to create classes quickly (typically in a one liner) while providing a lot of useful functionality out of the box &amp;#8212; most notably it is the fastest way to get a class suitable as a &lt;code&gt;Hash&lt;/code&gt; key (apart from using one of the other built in classes like &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Symbol&lt;/code&gt; or even &lt;code&gt;Array&lt;/code&gt;).  If you haven&amp;#8217;t been using &lt;code&gt;Struct&lt;/code&gt; so far you might want to try it out in your next hack.  Enjoy less typing with more &lt;code&gt;Structs&lt;/code&gt;!&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Mon, 21 Sep 2009 21:48:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/017-Struct.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/017-Struct.html</guid></item><item><title>Muppet Labs closing for now</title><description>&lt;h3&gt;Looking back&lt;/h3&gt;
&lt;p&gt;It is time to look back at the Muppet Laboratory series.  Here&amp;#8217;s my list of noteworthy items &amp;#8212; I will keep it rather short as interest in the series seems to have dwindled anyway:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;The first version with &lt;span class="caps"&gt;LRU&lt;/span&gt; caching integrated was way too complex and had ridiculous performance.  Continuous checking of interactions against the search criteria made the code complex and slow.  In this case the &lt;a href="http://en.wikipedia.org/w/index.php?title=Premature_optimization"&gt;premature optimization&lt;/a&gt; was worse than ineffective.&lt;/li&gt;
	&lt;li&gt;I am test lazy (I confess) but apparently this works remarkably well.  Note, that this does not mean I don&amp;#8217;t test.  But for my scripts I usually do not write &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/test/unit/rdoc/classes/Test/Unit.html"&gt;unit tests&lt;/a&gt; or &lt;a href="http://rspec.info/"&gt;RSpecs&lt;/a&gt;.  (file under: Ruby Bad Practices &amp;#8212; fortunately the acronym is the same)&lt;/li&gt;
	&lt;li&gt;Overall the &lt;span class="caps"&gt;LRU&lt;/span&gt; approach works remarkably well at limiting memory usage while processing huge amounts of input data so I would say the plan succeeded mostly.&lt;/li&gt;
	&lt;li&gt;I found the idea to use block passed to a method as a class body especially interesting.  I will probably recycle this for other cases where I want to provide a framework (including command line parsing) which needs to be filled with user code.&lt;/li&gt;
	&lt;li&gt;Summertime is a bad time for a blog series &amp;#8212; author and readers are occupied with other things, mainly enjoying sunny outsides.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What did you consider most valuable for you?  What would you have done differently (software as well as blog series wise)?  I would be curious to learn what your thoughts are.&lt;/p&gt;
&lt;h3&gt;What&amp;#8217;s ahead?&lt;/h3&gt;
&lt;p&gt;The next article will be about the versatility of &lt;code&gt;Struct&lt;/code&gt;.  This is another &lt;a href="http://blog.rubybestpractices.com/posts/gregory/009-beautiful-blocks.html"&gt;swiss army knife&lt;/a&gt; of the lazy Ruby coder.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Mon, 07 Sep 2009 19:03:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/016-Muppet-Lab_close.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/016-Muppet-Lab_close.html</guid></item><item><title>James will be right back after these interruptions</title><description>&lt;h1&gt;James will be right back after these interruptions&lt;/h1&gt;
&lt;h3&gt;How many times has this happened to you?&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;[&lt;span class="caps"&gt;WAY&lt;/span&gt;-&lt;span class="caps"&gt;TOO&lt;/span&gt;-&lt;span class="caps"&gt;LOUD&lt;/span&gt; TV &lt;span class="caps"&gt;VOICE&lt;/span&gt;]: You&amp;#8217;re working on some code, making good progress, solving a particular issue, when Oh No!,  &lt;br /&gt;
you&amp;#8217;ve run into a new bug.  Now what?&lt;/p&gt;
&lt;p&gt;You could open a browser, go to your issue tracker, and open a ticket. But that could take several minutes!&lt;/p&gt;
&lt;p&gt;Your train of thought would be derailed, code momentum lost, and time wasted!  But you can&amp;#8217;t just let that bug slide away!  Don&amp;#8217;t you wish there was an easier way to handle this?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;As far as I know there have been no late-night TV commercials selling solutions to software developers, but there are times we could use them.  The problem of staying focused on one task, while not ignoring others, is a real one, at least for me, and I suspect many others.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s what happens: You pick a bug to fix or feature to add, and set out to complete it.  Almost inevitably, though, you encounter other issues or interests.  If it looks to be minor, it&amp;#8217;s tempting to fix it right then. Sometimes this is trivial; a typo in the UI text in the file you&amp;#8217;re working on.  These are the cases where even adding a &lt;span class="caps"&gt;FIXME&lt;/span&gt; or &lt;span class="caps"&gt;TODO&lt;/span&gt; to the code would be about as much work as just fixing the problem.&lt;/p&gt;
&lt;p&gt;Other times, though, it&amp;#8217;s obvious that this new concern will take a bit of time. Or, maybe worse, there&amp;#8217;s no simple way to quickly judge how much work would be needed.  Dropping what you&amp;#8217;re doing to fix something else isn&amp;#8217;t a recommended practice.  Given that each task is prone to uncover a new task, you&amp;#8217;re doomed from the start to never finish anything.&lt;/p&gt;
&lt;p&gt;That leaves two (admittedly broad) options.  One is to ignore everything that isn&amp;#8217;t immediately related to the immediate task.  The other is to stop what you&amp;#8217;re doing and make a note of the problem.  But how long is &lt;strong&gt;that&lt;/strong&gt; going to take?&lt;/p&gt;
&lt;h3&gt;Now watch this!&lt;/h3&gt;
&lt;p&gt;Lately I&amp;#8217;ve been interested in focus and attention.  Like many people my ability to focus often varies.  For tasks that don&amp;#8217;t have an intrinsic lure (e.g. bug fixing) I work best if I stick to well-defined tasks over specific durations.  (This is an approach sometimes referred to as time boxing. Some formal examples are the &lt;a href="http://www.pomodorotechnique.com"&gt;Pomodoro Technique&lt;/a&gt;  and the &lt;a href="http://www.markforster.net/autofocus-system"&gt;Autofocus System&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;An important aspect is to really spend that time doing that specific task.  If it leads to assorted sub-tasks,  it matters how much time those things take, since time is limited.  If necessary digressions take too long, the whole &amp;#8220;do one thing&amp;#8221; plan falls apart, as does one&amp;#8217;s focus.&lt;/p&gt;
&lt;p&gt;So now we have two problems.  One, the code distraction that just appeared, and two, the need for a way to quickly and effectively record it. Here&amp;#8217;s what I&amp;#8217;ve been doing about that second one, which leads to solving the first one.&lt;/p&gt;
&lt;p&gt;I first started looking into the idea  of rapid notation when I was working a contract job that needed some detailed time tracking.  After spending two hours adding what seemed like a simple feature to a Java Web app I wanted to be able to look a back a see just where the time went.&lt;/p&gt;
&lt;p&gt;I started by using a plain text file.  Every so often, when I found myself doing something that didn&amp;#8217;t seem to be directly adding to a solution (for example, rebooting the app server to fix &lt;span class="caps"&gt;JVM&lt;/span&gt;  out-of-memory issues) I made a note.&lt;/p&gt;
&lt;p&gt;It worked OK, but it was a bit slow.  There was a lot of friction on opening the file, adding text, and saving it.  Even leaving the file open all the time was not helpful enough.  As I usually work at the command line I wrote a small Ruby script to let me write my notes right from the terminal.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;

    #!/usr/bin/env ruby

    @data_file = "/home/james/data/_at-today-please.txt" 

    def ts; Time.now.to_s; end

    def edit
      IO.popen "gvim #{@data_file} &amp;amp; "
    end

    def add
      msg = ARGV.join( ' ' ).to_s.strip
      File.open(@data_file, "a") do |f|
        f.print "--- #{ts}:\n\t#{msg}\n\n\n"
      end
    end

    ARGV.empty? ? edit : add
 &lt;/pre&gt;
&lt;p&gt;I&amp;#8217;m not making any claims for this code other than follows the principal of &lt;span class="caps"&gt;WFJ&lt;/span&gt;: Works for James.  I have it in a file at ~/bin/@; adding a short note is about as simple as it gets.  If I need to add something complex (or something that just doesn&amp;#8217;t play well at the command line), I pass no arguments and edit the file directly.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s flawed, of course.  Depending on the shell, different chracters (quote marks, for example) can throw things off.  But it works good enough for quick time-stamped notes.&lt;/p&gt;
&lt;h3&gt;But wait, there&amp;#8217;s more!&lt;/h3&gt;
&lt;p&gt;Some time after this hack I found myself working with &lt;a href="http://trac.edgewall.org"&gt;Trac.&lt;/a&gt;  It does a good job of coordinating source code, issues, project planning, and assorted other goodies.  Entering bugs, though, was a drag.  The Web UI meant entering text in multiple fields and selecting values from a few dropdown lists.   Once again, to keep from getting too distracted  while developing I wrote some code to post tickets from the command line.  The project was called Tracula (because the key to any project is a clever punny name) and helped my development process by removing some of the friction of tracking issues uncovered during development.  Usage hit some snags when different versions of Trac required somewhat more gnarly means of athenticating &lt;span class="caps"&gt;HTTP&lt;/span&gt; posts, while my use of Trac dropped in favor of other project management tools.&lt;/p&gt;
&lt;p&gt;Nonetheless, the general idea stayed with me, and when picking any tool I look to see if there&amp;#8217;s a simple &lt;span class="caps"&gt;HTTP&lt;/span&gt; interface that allows for automation and custom command-line driven clients.&lt;/p&gt;
&lt;p&gt;I now have &lt;a href="http://github.com/Neurogami"&gt;several projects on GitHub.com&lt;/a&gt;, which has become much like a hosted Trac, but with more ass-kickery. Each repo can have an issue tracker, and I&amp;#8217;ve just started using it for my &lt;a href="http://github.com/Neurogami/rhesus/tree/master"&gt;Rhesus&lt;/a&gt; project.&lt;/p&gt;
&lt;p&gt;Rhesus is yet another &lt;span class="caps"&gt;WFJ&lt;/span&gt; tool that has been evolving as I use it.  I had been making notes about the code in various places when I realized there was an actual bug tracker available.  I added a few issues, and immediately wondered if there was an &lt;span class="caps"&gt;API&lt;/span&gt; for this.  And &lt;a href="http://develop.github.com"&gt;there is&lt;/a&gt; (thanks, Engine Yard!).&lt;/p&gt;
&lt;p&gt;With Tracula there were three key options: fetch a list of open tickets; post a single new ticket; do a batch post of mulitple tickets.  How to do these with the GitHub &lt;span class="caps"&gt;API&lt;/span&gt;?  Well, fetching tickets is really easy, since there&amp;#8217;s no need for any authentication.  If you have &lt;code&gt;curl&lt;/code&gt; or &lt;code&gt;wget&lt;/code&gt; installed, it&amp;#8217;s a just a well-crafted &lt;span class="caps"&gt;URL&lt;/span&gt;:&lt;/p&gt;
&lt;pre&gt;    http://github.com/api/v2/json/issues/list/Neurogami/rhesus/open&lt;/pre&gt;
&lt;p&gt;will give you a list of open Rhesus issues.  Very slick, but since the results are a &lt;span class="caps"&gt;JSON&lt;/span&gt; string, maybe not the easiest thing to read. You can change that to &lt;span class="caps"&gt;XML&lt;/span&gt; or &lt;span class="caps"&gt;YAML&lt;/span&gt; if you like, but for better control, how about using some Ruby to slurp it in and present it in a more refined manner?&lt;/p&gt;
&lt;h3&gt;And if you call &lt;span class="caps"&gt;RIGHT&lt;/span&gt; &lt;span class="caps"&gt;NOW&lt;/span&gt; &amp;#8230;&lt;/h3&gt;
&lt;p&gt;A basic approach to showing the current set of open issues might be: make a call to the GitHub &lt;span class="caps"&gt;API&lt;/span&gt;; parse the results into some useful Ruby structure; selectively show the details to avoid overcrowding the screen.  One thing you need to consider, though, is just how often will the list of issues change relative to the number of times you want to see it.  In my case, I&amp;#8217;ll likely want to see the list way more often than it will change.  To make life easier both for me and for GitHub, I want my code to cache the list of issues and render that cache by default.   I&amp;#8217;m also going to make this a Rake task, and I&amp;#8217;ll allow for a parameter to indicate that the cache should be updated.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;

  namespace :issues do
    desc 'Open issues'
    task :open do
      paged_issues ENV['GH_NO_CACHE']
    end
  end
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;page_issues&lt;/code&gt; method will grab the set of issues and render them one by one:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;

  def ___
    warn "\n" + '_' * 30
  end

  def paged_issues no_cache = false
    ARGV.clear # Otherwise the call to gets will immediately find input
    warn "Hit &amp;lt;enter&amp;gt; after each issue to see the next one."
    issues(no_cache).each do |issue|
      ___
      warn "Title: #{issue['title']}"
      warn "Details: \n#{issue['body']}"
      ___
      gets
    end
    warn "\nThat's it!"
  end
&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;issues&lt;/code&gt; method will either pull from the cache or fetch anew from GitHub&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;

    def issues no_cache = false
      issues_cache = 'issues.yaml'
      if no_cache || !File.exist?(issues_cache)
         warn "Reloading issues from GitHub ..."
         File.open( issues_cache, 'w'){ |f| f.puts get_issues }
      end
      YAML.load(IO.read(issues_cache))['issues']
    end
&lt;/pre&gt;
&lt;p&gt;This allows for&lt;/p&gt;
&lt;pre&gt;rake issues:open&lt;/pre&gt;
&lt;p&gt;and&lt;/p&gt;
&lt;pre&gt;rake issues:open  GH_NO_CHACHE=true&lt;/pre&gt;
&lt;h3&gt;Operators are standing by!&lt;/h3&gt;
&lt;p&gt;What about adding a new issue?  The docs say that an authorized &lt;span class="caps"&gt;POST&lt;/span&gt; is needed.  And what&amp;#8217;s an authorized &lt;span class="caps"&gt;POST&lt;/span&gt;? It&amp;#8217;s an &lt;span class="caps"&gt;HTPP&lt;/span&gt; &lt;span class="caps"&gt;POST&lt;/span&gt; with parameters for your user name (&lt;code&gt;login&lt;/code&gt;) and your authorization token (&lt;code&gt;token&lt;/code&gt;).  The latter may be found on your GitHub account page.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;

     namespace :issues do
      # ...
      desc 'Create a new issue'
      task :create do
        issue_details = ENV['DETAILS'].to_s.strip
        if issue_details.empty?
          warn "No issue details!"
        else
          title, body =  issue_details.split(' -- ', 2)
          create_issue  title, body 
        end
      end
    
     # ...
     end
&lt;/pre&gt;
&lt;p&gt;Rake is not the most friendly when it comes to passing arguments, so to (somewhat) simplify things I decided to use one parameter that employed a delimiter to set off the issue title and body.  The code that does the actual ticket creation is oblivious to this, and could easily be used in a regular Ruby app.  The choice of making something a Rake task or a stand-alone executable depends on how you expect to use it.  With Rake, it&amp;#8217;s easy to get a reminder of what tasks are available using &lt;code&gt;rake -T&lt;/code&gt;.  The downside is that argument handling is not so nice.&lt;/p&gt;
&lt;p&gt;(Were this more than demo code, though, I would ultimately make the core code a library so that having both a Rake task and a standalone app would be equally easy.  And, in fact, some folks have been working on &lt;a href="http://github.com/fcoury/octopi/tree/master"&gt;GitHub &lt;span class="caps"&gt;API&lt;/span&gt; Ruby libraries.&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;Doing a &lt;span class="caps"&gt;POST&lt;/span&gt; is a bit more complex than just reading from a &lt;span class="caps"&gt;URL&lt;/span&gt;, but no big deal:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;

      def create_issue title, body
        require 'net/http'
        require 'uri'

        token = ENV['GH_AUTH_TOKEN']
        url = 'http://github.com/api/v2/yaml/issues/open/Neurogami/rhesus'
        res = Net::HTTP.post_form(URI.parse(url),
                                  {'title'=&amp;gt; title, 
                                      'body' =&amp;gt; body,
                                      'login' =&amp;gt; 'Neurogami',
                                       'token'=&amp;gt; token }
                                 )
        warn res.body

      end
&lt;/pre&gt;

&lt;p&gt;Note that the code pulls the authentication token from an environment variable. That&amp;#8217;s done to avoid having to embed it in the code or some config file that may inadvertently reach the wrong eyes.&lt;/p&gt;
&lt;p&gt;As for bulk posting of issues, well, better add a ticket for that.&lt;/p&gt;
&lt;h3&gt;But that&amp;#8217;s not all;  you&amp;#8217;ll also get this!&lt;/h3&gt;
&lt;p&gt;I must confess that I&amp;#8217;ve been writing the code as I wrote this post.  It&amp;#8217;s an amazingly useful way to get some code written.&lt;/p&gt;
&lt;p&gt;I thought about the whole &amp;#8220;Oh, if you were really doing this right, you&amp;#8217;d make this a library&amp;#8221; thing, and, well, I made this a library thing.&lt;/p&gt;
&lt;p&gt;You can get the code here: &lt;a href="http://github.com/Neurogami/ghissues/tree/master"&gt;http://github.com/Neurogami/ghissues/tree/master&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s basically the above code, with some provisions for reading a local config file that defines the repo, repo owner, and a file for saving a cache of the repo issues.   (A down-side of coding-for-content is that certain niceties, like docs and tests, may fall by the wayside.  The code, however, is pretty simple.)&lt;/p&gt;
&lt;p&gt;Re-doing the Rake tasks using this gem is left as an exercise for the reader.&lt;/p&gt;
&lt;h3&gt;Don&amp;#8217;t wait; act now!&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;ve written a few other apps along these lines. One lets me add items to my list at &lt;a href="http://todoist.com"&gt;Todoist.com.&lt;/a&gt; I can even set reminders to pester me to do something later.  Very handy; the improved speed in setting a reminder or adding a new bug ticket is well worth the time spent coding up such tools.  There are numerous existing apps out there for things like this as well.  (Check out &lt;a href="http://news.ycombinator.com/item?id=770064"&gt;this thread on Hacker News.&lt;/a&gt;).  See if one doesn&amp;#8217;t help you do more with less friction.&lt;/p&gt;
&lt;p&gt;But if you can&amp;#8217;t find one that really works for you, consider writing your own.  It&amp;#8217;s not hard, and there&amp;#8217;s a real payoff in having something that fits your style and keeps you moving.&lt;/p&gt;</description><author>james.britt@gmail.com (James Britt)</author><pubDate>Sun, 30 Aug 2009 13:00:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/jamesbritt/James_will_be_right_back_after_these_interruptions.html</link><guid>http://blog.rubybestpractices.com/posts/jamesbritt/James_will_be_right_back_after_these_interruptions.html</guid></item><item><title>Completing the Animal</title><description>&lt;h3&gt;Leftovers&lt;/h3&gt;
&lt;p&gt;Summertime was a bit tough &amp;#8212; but the end is near!  Today I will cover two major parts that were needed to complete the &amp;#8220;animal&amp;#8221;.  After that I will present lessons that I learned in this public blog software project.  Muppet Laboratories will then close their doors but &lt;a href="http://github.com/rklemme/muppet-laboratories/tree/master"&gt;the code&lt;/a&gt; will still be there.&lt;/p&gt;
&lt;p&gt;For a fully functioning Animal mainly two things were missing:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;command line parsing,&lt;/li&gt;
	&lt;li&gt;creation of a proper filter mechanism based on command line arguments.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We will first look at command line parsing.&lt;/p&gt;
&lt;h3&gt;Command Line Parsing&lt;/h3&gt;
&lt;p&gt;There is actually no rocket since involved whatsoever.  The most noteworthy piece of information is probably that you need to include &amp;#8216;optparse/time&amp;#8217; in order to be able to allow &lt;code&gt;OptionParser&lt;/code&gt; to parse time stamps passed as option arguments.  (Funny thing is, &lt;code&gt;OptionParser&lt;/code&gt; will also happily accept strings like &amp;#8220;now&amp;#8221; and parse them as timestamps.)&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
require 'ostruct'
require 'optparse'
require 'optparse/time'

  def self.parse_command_line(argv = ::ARGV) 
    o = OpenStruct.new(:output_dir =&amp;gt; '.')

    # parse
    OptionParser.new do |opts|
      opts.on '-d', '--dir=DIRECTORY', 'Output directory ' do |v|
        o.output_dir = v
      end

      opts.on '-r', '--rx=REGEXP', ::Regexp, 'Regular expression matched',
      'against log line text' do |v|
        o.rx = v
      end

      opts.on '-t', '--time=TIME', ::Time, 'timestamp' do |v|
        o.ts = v
      end

      opts.on '-s', '--start=TIME', ::Time, 'start timestamp' do |v|
        o.start_ts = v
      end

      opts.on '-e', '--end=TIME', ::Time, 'end timestamp' do |v|
        o.end_ts = v
      end

      opts.on '--ids=ID_LIST', ::Array, 'Comma separated list of interaction ids' do |v|
        (o.ids ||= Set.new).merge v
      end

      opts.on '--id-file=FILE', 'File with ids one per line',
       '(empty lines are ignored)' do |v|
        s = o.ids ||= Set.new

        File.foreach v do |line|
          line.strip!
          s &amp;lt;&amp;lt; line unless line == ''
        end
       end

      opts.on '--buffer=INTERACTIONS', ::Integer,
        'Max no. of interactions to keep in memory' do |v|
        o.max_size = v
        end

      opts.on_tail '-h', '--help', 'Print this help' do
        puts opts
        exit 0
      end
    end.parse! argv

    raise 'Only one of time or (start, end) allowed' if o.ts &amp;amp;&amp;amp; (o.start_ts || o.end_ts)
    raise 'Missing end timestamp' if o.start_ts &amp;amp;&amp;amp; !o.end_ts
    raise 'Missing start timestamp' if !o.start_ts &amp;amp;&amp;amp; o.end_ts

    o
  end
&lt;/pre&gt;
&lt;p&gt;I personally find &lt;code&gt;OptionParser&lt;/code&gt; very elegant and complete but other seem to prefer other command line parsing packages, like &lt;a href="http://ruby-doc.org/stdlib/libdoc/getoptlong/rdoc/index.html"&gt;GetoptLong&lt;/a&gt; and there are &lt;a href="http://totalrecall.wordpress.com/2008/09/05/command-line-parsing-choosing-a-ruby-library/"&gt;others around&lt;/a&gt; as well.  Main advantages of &lt;code&gt;OptionParser&lt;/code&gt; in my opinion:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Options, their documentation and their processing are all placed close to each other.&lt;/li&gt;
	&lt;li&gt;Built in support for conversion of argument strings to most basic types and even lists of values.&lt;/li&gt;
	&lt;li&gt;It is a part of the standard Ruby distribution, i.e you can safely assume that it is available.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Filter Creation&lt;/h3&gt;
&lt;p&gt;There are several approaches that can be taken on creating a bit of filter code from options taken from the command line &amp;#8212; all have different strengths and weaknesses:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Interpreting the option set on each filter invocation (slow but easy to implement).&lt;/li&gt;
	&lt;li&gt;Combination of written filter code with filter criteria values stuffed in a closure (faster than the first option but equally easy to implement).&lt;/li&gt;
	&lt;li&gt;Generation of filter code (usually fastest, can be a bit complex to implement).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I picked option 2 because of the speed advantage and the avoidance of &lt;a href="http://www.rubycentral.com/pickaxe/taint.html"&gt;safety issues&lt;/a&gt; that come with using &lt;code&gt;eval&lt;/code&gt;.  I also find it a bit inelegant to generate code but that&amp;#8217;s a purely aesthetic argument which I don&amp;#8217;t claim any substance for.  (But since we&amp;#8217;re into Ruby at least partly for the fun, that argument is not too far off the mark.)&lt;/p&gt;
&lt;p&gt;As interface I choose &lt;code&gt;lambda's&lt;/code&gt; square brackets.  So, here is the filter creation code:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
    def create_filter(opts)
      # store in local variables to ensure
      # ensure values do not get changed
      # and a small speed improvement
      o_ids = opts.ids
      o_ts = opts.ts
      o_start_ts = opts.start_ts
      o_end_ts = opts.end_ts
      o_rx = opts.rx

      f = case
          when o_ids
            warn 'WARNING: Ignoring time filters with ids given' if
            o_ts || o_start_ts || o_end_ts
            lambda {|ip| o_ids.include? ip.id}
          when o_ts
            lambda {|ip|
              ip.entries.first.time_stamp &amp;lt;= o_ts &amp;amp;&amp;amp;
                ip.entries.last.time_stamp &amp;gt;= o_ts
            }
          when o_start_ts &amp;amp;&amp;amp; o_end_ts
            lambda { |ip|
              ip.entries.last.time_stamp &amp;gt;= o_start_ts &amp;amp;&amp;amp; 
                ip.entries.first.time_stamp &amp;lt;= o_end_ts
            }
          end

      case
      when f &amp;amp;&amp;amp; o_rx
        lambda {|ip| f[ip] &amp;amp;&amp;amp; ip.entries.any? {|e| o_rx =~ e.line}}
      when o_rx
        lambda {|ip| ip.entries.any? {|e| o_rx =~ e.line}}
      when f
        f
      else
        YES
      end
    end
&lt;/pre&gt;
&lt;p&gt;As you can see there is a bit of prioritization going on: I choose to ignore time range options if also interaction ids are used as filter criterion.  Reason is that interactions are usually short and additional time based filters would either have to add more interactions to the result or remove interactions whose id was selected (depending on whether &amp;#8220;and&amp;#8221; or &amp;#8220;or&amp;#8221; combination was chosen).&lt;/p&gt;
&lt;p&gt;The text filter (regular expression really) on the other hand is &amp;#8220;and&amp;#8221; connected with the other filter, i.e. if the list of interactions selected by time or ids is large then it will be narrowed down through the text filter.&lt;/p&gt;
&lt;p&gt;One word about time filters: when given a single point in time, the test is pretty straightforward &amp;#8212; the first timestamp must be lower and the last timestamp must be larger than the test time, i.e. the interaction was active at the given time.  The test for a given time interval (start and end time given separately) may look a bit odd at first.  However, there is no typo involved.  The test ensures that the test interval and the interaction&amp;#8217;s time interval overlap.  Or put differently: the test ensures that all interactions are included that were active during the test interval.&lt;/p&gt;
&lt;h3&gt;Things left to do&lt;/h3&gt;
&lt;p&gt;For now I am pretty satisfied with the results so I do not feel a lot pressure to continue working on it.  However, there are a few things that could be done:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Cleanup of &lt;code&gt;require&lt;/code&gt; and deletion of source files that were not used.&lt;/li&gt;
	&lt;li&gt;Adding of statistics output like lines read, lines written, interactions found etc.&lt;/li&gt;
	&lt;li&gt;Profiling and optimization.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anything else?&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Mon, 24 Aug 2009 21:09:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/015-Completing_the_Animal.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/015-Completing_the_Animal.html</guid></item><item><title>Be Nice and Have Fun</title><description>&lt;p&gt;Yet again, we&amp;#8217;re experiencing &lt;a href="http://news.ycombinator.com/item?id=773106"&gt;a firestorm&lt;/a&gt; that will shake things up and change the Ruby community in a big way.  But like anything else, the best thing we can do is remember that the sky is not falling, and that all internet drama is ephemeral at best.&lt;/p&gt;
&lt;p&gt;Sure, we&amp;#8217;ll all dearly miss a valued community member who inspired many of us.  But thanks to distributed revision control systems, we&amp;#8217;ll be able to commemorate _why through his works, currently being &lt;a href="http://github.com/whymirror"&gt;mirrored on github&lt;/a&gt; .&lt;/p&gt;
&lt;p&gt;So what do we do in this post _why world?  The answer to that is fairly simple: the same thing we&amp;#8217;ve been doing.  The true spirit of the Ruby community (and even the free software hacker community at large) is to work on fun stuff, and try to be nice to people.  If we can keep that up, the sky will not fall, and may even make room for new stars to light up the present darkness.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll let this brief statement stand on its own here, as &lt;span class="caps"&gt;RBP&lt;/span&gt; has no intentions of becoming a gossip blog, but feel free to leave your thoughts in the comments.&lt;/p&gt;
&lt;p&gt;Expect a new Ruby 1.9 series post some time before or just after &lt;span class="caps"&gt;LSRC&lt;/span&gt;.  Until then, keep your heads up folks.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;NOTE&lt;/span&gt;: I have Aaron Patterson to thank for expressing what I was thinking in words &amp;#8216;do fun stuff and try to be nice&amp;#8217;&lt;/i&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Fri, 21 Aug 2009 11:25:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/012-be-nice-and-have-fun.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/012-be-nice-and-have-fun.html</guid></item><item><title>A bit of Optimization</title><description>&lt;p&gt;As suggested &lt;a href="http://blog.rubybestpractices.com/posts/rklemme/013-LRU-Explanations.html"&gt;earlier&lt;/a&gt; I did a bit of benchmarking and found these timings of the first version which kept everything in memory and the next version with two &lt;span class="caps"&gt;LRU&lt;/span&gt; storages (for InteractionProcessor and IO objects):&lt;/p&gt;
&lt;pre&gt;
v0.1

robert@fussel ~/Eigene Dateien/Projects/muppet-laboratories
$ time ruby19 bin/sample-animal.rb sample.log

real    11m53.226s
user    6m34.561s
sys     4m33.921s


v0.2.1

robert@fussel ~/Eigene Dateien/Projects/muppet-laboratories
$ time ruby19 bin/sample-animal.rb sample.log

real    25m40.842s
user    14m40.655s
sys     8m29.701s
&lt;/pre&gt;
&lt;p&gt;I then went on and refactored the code in these ways:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;removed &lt;span class="caps"&gt;LRU&lt;/span&gt; storage of &lt;code&gt;IO&lt;/code&gt; objects&lt;/li&gt;
	&lt;li&gt;removed state pattern and replaced it with a single filter test again&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The solution now resembles the first version quite a bit with the difference that the storage of &lt;code&gt;InteractionProcessor&lt;/code&gt; instances is now an &lt;code&gt;LRUHash&lt;/code&gt;.  The &lt;code&gt;InteractionProcessor&lt;/code&gt; now looks very simple &amp;#8212; again:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class InteractionProcessor
    
    # mode for writing files
    OPEN_MODE = IO::WRONLY | IO::CREAT | IO::TRUNC

    attr_reader :id, :coord, :entries

    def initialize(id, coordinator)
      @id = id
      @coord = coordinator
      @entries = []
    end

    # Process the first line
    def process_initial(time_stamp, line)
      process(time_stamp, line)
    end

    # Process an initial line
    def process(time_stamp, line)
      @entries &amp;lt;&amp;lt; Entry.new(time_stamp, line)
    end

    # Append a continuation line to the last entry
    def append_line(line)
      @entries.last.line &amp;lt;&amp;lt; line
    end

    def finish
      if ! @entries.empty? &amp;amp;&amp;amp; @coord.filter[self]
        fn = file_name
        FileUtils.mkdir_p(File.dirname(fn))

        File.open(fn, OPEN_MODE) do |io|
          @entries.each {|e| io.puts(e.line)}
        end
      end
    end

    private

    # calculate the file name, this fails if
    # there are no entries!
    def file_name
      ts = @entries.first.time_stamp
      File.join(@coord.options.output_dir,
                ts.strftime('%Y-%m-%d'),
                ts.strftime('%H-%M'),
                ts.strftime('%S.%3N-') + id)
    end
  end
&lt;/pre&gt;
&lt;p&gt;And now this is the timing we get:&lt;/p&gt;
&lt;pre&gt;
v0.3

robert@fussel ~/Eigene Dateien/Projects/muppet-laboratories
$ time ruby19 bin/sample-animal.rb sample.log

real    7m29.546s
user    2m16.702s
sys     4m8.296s
&lt;/pre&gt;
&lt;p&gt;Now, this is even faster than the first version!  The difference seems to mainly be caused by a reduction in user time.  I would have expected at most a small change in system time for less paging since we limit the memory usage.  Maybe the difference is caused by the fact that the main &lt;code&gt;Hash's&lt;/code&gt; size does not increase beyond a fixed limit.&lt;/p&gt;
&lt;p&gt;I guess the &lt;span class="caps"&gt;LRU&lt;/span&gt; based storage of file handles qualified as premature optimization: apparently it wasn&amp;#8217;t necessary to get rid of individual log lines as fast as possible.  Instead, it makes more sense to treat an interaction as entity and wait with the processing until the interaction is complete (well, not really: until the &lt;span class="caps"&gt;LRU&lt;/span&gt; storage decides, that the interaction must be purged from memory).  That&amp;#8217;s a nice example how granularity of processing directly influences performance and application design.  In fact, treating an interaction as entity is probably also the &lt;a href="http://en.wikipedia.org/wiki/KISS_principle"&gt;most straightforward&lt;/a&gt; approach.  And it turns out to be more efficient than the much more complex state pattern logic.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Sun, 09 Aug 2009 20:47:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/014-First_Optimization.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/014-First_Optimization.html</guid></item><item><title>Should I Tap that Hash?  (Ruby 1.9 Style)</title><description>&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: Be sure to read the comments.  I&amp;#8217;ve already learned a lot from them, and you might, too.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;Though the &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; book covers Ruby 1.9, it is decidedly not a &amp;#8220;Ruby 1.9 Best Practices&amp;#8221; book.   The reason for this, of course, is that common idioms for Ruby 1.9 haven&amp;#8217;t evolved yet.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s work together to change that.   Every week until Ruby 1.9.2 comes out, I&amp;#8217;ll be coming up with short, manageable bits of Ruby 1.9 code for discussion, as part of a &amp;#8220;Ruby 1.9 Style&amp;#8221; series.  These should not be taken to be authoritative in any way, but instead work as conversation starters so that we can move forward as a community and separate the good from the bad when hacking code on Ruby 1.9.&lt;/p&gt;
&lt;p&gt;Rather than describing in detail how this series will work, I&amp;#8217;ll just begin with some real content and you can get a sense of the format from that.  The only key thing is to remember to not be lazy, and to actually comment on these posts.  Ruby 1.9 is basically the wild west right now, and its going to take quite a few sound voices to tame it.  So be sure to share your thoughts after you take a look at the proposed idiom below.&lt;/p&gt;
&lt;h3&gt;Object#tap, a seemingly benign addition.&lt;/h3&gt;
&lt;p&gt;Ruby 1.9 gives us &lt;tt&gt;tap&lt;/tt&gt;.  And &lt;tt&gt;tap&lt;/tt&gt; is sort of neat because it can be useful as a debugging tool, especially in &lt;a href="http://moonbase.rydia.net/mental/blog/programming/eavesdropping-on-expressions.html"&gt;chained code&lt;/a&gt;.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  &amp;gt;&amp;gt;  [1,2,3].map { |x| x + 1 }.tap { |y| p y }.inject(:+)
  [2, 3, 4]
  =&amp;gt; 9
&lt;/pre&gt;
&lt;p&gt;There isn&amp;#8217;t much conceptual weight here, either.  Essentially, you&amp;#8217;re looking at something like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def tap
    yield(self)
    self
  end
&lt;/pre&gt;
&lt;p&gt;But hmm, doesn&amp;#8217;t that look familiar?&lt;/p&gt;
&lt;h3&gt;Object#tap as an alternative to ActiveSupport&amp;#8217;s returning&lt;/h3&gt;
&lt;p&gt;Those who work with Rails or with ActiveSupport in some other capacity will have seen &lt;tt&gt;returning&lt;/tt&gt;.  The problem it is meant to solve is seen in the code below.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def ugly
    results = {}

    [:x, :y, :z].each do |letter|
      results[letter] = rand(100)
    end

    results
  end
&lt;/pre&gt;
&lt;p&gt;Using &lt;tt&gt;returning&lt;/tt&gt;, this can be cleaned up a bit:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def sexy
  returning({}) do |results|
    [:x, :y, :z].each do |letter|
      results[letter] = rand(100)
    end
  end
end
&lt;/pre&gt;
&lt;p&gt;This code &lt;strike&gt;is definitely more &lt;span class="caps"&gt;DRY&lt;/span&gt;, and&lt;/strike&gt; looks pretty clean.  The only problem with it is that since it relies on ActiveSupport, you&amp;#8217;re essentially sifting through DHH&amp;#8217;s junk drawer for a piece of non-standard functionality for a fairly basic purpose.  While it may not be a &amp;#8220;Rails Best Practice&amp;#8221;, I tend to shy away from this sort of thing to keep from being too dependent on a framework that I only use part of the time.&lt;/p&gt;
&lt;p&gt;But if we think for a second, how would &lt;tt&gt;returning&lt;/tt&gt; be implemented?  Something like this, right?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def returning(obj)
    yield(obj)
    obj
  end
&lt;/pre&gt;
&lt;p&gt;Go check out the end of the previous section.  What we can see now is that &lt;tt&gt;returning&lt;/tt&gt; is just &lt;tt&gt;Object#tap&lt;/tt&gt; inside out!  So what happens when we use &lt;tt&gt;tap&lt;/tt&gt; that way?  Let&amp;#8217;s take a look.&lt;/p&gt;
&lt;h3&gt;Tapping that Hash.&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;ve started on a few Ruby 1.9 production apps, and that&amp;#8217;s where I first ran into attempting to use &lt;tt&gt;tap&lt;/tt&gt; as if it were &lt;tt&gt;returning&lt;/tt&gt;.  Take a look at this bit of code:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def times_for_period(date)
    days = work_days_for_period(date)
    regular_hours_by_week = Hash.new(0)

    { :regular_hours =&amp;gt; 0, :other_hours =&amp;gt; Hash.new(0) }.tap do |results|
      days.each do |d|
        times = d.times

        results[:regular_hours] += times[:regular_hours]
        regular_hours_by_week[d.date.cweek] += times[:regular_hours]

        times[:other_hours].each { |k,v| results[:other_hours][k] += v }
      end

      results[:weekly_hours] = regular_hours_by_week.keys.sort.map do |k| 
        regular_hours_by_week[k]
      end
    end
  end
&lt;/pre&gt;
&lt;p&gt;What I&amp;#8217;m doing here is calling &lt;tt&gt;tap&lt;/tt&gt; on a default hash and then populating it via the code within the block.  If I was simply iterating over some values, I might use &lt;tt&gt;inject&lt;/tt&gt; or &lt;tt&gt;each_with_object&lt;/tt&gt;, but my needs were a little more complicated here.&lt;/p&gt;
&lt;p&gt;This approach adds a little complexity, but in my experience, having to explicitly return a collection at the end of a method can be cumbersome, and I frequently forget about it during refactoring and cause my tests to go red on me.&lt;/p&gt;
&lt;p&gt;What do you think? Is &lt;tt&gt;Object#tap&lt;/tt&gt; the new &lt;tt&gt;returning&lt;/tt&gt;?  Or should we put this knife carefully back into DHH&amp;#8217;s junk drawer for safekeeping? I&amp;#8217;m pretty sure Rails didn&amp;#8217;t invent this functionality, but that&amp;#8217;s where a lot of us might have encountered it first.&lt;/p&gt;
&lt;p&gt;Help me decide whether this is elegant or nasty in the comments below.&lt;/p&gt;
&lt;h3&gt;A Gentle Reminder&lt;/h3&gt;
&lt;p&gt;I have to warn you, some of my ideas might be bad.  I&amp;#8217;ll be posting code that I find interesting or stuff that I don&amp;#8217;t know exactly how I feel about.  If we hit a dud from time to time, it&amp;#8217;s only to be expected.  But if you want to help me out, consider contributing content to this series.  If you have an idea for a guest post, go ahead and email me with the details, and I&amp;#8217;ll get back to you.&lt;/p&gt;
&lt;p&gt;Looking forward to your thoughts on this one and many more in the coming weeks!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Wed, 05 Aug 2009 12:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/011-tap-that-hash.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/011-tap-that-hash.html</guid></item><item><title>LRU Integration explained</title><description>&lt;p&gt;Today I will present my reasoning which lead me to the implementation of the &lt;code&gt;LRUHash&lt;/code&gt; as well as how I integrated it into the main code.  We will look at how &lt;code&gt;LRUHash&lt;/code&gt; works and how it is integrated into the project.  Then I will answer some questions that were actually asked &amp;#8212; or only thought.&lt;/p&gt;
&lt;h3&gt;How &lt;code&gt;LRUHash&lt;/code&gt; works&lt;/h3&gt;
&lt;p&gt;The interface should resemble a &lt;code&gt;Hash&lt;/code&gt; as much as possible so that &lt;code&gt;LRUHash&lt;/code&gt; can be easily substituted for a &lt;code&gt;Hash&lt;/code&gt; instance without alteration of the code that uses it.  As long as the instance remains below the maximum size it behaves much the same as a regular &lt;code&gt;Hash&lt;/code&gt;.  Only when the size limit defined via &lt;code&gt;max_size&lt;/code&gt; is reached any subsequent store operations will remove the oldest entry.&lt;/p&gt;
&lt;p&gt;Internally a &lt;code&gt;LRUHash&lt;/code&gt; maintains a linked list of &lt;code&gt;LRUHash::Node&lt;/code&gt; instances and a &lt;code&gt;Hash&lt;/code&gt;.  Nodes contain key and value of a hash entry as well as links to their predecessor and successor.  The &lt;code&gt;Hash&lt;/code&gt; is used for fast access of individual nodes while the linked list is used to maintain information about access order: every node which is accessed is moved to the head of the list so the least recently used element is always at the tail.&lt;/p&gt;
&lt;p&gt;There are two nodes referenced as &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt; which are never changed.  This makes it easier to move nodes around in the list because extraction and insertion are always operations on inner nodes and do not need to account for the first and last element on the list which is tedious because then you would also have to change the first and last pointer.&lt;/p&gt;
&lt;p&gt;Additionally to the &lt;code&gt;default_proc&lt;/code&gt; which works exactly the same way as in &lt;code&gt;Hash&lt;/code&gt; there is a &lt;code&gt;release_proc&lt;/code&gt; which is invoked whenever an item is removed from the &lt;code&gt;LRUHash&lt;/code&gt; &amp;#8212; either via explicit delete operations like &lt;code&gt;delete&lt;/code&gt;, &lt;code&gt;delete_if&lt;/code&gt; and &lt;code&gt;clear&lt;/code&gt; or via the automated expiry which kicks in as soon as the &lt;code&gt;LRUHash&lt;/code&gt; reaches its maximum size.&lt;/p&gt;
&lt;h3&gt;How &lt;code&gt;LRUHash&lt;/code&gt; is used in the project&lt;/h3&gt;
&lt;p&gt;There are two &lt;code&gt;LRUHash&lt;/code&gt; instances in class &lt;code&gt;Coordinator&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;A storage for interaction processors,&lt;/li&gt;
	&lt;li&gt;A storage for &lt;code&gt;File&lt;/code&gt; objects.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first instance is used to limit the overall number of interactions which are kept in memory.  Once the &lt;code&gt;LRUHash&lt;/code&gt; is filled and a new interaction needs to be stored the least recently used one is expired and removed.&lt;/p&gt;
&lt;p&gt;The second one is needed because &lt;code&gt;InteractionProcessor&lt;/code&gt; instances keep their &lt;code&gt;File&lt;/code&gt; object open and the limit for open file handles per process is usually much lower than the reasonable limit for interactions kept in memory.  So &lt;code&gt;File&lt;/code&gt; objects are stored in the &lt;code&gt;LRUHash&lt;/code&gt; and closed whenever necessary and reopened as well.&lt;/p&gt;
&lt;h3&gt;Why do you use &lt;code&gt;equal?&lt;/code&gt;?&lt;/h3&gt;
&lt;p&gt;There are no &amp;#8220;equivalent&amp;#8221; nodes in a single &lt;code&gt;LRUHash&lt;/code&gt; instance because they all have different keys.  Actually the concept of equivalence is not needed here; rather I just needed to check for &lt;em&gt;identity&lt;/em&gt; which is exactly what &lt;code&gt;equal?&lt;/code&gt; does.&lt;/p&gt;
&lt;h3&gt;Why did you not use PUPA&amp;#8217;s Ruby/Cache?&lt;/h3&gt;
&lt;p&gt;ged suggested in &lt;a href="http://blog.rubybestpractices.com/posts/rklemme/012-LRU-Integration.html#comment-12710034"&gt;his comment&lt;/a&gt; the use of &lt;a href="http://www.nongnu.org/pupa/ruby-cache.html"&gt;PUPA&amp;#8217;s Ruby/Cache&lt;/a&gt;.  I had looked at it before cooking &lt;a href="http://github.com/rklemme/muppet-laboratories/blob/739b688ebe27284b8239d486ac067d2b305a6b87/lib/lruhash.rb"&gt;my own little version&lt;/a&gt; and decided against using it for several reasons:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;It did not include the &lt;a href="http://ruby-doc.org/core/classes/Hash.html#M002854"&gt;default_proc mechanism of Ruby&amp;#8217;s Hash&lt;/a&gt; although you can use &lt;a href="http://www.nongnu.org/pupa/ruby-cache-MANUAL.html#label:43"&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/a&gt; with a block the same way as in &lt;a href="http://ruby-doc.org/core/classes/Hash.html#M002849"&gt;Hash&lt;/a&gt;.&lt;/li&gt;
	&lt;li&gt;It uses the notion of &amp;#8220;object size&amp;#8221; (explained &lt;a href="http://www.nongnu.org/pupa/ruby-cache-MANUAL.html#label:7"&gt;here&lt;/a&gt;) as one of the limits of cache size.  Besides the problems with defining &amp;#8220;object size&amp;#8221; which I pointed to &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/242080"&gt;here&lt;/a&gt; and &lt;a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/329527"&gt;here&lt;/a&gt; the more crucial reason was the problem with updating the cache&amp;#8217;s idea of the current size of objects (either the overhead is significant, because every time the overall size limit is checked all objects need to be looked at or the cache cannot be aware of size changes if it caches object sizes).&lt;/li&gt;
	&lt;li&gt;It uses wall clock expiration time for cached objects &amp;#8212; something I did not have use for in my implementation.&lt;/li&gt;
	&lt;li&gt;The fun of cooking my own.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;While items 2 and 3 could be remedied by using arbitrary large limits the overhead of calculating values would remain (at least the &lt;a href="http://www.nongnu.org/pupa/ruby-cache-MANUAL.html"&gt;documentation&lt;/a&gt; does not state that the overhead is saved when any of these limits are left out).&lt;/p&gt;
&lt;h3&gt;Performance Observations&lt;/h3&gt;
&lt;p&gt;While I did not actually measure timings the current version is significantly slower than the first draft version which kept everything in memory before writing out interactions to individual files.  I suspect that this may be caused by these factors:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Criterion evaluation is done multiple times per interaction (although it&amp;#8217;s still a dummy currently).&lt;/li&gt;
	&lt;li&gt;Frequent opening and closing of files caused by &lt;span class="caps"&gt;LRU&lt;/span&gt; handling of IO objects which is necessary because of the much lower limit of open file handles compared with interaction instances.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Both were introduced to get rid of log file lines as soon as possible.  This also lead to a complex design (especially in the area of evaluation of the criterion).  The effect may change though if real criteria are used.  This is certainly something that I need to analyze.&lt;/p&gt;
&lt;p&gt;An improved version would probably get rid of the immediate writing of lines as soon as possible and defer that to the point in time when the interaction is removed from the &lt;span class="caps"&gt;LRU&lt;/span&gt; cache of interactions.  That way the criterion needs to be executed only once, can be made much simpler &amp;#8212; especially for complex criteria which need to look at multiple entries such as the time range criterion.  Also, we do not need to keep multiple files open.&lt;/p&gt;
&lt;p&gt;&lt;i&gt;Note: This shows how important it is to keep an open mind and to think again about the code you have written from time to time.  I have discovered quite a bit of quirks I put into my code by this.  Of course you can say that if you do it right the first time, this is never necessary &amp;#8212; but who would claim to write optimal code in the first attempt?&lt;/i&gt;&lt;/p&gt;
&lt;h3&gt;Finally, a Best Practice&lt;/h3&gt;
&lt;p&gt;During my vacation I read &lt;a href="http://en.wikipedia.org/wiki/Zen_and_the_Art_of_Motorcycle_Maintenance"&gt;Zen and the Art of Motorcycle Maintenance&lt;/a&gt; (you can &lt;a href="http://www.virtualschool.edu/mon/Quality/PirsigZen/"&gt;browse the text&lt;/a&gt; but I&amp;#8217;d rather read a real book).  I had read it some 15 years ago and wanted to go back to this fascinating text which provides so many perspectives and crystallization points for thought.&lt;/p&gt;
&lt;p&gt;Now, what does this have to do with Ruby?  The best practice here is: once in a while do something completely different.  It helps keep your mind flexible and will open it up to new approaches to old matters as well as inspire your creativity.  You will also notice, that while you&amp;#8217;re away from your everyday business your mind will actually continue to work on it which typically shows by suddenly having an idea that turns up when you least expect it.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Fri, 31 Jul 2009 16:33:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/013-LRU-Explanations.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/013-LRU-Explanations.html</guid></item><item><title>LRU Integration</title><description>&lt;p&gt;This will be just a short article since I am a bit tight on time right now.&lt;/p&gt;
&lt;p&gt;For those of you who might not have heard the term &amp;#8220;&lt;span class="caps"&gt;LRU&lt;/span&gt;&amp;#8221; means &amp;#8220;least recently used&amp;#8221;.  It refers to a &lt;a href="http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used"&gt;replacement strategy&lt;/a&gt; used in caches.  For every cache with an upper limit on the number of elements cached it must be decided which element to remove from the cache once the cache gets full and another element should be put in the cache.  The decision can have dramatic impacts on the efficiency of the cache (its hit ratio).&lt;/p&gt;
&lt;p&gt;&lt;span class="caps"&gt;LRU&lt;/span&gt; is easy to implement and works pretty well in many cases so I picked that one.  &amp;#8220;&lt;span class="caps"&gt;LRU&lt;/span&gt;&amp;#8221; means, remove the element which has not been used for the longest time.  This is typically implemented using a doubly linked list because with that elements can be moved to the head very quickly (O(1)).  The algorithm works by moving every accessed element to the front of the list and deleting the last one when space is needed.&lt;/p&gt;
&lt;p&gt;I created a class with a &lt;code&gt;Hash&lt;/code&gt; like interface and an additional feature, a &lt;code&gt;release_proc&lt;/code&gt; which gets called with the removed entry&amp;#8217;s key and value.  That way we can automate the cleanup process easily.&lt;/p&gt;
&lt;p&gt;Internally the class has a Hash for fast access which has list nodes as values.  These are the main methods for &lt;span class="caps"&gt;LRU&lt;/span&gt; mechanism during read access.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def fetch(key, &amp;amp;b)
    n = @h[key]

    if n
      # hit -&amp;gt; move to front
      front(n).value
    else
      (b || FETCH)[key]
    end
  end

  # move node to front
  def front(node)
    node.insert_after(@head)
  end
&lt;/pre&gt;
&lt;p&gt;Individual entries are of class &lt;code&gt;Node&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # A single node in the doubly linked LRU list of nodes
  Node = Struct.new :key, :value, :pred, :succ do
    def unlink
      pred.succ = succ if pred
      succ.pred = pred if succ
      self.succ = self.pred = nil
      self
    end

    def insert_after(node)
      raise 'Cannot insert after self' if equal? node
      return self if node.succ.equal? self

      unlink

      self.succ = node.succ
      self.pred = node

      node.succ.pred = self if node.succ
      node.succ = self

      self
    end
  end
&lt;/pre&gt;
&lt;p&gt;And here&amp;#8217;s the code for the removal of old entries:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def store(key, value)
    # same optimization as in Hash
    key = key.dup.freeze if String === key &amp;amp;&amp;amp; !key.frozen?

    n = @h[key]

    unless n
      if size == max_size
        # reuse node to optimize memory usage
        n = delete_oldest
        n.key = key
        n.value = value
      else
        n = Node.new key, value
      end

      @h[key] = n
    end

    front(n).value = value
  end

  # remove the node and invoke the cleanup proc
  # if set
  def remove_node(node)
    n = @h.delete(node.key)
    n.unlink
    release_proc and release_proc[n.key, n.value]
    n
  end

  # remove the oldest node returning the node
  def delete_oldest
    n = @tail.pred
    raise "Cannot delete from empty hash" if @head.equal? n
    remove_node n
  end
&lt;/pre&gt;
&lt;p&gt;You can see the whole story in the &lt;a href="http://github.com/rklemme/muppet-laboratories/tree/master"&gt;git repo&lt;/a&gt; where the &lt;code&gt;LRUHash&lt;/code&gt; is also integrated into the main animal code.  Class &lt;code&gt;InteractionProcessor&lt;/code&gt; has changed a bit as well as &lt;code&gt;Coordinator&lt;/code&gt;.  Some places are still a bit inelegant but that will have to wait until I have a bit more time.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Fri, 10 Jul 2009 21:07:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/012-LRU-Integration.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/012-LRU-Integration.html</guid></item><item><title>25th Post!</title><description>&lt;p&gt;This is the 25th post to &lt;span class="caps"&gt;RBP&lt;/span&gt; blog!  Hooray!&lt;/p&gt;
&lt;p&gt;We&amp;#8217;ve been really happy with how things have gone so far.  Conversations have been for the most part civil and lively, we haven&amp;#8217;t run out of content, and the blog has seen new content nearly every week.&lt;/p&gt;
&lt;p&gt;I know that we aren&amp;#8217;t seeing as many voices on a week to week basis as we hoped for, but let&amp;#8217;s face it, people are bound to get busy.  That having been said, it&amp;#8217;d be great to know what readers are thinking about our content so far.&lt;/p&gt;
&lt;p&gt;So, what do you think?  Ranging from technical issues to ones of personal taste, it&amp;#8217;d be nice to know what keeps &lt;span class="caps"&gt;RBP&lt;/span&gt; in your feed reader, and what we can do to keep it there.  All feedback is welcome, so go ahead and let us know what&amp;#8217;s on your mind.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;ve got a great idea for a post, a series, or just some minor nitpick you want to voice, go for it.  So far we&amp;#8217;ve gained a lot from user responses, so I&amp;#8217;d like to keep with that tradition and keep the feedback loop tight.&lt;/p&gt;
&lt;p&gt;Now that you&amp;#8217;ve seen 25 posts, how should the next 25 look?&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 07 Jul 2009 05:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/010-twenty-five.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/010-twenty-five.html</guid></item><item><title>Code Blocks: Ruby's Swiss Army Knife</title><description>&lt;p&gt;&lt;b&gt;The following blog post is a direct excerpt from the &lt;a href="http://oreilly.com/catalog/9780596523008/"&gt;Ruby Best Practices&lt;/a&gt; book.  If you&amp;#8217;ve been enjoying this blog, you&amp;#8217;d probably love the book, so I&amp;#8217;ve decided to release some content here to give you a sense of what to expect.  Enjoy!&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;UPDATE&lt;/span&gt;: For those coming from other languages, Ruby&amp;#8217;s &lt;a href="http://en.wikipedia.org/wiki/Ruby_%28programming_language%29#Blocks_and_iterators"&gt;code blocks&lt;/a&gt; are inherently &lt;a href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29"&gt;closures&lt;/a&gt; , and provide syntactic sugar for methods that accept &lt;tt&gt;Proc&lt;/tt&gt; objects (Ruby&amp;#8217;s anonymous functions).  While not strictly necessary for understanding this article, a solid grasp on what closures are and how they work will take you far.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;In Ruby, code blocks are everywhere. If you&#8217;ve ever used &lt;tt&gt;Enumerable&lt;/tt&gt;, you&#8217;ve worked with blocks. But what are they? Are they simply iterators, working to abstract away our need for the for loop? They certainly do a good job of that:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; ["Blocks","are","really","neat"].map { |e| e.upcase } 
  =&amp;gt; ["BLOCKS", "ARE", "REALLY", "NEAT"]
&lt;/pre&gt;
&lt;p&gt;But other blocks don&#8217;t really iterate over collections&#8212;they just do helpful things for us. For example, they allow us to write something like:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  File.open("foo.txt","w") { |f| f &amp;lt;&amp;lt; "This is sexy" } 
&lt;/pre&gt;
&lt;p&gt;instead of forcing us to write this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  file = File.open("foo.txt","w") 
  file &amp;lt;&amp;lt; "This is tedious" 
  file.close 
&lt;/pre&gt;
&lt;p&gt;So blocks are useful for iteration, and also useful for injecting some code between pre-processing and post-processing operations in methods. But is that all they&#8217;re good for? Sticking with Ruby built-ins, we find that isn&#8217;t the case. Blocks can also shift our scope temporarily, giving us easier access to places we want to be:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
 "This is a string".instance_eval do 
    "O hai, can has reverse? #{reverse}. kthxbye" 
  end 
  #=&amp;gt; "O hai, can has reverse? gnirts a si sihT. kthxbye" 
&lt;/pre&gt;

&lt;p&gt;But blocks aren&#8217;t necessarily limited to code that gets run right away and then disappears. They can also form templates for what to do down the line, springing to action when called for:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; foo = Hash.new { |h,k| h[k] = [] } 
  =&amp;gt; {} 
  &amp;gt;&amp;gt; foo[:bar] 
  =&amp;gt; [] 
  &amp;gt;&amp;gt; foo[:bar] &amp;lt;&amp;lt; 1 &amp;lt;&amp;lt; 2 &amp;lt;&amp;lt; 3 
  =&amp;gt; [1, 2, 3] 
  &amp;gt;&amp;gt; foo[:baz] 
  =&amp;gt; [] 
&lt;/pre&gt;
&lt;p&gt;So even if we label all methods that accept a block as iterators, we know the story runs deeper than that. With this in mind, we can leverage some basic techniques to utilize any of the approaches shown here, as well as some more advanced tricks. By doing things in a way that is consistent with Ruby itself, we can make life easier for our users. Rather than piling on new concepts, we can allow them to reuse their previous knowledge. Let&#8217;s take a look at a few examples of how to do that now.&lt;/p&gt;
&lt;h3&gt;Working with Enumerable&lt;/h3&gt;
&lt;p&gt;The most common use of blocks in Ruby might be the most trivial. The following class implements a basic sorted list, and then mixes in the &lt;tt&gt;Enumerable&lt;/tt&gt; module. The block magic happens in &lt;tt&gt;each()&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class SortedList 
    include Enumerable 
  
    def initialize 
      @data = [] 
    end 
  
    def &amp;lt;&amp;lt;(element) 
      (@data &amp;lt;&amp;lt; element).sort! 
    end 
  
    def each 
      @data.each { |e| yield(e) } 
    end 
  end
&lt;/pre&gt;
&lt;p&gt;Our &lt;tt&gt;each()&lt;/tt&gt; method simply walks over each element in our &lt;tt&gt;@data&lt;/tt&gt; array and passes it through the block provided to the method by calling yield. The resulting iterator works exactly the same as &lt;tt&gt;Array#each&lt;/tt&gt; and &lt;tt&gt;Hash#each&lt;/tt&gt; and all the Ruby built-ins, and indeed simply wraps &lt;tt&gt;Array#each&lt;/tt&gt; in this case:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; a = SortedList.new 
  =&amp;gt; #&amp;lt;SortedList:0x5f0e74 @data=[]&amp;gt; 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 4 
  =&amp;gt; [4] 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 5 
  =&amp;gt; [4, 5] 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 1 
  =&amp;gt; [1, 4, 5] 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 7 
  =&amp;gt; [1, 4, 5, 7] 
  &amp;gt;&amp;gt; a &amp;lt;&amp;lt; 3 
  =&amp;gt; [1, 3, 4, 5, 7] 
  &amp;gt;&amp;gt; x = 0 
  =&amp;gt; 0 
  &amp;gt;&amp;gt; a.each { |e| x += e } 
  =&amp;gt; [1, 3, 4, 5, 7] 
  &amp;gt;&amp;gt; x 
  =&amp;gt; 20
&lt;/pre&gt;
&lt;p&gt;This shouldn&#8217;t be surprising. What is really the interesting bit is that by including the module &lt;tt&gt;Enumerable&lt;/tt&gt;, we gain access to most of the other features we&#8217;re used to working with when processing Ruby&#8217;s built-in collections. Here are just a few examples:&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; a.map { |e| "Element #{e}" } 
  =&amp;gt; ["Element 1", "Element 3", "Element 4", "Element 5", "Element 7"] 
  &amp;gt;&amp;gt; a.inject(0) { |s,e| s + e } 
  =&amp;gt; 20 
  &amp;gt;&amp;gt; a.to_a 
  =&amp;gt; [1, 3, 4, 5, 7] 
  &amp;gt;&amp;gt; a.select { |e| e &amp;gt; 3 } 
  =&amp;gt; [4, 5, 7] 
&lt;/pre&gt;
&lt;p&gt;In a lot of cases, the features provided by &lt;tt&gt;Enumerable&lt;/tt&gt; will be more than enough for traversing your data. However, it&#8217;s often useful to add additional features that build on top of the the &lt;tt&gt;Enumerable&lt;/tt&gt; methods. We can show this by adding a simple reporting method to &lt;tt&gt;SortedList&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class SortedList 
    def report(head) 
      header = "#{head}\n#{'-'*head.length}" 
      body = map{|e| yield(e)}.join("\n") + "\n" 
      footer = "This report was generated at #{Time.now}\n" 
      [header, body, footer].join("\n") 
    end 
  end
&lt;/pre&gt;
&lt;p&gt;which, when run, produces output like this:&lt;/p&gt;
&lt;pre&gt;
&amp;gt;&amp;gt; puts a.report("So many fish") { |e| "#{e} fish" } 
  So many fish 
  ------------ 
  1 fish 
  3 fish 
  4 fish 
  5 fish 
  7 fish 
  This report was generated at 2008-07-22 22:47:20 -0400 
&lt;/pre&gt;
&lt;p&gt;Building custom iterators is really that simple. This provides a great deal of flexibility, given that the code block can execute arbitrary expressions and do manipulations of its own as it walks across the elements. But as mentioned before, blocks can be used for more than just iteration.&lt;/p&gt;
&lt;h3&gt;Using Blocks to Abstract Pre- and Postprocessing&lt;/h3&gt;
&lt;p&gt;We looked at the block form of File.open() as an example of how blocks can provide an elegant way to avoid repeating tedious setup and teardown steps. However, files are surely not the only resources that need to be properly managed. Network I/O via sockets is another place where this technique can come in handy.&lt;/p&gt;
&lt;p&gt;On the client side, we&#8217;d like to be able to create a method that allows us to send a message to a server, return its response, then cleanly close the connection. The first thing that comes to mind is something simple like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require "socket" 

  class Client 

    def initialize(ip="127.0.0.1",port=3333) 
      @ip, @port = ip, port 
    end 

    def send_message(msg) 
      socket = TCPSocket.new(@ip,@port) 
      socket.puts(msg) 
      response = socket.gets 
    ensure 
      socket.close 
    end 
  
  end
&lt;/pre&gt;
&lt;p&gt;This is reasonably straightforward, but what happens when we want to add another method that waits to receive a message back from the server?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require "socket" 
  
  class Client 
    
    def initialize(ip="127.0.0.1",port=3333) 
      @ip, @port = ip, port 
    end 
    
    def send_message(msg) 
      socket = TCPSocket.new(@ip,@port) 
      socket.puts(msg) 
      response = socket.gets 
    ensure 
      socket.close 
    end 
    
    def receive_message 
      socket = TCPSocket.new(@ip,@port) 
      response = socket.gets 
    ensure 
      socket.close 
    end 
  end
&lt;/pre&gt;
&lt;p&gt;This is starting to look messy, as we have repeated most of the code between &lt;tt&gt;send_message&lt;/tt&gt; and &lt;tt&gt;receive_message&lt;/tt&gt;. Ordinarily, we&#8217;d break off the shared code into a private method that the two could share, but the trouble here is that the difference between these two methods is in the middle, not in a single extractable chunk. This is where blocks come to the rescue:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require "socket" 

  class Client 
    def initialize(ip="127.0.0.1",port=3333) 
      @ip, @port = ip, port 
    end 
  
    def send_message(msg) 
      connection do |socket| 
        socket.puts(msg) 
        socket.gets 
      end 
    end 

    def receive_message 
      connection { |socket| socket.gets } 
    end
     
    private 
    
    def connection 
      socket = TCPSocket.new(@ip,@port) 
      yield(socket) 
    ensure 
      socket.close 
    end 
  
  end
&lt;/pre&gt;
&lt;p&gt;As you can see, the resulting code is a lot cleaner. As long as we use our &lt;tt&gt;connection()&lt;/tt&gt; method with a block, we won&#8217;t need to worry about opening and closing the &lt;tt&gt;TCPSocket&lt;/tt&gt;; it&#8217;ll handle that for us. This means we&#8217;ve captured that logic in one place, and can reuse it however we&#8217;d like.&lt;/p&gt;
&lt;p&gt;To make things a bit more interesting, let&#8217;s take a look at a simple server with which this code can interact, which gives us a chance to look at yet another way that blocks can be useful in interface design.&lt;/p&gt;
&lt;h3&gt;Blocks as Dynamic Callbacks&lt;/h3&gt;
&lt;p&gt;There is a lot of power in being able to pass around code blocks just like they were any other object. This allows for the capability of creating and storing dynamic callbacks, which can later be looked up and executed as needed.&lt;/p&gt;
&lt;p&gt;In order to play with our &lt;tt&gt;Client&lt;/tt&gt; code from the previous example, we&#8217;re going to create a trivial &lt;tt&gt;TCPServer&lt;/tt&gt; that attempts to match incoming messages against patterns to determine how it should respond. Rather than hardcoding behaviors into the server itself or relying on inheritance to handle responses, we will instead allow responses to be defined through ordinary method calls accompanied by a block. Our goal is to get an interface that looks like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  server = Server.new 

  server.handle(/hello/i) { "Hello from server at #{Time.now}" } 
  server.handle(/goodbye/i) { "Goodbye from server at #{Time.now}" } 
  server.handle(/name is (\w+)/) { |m| "Nice to meet you #{m[1]}!" } 

  server.run
&lt;/pre&gt;
&lt;p&gt;The first two examples are fairly simple, matching a single word and then responding with a generic message and timestamp. The third example is a bit more interesting, repeating the client&#8217;s name back in the response message. This will be accomplished by querying a simple &lt;tt&gt;MatchData&lt;/tt&gt; object, which is yielded to the block.&lt;/p&gt;
&lt;p&gt;Though making this work might seem like black magic to the uninitiated, a look at its implementation reveals that it is actually a fairly pedestrian task:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Server 
    
    def initialize(port=3333) 
      @server   = TCPServer.new('127.0.0.1',port) 
      @handlers = {} 
    end 
    
    def handle(pattern, &amp;amp;block) 
      @handlers[pattern] = block 
    end 
    
    def run 
      while session = @server.accept 
        msg = session.gets 
        match = nil 
        @handlers.each do |pattern,block| 
          if match = msg.match(pattern) 
            break session.puts(block.call(match)) 
          end 
        end 
        unless match 
          session.puts "Server received unknown message: #{msg}" 
        end 
      end 
    end
     
  end
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;handle()&lt;/tt&gt; method slurps up the provided block using the &lt;tt&gt;&amp;amp;block&lt;/tt&gt; syntax, and stores it in a hash keyed by the given pattern. When &lt;tt&gt;Server#run&lt;/tt&gt; is called, an endless loop is started that waits for and handles client connections. Each time a message is received, the hash of handlers is iterated over. If a pattern is found that matches the message, the associated block is called, providing the match data object so that the callback can respond accordingly.&lt;/p&gt;
&lt;p&gt;If you&#8217;d like to try this out, use the following code to spin up a server:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  server = Server.new 
  server.handle(/hello/i) { "Hello from server at #{Time.now}" } 
  server.handle(/goodbye/i) { "Goodbye from server at #{Time.now}" } 
  server.handle(/name is (\w+)/) { |m| "Nice to meet you #{m[1]}!" } 
  server.run
&lt;/pre&gt;
&lt;p&gt;Once you have that running and listening for connections, execute the following client code:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  client = Client.new 
  
  ["Hello", "My name is Greg", "Goodbye"].each do |msg| 
    response = client.send_message(msg) 
    puts response 
  end 
&lt;/pre&gt;
&lt;p&gt;You will get back something like this:&lt;/p&gt;
&lt;pre&gt;
  Hello from server at Wed Jul 23 16:15:37 -0400 2008 
  Nice to meet you Greg! 
  Goodbye from server at Wed Jul 23 16:15:37 -0400 2008 
&lt;/pre&gt;
&lt;p&gt;It would be easy to extend both the client and server to do more interesting things that build on this very simple foundation. Feel free to take a few minutes to play around with that, and then we&#8217;ll look at one more block trick that&#8217;s fairly common in Ruby.&lt;/p&gt;
&lt;h3&gt;Blocks for Interface Simplification&lt;/h3&gt;
&lt;p&gt;Does it feel like the word &#8220;server&#8221; is written too many times in this code?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  server = Server.new 
  server.handle(/hello/i) { "Hello from server at #{Time.now}" } 
  server.handle(/goodbye/i) { "Goodbye from server at #{Time.now}" } 
  server.handle(/name is (\w+)/) { |m| "Nice to meet you #{m[1]}!" } 
  server.run 
&lt;/pre&gt;
&lt;p&gt;When you see code like this, it might be a sign that you could do better. Although there are merits to this somewhat standard approach, we can cheat a little bit with blocks (of course) and make things prettier. It would be nice to be able to write this instead:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  Server.run do 
    handle(/hello/i) { "Hello from server at #{Time.now}" } 
    handle(/goodbye/i) { "Goodbye from server at #{Time.now}" } 
    handle(/name is (\w+)/) { |m| "Nice to meet you #{m[1]}!" } 
  end 
&lt;/pre&gt;
&lt;p&gt;As you may recall from an earlier example, it is possible to execute a block within the scope of an instantiated object in Ruby. Using this knowledge, we can implement this handy shortcut interface as a simple class method:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Server 
    # other methods same as before 
    def self.run(port=3333,&amp;amp;block) 
      server = Server.new(port) 
      server.instance_eval(&amp;amp;block) 
      server.run 
    end 
  end
&lt;/pre&gt;
&lt;p&gt;This is all you need to get the new interface running, and rounds off our quick exploration of the different ways that you can use blocks to improve your &lt;span class="caps"&gt;API&lt;/span&gt; design while simplifying your method implementations.  Let&amp;#8217;s recap with a few tips before we wrap up here.&lt;/p&gt;
&lt;h3&gt;Things to Remember&lt;/h3&gt;
&lt;p&gt;Keep the following things in mind when using blocks as part of your interface:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;If you create a collection class that you need to traverse, build on top of Enumerable rather than reinventing the wheel.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;If you have shared code that differs only in the middle, create a helper method that yields a block in between the pre/postprocessing code to avoid duplication of effort.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;If you use the &amp;amp;block syntax, you can capture the code block provided to a method inside a variable. You can then store this and use it later, which is very useful for creating dynamic callbacks.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;Using a combination of &amp;amp;block and instance_eval, you can execute blocks within the context of arbitrary objects, which opens up a lot of doors for highly customized interfaces.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;The return value of yield (and block.call) is the same as the return value of the provided block.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Did you enjoy this post?&lt;/h3&gt;
&lt;p&gt;If you had fun reading this, definitely consider picking up a copy of &lt;a href="http://oreilly.com/catalog/9780596523008/"&gt;Ruby Best Practices&lt;/a&gt; .  If you need more convincing, there is a whole &lt;a href="http://cdn.oreilly.com/books/9780596523008/Mastering_the_Dynamic_Toolkit.xml.pdf"&gt;sample chapter&lt;/a&gt; for you to check out in addition to this excerpt.  If you&amp;#8217;ve already picked up the book and are enjoying it, tell your friends, and consider leaving a review on the &lt;a href="http://www.amazon.com/gp/product/0596523009"&gt;Amazon product page&lt;/a&gt; .  If you don&amp;#8217;t have enough time for that, go help me win the &lt;a href="http://rubytrends.com/styles/book/trends/134"&gt;popularity contest&lt;/a&gt; over at RubyTrends, as there are several books that I admire that still need to be overcome :)&lt;/p&gt;
&lt;p&gt;As always, I welcome your thoughts and feedback.  Let me know what you think of the techniques shown here, or share your own personal favorite code block trick.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 07 Jul 2009 04:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/009-beautiful-blocks.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/009-beautiful-blocks.html</guid></item><item><title>Animal Interaction Processing</title><description>&lt;p&gt;As stated I intend to &lt;a href="http://blog.rubybestpractices.com/posts/rklemme/008-First_Design_Considerations.html#comment-10936141"&gt;exploit locality of interaction log messages&lt;/a&gt; by &lt;a href="http://blog.rubybestpractices.com/posts/rklemme/009-Shadow_of_the_Animal.html"&gt;using &lt;span class="caps"&gt;LRU&lt;/span&gt;&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used"&gt;cache algorithm&lt;/a&gt; and handle log lines as efficiently as possible.  The general concept looks like this:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Whenever a new interaction is seen in the log file, create a new &lt;code&gt;InteractionProcessor&lt;/code&gt; for it and put it in some storage which allows for fast access.&lt;/li&gt;
	&lt;li&gt;Any further processing of log lines read for a particular interaction is dealt with by that &lt;code&gt;InteractionProcessor&lt;/code&gt; instance.&lt;/li&gt;
	&lt;li&gt;The storage should have an upper limit on the number of entries and expire entries via a &lt;a href="http://en.wikipedia.org/wiki/Cache_algorithms"&gt;cache algorithm&lt;/a&gt; in order to avoid overusing memory.&lt;/li&gt;
	&lt;li&gt;To further reduce memory usage, write log lines of an interaction to the corresponding output file as soon as possible.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It should be immediately clear that this confronts us with a number of challenges we will now have to look at.&lt;/p&gt;
&lt;h3&gt;Challenge: Early Expiry&lt;/h3&gt;
&lt;p&gt;Considering that we do not have a means to detect the end of an interaction we can only rely on the expiry algorithmof our &lt;code&gt;InteractionProcessor&lt;/code&gt; storage.  This means, there is always the chance that an &lt;code&gt;InteractionProcessor&lt;/code&gt; is evicted from the storage although there are more log records to come for this interaction.  This situations becomes more likely if&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;the size limit of the storage is reduced,&lt;/li&gt;
	&lt;li&gt;the number of interactions which are active at one point in time increases.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The latter can be caused by high activity on the original system (many interactions are started in a time interval) or interactions having huge gaps (making them live longer).&lt;/p&gt;
&lt;p&gt;Now, what does it mean for our processing?  Since we can only detect the initial line of an interaction through the fact that there is not yet an interaction processor for this interaction, we may be in a situation that we believe this is a new interaction while in fact we have seen it already.  This may lead to wrong filtering results (for example, if the beginning timestamp of this interaction needs to be evaluated for filtering and the difference between the real first timestamp and the second &amp;#8220;first&amp;#8221; timestamp makes a difference).&lt;/p&gt;
&lt;p&gt;There are a few things that we can do:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Check the filesystem for this interaction and read previous log records into memory before continuing processing this interaction.&lt;/li&gt;
	&lt;li&gt;Remember all interaction ids along with their initial timestamps or with the file name to know whether an interaction has been seen already and to find it efficiently in the filesystem to read previous records (see 1).&lt;/li&gt;
	&lt;li&gt;Nothing.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Option 1 is very inefficient, because we do not know the initial timestamp and so must potentially search multiple directories.  Option 2 is dangerous because it does not impose any limits on the storage needed for interaction ids with their timestamps.  That leaves us with option 3 &amp;#8211; a seemingly bad choice on first sight.&lt;/p&gt;
&lt;p&gt;To comfort you let&amp;#8217;s try to find out &lt;em&gt;how&lt;/em&gt; dangerous it actually is to do nothing about it.  Assuming for the moment that &lt;code&gt;test-gen.rb&lt;/code&gt; has a realistic model of log files we will see in practice.  Now let&amp;#8217;s also hope I get the math right&amp;#8230;  Looking into the source code, you will see that the average time interval between two lines of a single interaction is 5 seconds:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
Timer = Struct.new :t do
  def tic
    self.t += rand(10_000) / 1000.0
  end
end
&lt;/pre&gt;
&lt;p&gt;Furthermore we see that there are 1000 new interactions per minute (variable &lt;code&gt;commands&lt;/code&gt;) or, put differently, a new interaction starts every 60ms.  Furthermore there are on average 5.5 (2 + 3.5) log records per interaction (note, I fixed the time distribution of start times which wasn&amp;#8217;t uniform in the first version of the generator):&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
while t &amp;lt; end_time
  # create new entries
  commands.times do
    id = generate_id
    tx.t = t + rand(60_000) / 1000.0

    entries.add(Entry.create(tx.t, id, 'START'))

    (2 + rand(8)).times do
      pick = rand(10)
      msg = pick == 0 ? MESSAGES.last : MESSAGES[pick % 2]
      entries.add(Entry.create(tx.tic, id, msg))
    end

    entries.add(Entry.create(tx.tic, id, 'END'))
  end

  # write entries of this minute
  entries.print t
  t += 60
end
&lt;/pre&gt;
&lt;p&gt;This means, the average life span of an interaction is 22.5 seconds (5 sec * (5.5 &amp;#8211; 1)).  So now, continuing with our average calculation, this means that there are roughly 375 new interactions in a 22.5 second interval (22.5 sec / 60ms).  So, for the average case keeping 400 &lt;code&gt;InteractionProcessors&lt;/code&gt; in memory is sufficient.  Of course we need to take into accound that this is just an average calculation and also does not cover temporary load surges but if we apply factor 100 (i.e. 40,000 storage limit) this still doesn&amp;#8217;t look like it will blast system memory and we should be safe for most situations (unfortunately my stochastic skills are totally rusty today, so if someone cares to calculate the likelyhood of failure that would be interesting to see).  Assuming that we need 0.5 KB per &lt;code&gt;InteractionProcessor&lt;/code&gt; because of log lines that need to be kept in memory we&amp;#8217;re at about 20 MB which isn&amp;#8217;t a lot of memory these days.&lt;/p&gt;
&lt;p&gt;To sum it up: with the formula &lt;code&gt;(avg entries - 1) * avg interval * new IA per minute / 60s&lt;/code&gt; we get the average number of interactions active at a time.  It turns out that for our sample log generator this is 375 which leaves a lot of headroom for the interaction processor storage.  Without diving into stochastics too much it is obvious that we are pretty safe if we do not implement a solution for dealing with interactions that were expired too early.&lt;/p&gt;
&lt;h3&gt;Challenge: How to keep as few log lines in memory as possible?&lt;/h3&gt;
&lt;p&gt;Since our concept includes getting rid of log lines from memory as soon as possible, we will have to look at how this might be achieved.  Remember, we want to only output interactions which are included in our filter criteria, which can be quite different and need to look at&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;interaction id,&lt;/li&gt;
	&lt;li&gt;initial timestamp,&lt;/li&gt;
	&lt;li&gt;last timestamp,&lt;/li&gt;
	&lt;li&gt;a string matched somewhere in any of the log lines.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It should be immediately clear that not all of these criteria can be evaluated when the initial line of an interaction is seen.  A simple matches / does not match logic won&amp;#8217;t help here.  We need a filter that can tell us &amp;#8220;matches&amp;#8221;, &amp;#8220;does not match&amp;#8221; and &amp;#8220;maybe matches&amp;#8221; where the first two answers must only be given if there is no new information (log lines) which can make it invalid.  So we will use a filter that returns any of &lt;code&gt;:yes&lt;/code&gt;, &lt;code&gt;:no&lt;/code&gt; or &lt;code&gt;:maybe&lt;/code&gt;.  This is our dummy filter, which also has a changed interface:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
    YES = Class.new do
      def first(iap, line, ts) :yes end
      def initial(iap, line, ts) :yes end
      def followup(iap, line) :yes end
    end.new
&lt;/pre&gt;
&lt;p&gt;We do not use the complete &lt;code&gt;InteractionProcessor&lt;/code&gt; as argument but add the current line and also the timestamp if needed.  This also leads to three processing states in our &lt;code&gt;InteractionProcessor&lt;/code&gt;: undecided, including, excluding.  We handle this using the &lt;a href="http://c2.com/cgi/wiki?StatePattern"&gt;state pattern&lt;/a&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class InteractionProcessor

    UNDECIDED = Class.new do
      def process_initial(iap, line, time_stamp)
        case iap.coord.filter.first(iap, line, time_stamp)
        when :yes
          # we'll improve this once LRU is there
          iap.entries &amp;lt;&amp;lt; Entry.new(time_stamp, line)
          INCLUDE
        when :no
          iap.entries.clear
          EXCLUDE
        when :maybe
          iap.entries &amp;lt;&amp;lt; Entry.new(time_stamp, line)
          self
        else
          raise 'Illegal return'
        end
      end

      def process(iap, line, time_stamp)
        case iap.coord.filter.initial(iap, line, time_stamp)
        when :yes
          # we'll improve this once LRU is there
          iap.entries &amp;lt;&amp;lt; Entry.new(time_stamp, line)
          INCLUDE
        when :no
          iap.entries.clear
          EXCLUDE
        when :maybe
          iap.entries &amp;lt;&amp;lt; Entry.new(time_stamp, line)
          self
        else
          raise 'Illegal return'
        end
      end

      def append_line(iap, line)
        case iap.coord.filter.followup(iap, line)
        when :yes
          # we'll improve this once LRU is there
          l = iap.entries.last and l.line &amp;lt;&amp;lt; line
          INCLUDE
        when :no
          iap.entries.clear
          EXCLUDE
        when :maybe
          l = iap.entries.last and l.line &amp;lt;&amp;lt; line
          self
        else
          raise 'Illegal return'
        end
      end
    end.new

    INCLUDE = Class.new do
      def process_initial(iap, line, time_stamp)
        iap.entries &amp;lt;&amp;lt; Entry.new(time_stamp, line)
        self
      end

      def process(iap, line, time_stamp)
        iap.entries &amp;lt;&amp;lt; Entry.new(time_stamp, line)
        self
      end

      def append_line(iap, line)
        l = iap.entries.last and l.line &amp;lt;&amp;lt; line
        self
      end
    end.new

    EXCLUDE = Class.new do
      def process_initial(iap, line, ts)
        self
      end

      def process(iap, line, ts)
        self
      end

      def append_line(iap, line)
        self
      end
    end.new

  # ...

    # Process the first line
    def process_initial(time_stamp, line)
      @state = @state.process_initial(self, line, time_stamp)
    end

    # Process an initial line
    def process(time_stamp, line)
      @state = @state.process(self, line, time_stamp)
    end

    # Append a continuation line to the last entry
    def append_line(line)
      @state = @state.append_line(self, line)
    end

  # ...

  end
&lt;/pre&gt;
&lt;h3&gt;Challenge: Number of Open File Descriptors&lt;/h3&gt;
&lt;p&gt;If we store 40,000 &lt;code&gt;InteractionProcessors&lt;/code&gt; in memory then the worst case with regard to file descriptors is that all have one open.  That&amp;#8217;s more than usually allowed for user processes.  We&amp;#8217;ll remedy this by using a &lt;span class="caps"&gt;LRU&lt;/span&gt; strategy here as well: we will have a set of open files and close the least recently used if we hit a fixed limit.  I will cover this in one of the next versions, when we&amp;#8217;ll have &lt;span class="caps"&gt;LRU&lt;/span&gt; handling integrated.  (Maybe there is even a gem we can reuse.)&lt;/p&gt;
&lt;h3&gt;Summary and Outlook&lt;/h3&gt;
&lt;p&gt;This has grown into a rather largish article but I wanted to cover &lt;code&gt;InteractionProcessor&lt;/code&gt; with reasonable completion.  Note, that we still do not have the &lt;span class="caps"&gt;LRU&lt;/span&gt; mechanics and a couple of other things so this class will change again.  Next articles will have to deal with &lt;span class="caps"&gt;LRU&lt;/span&gt; implementation if I do not find anything suitable and integration of that into the rest of the application.  Furthermore, I expect the implementation of the filtering to be one more complex and thus interesting piece.  Stay tuned.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Tue, 30 Jun 2009 16:30:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/011-Animal_Interaction.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/011-Animal_Interaction.html</guid></item><item><title>The Decorator Delegator Disco</title><description>&lt;p&gt;As promised, we&amp;#8217;re back with more design discussion and hopefully some interesting ideas.  Let&amp;#8217;s start with a quick recap of what has happened so far.&lt;/p&gt;
&lt;p&gt;First, &lt;a href="http://sandimetz.com/"&gt;Sandi Metz&lt;/a&gt; posted on her blog about &lt;a href="http://sandimetz.com/2009/06/ruby-case-statements-and-kindof.html"&gt;type specific coupling&lt;/a&gt; that a &lt;tt&gt;case&lt;/tt&gt; statement can introduce.  Her proposed solution encouraged us to pass the responsibilities down to the individual objects, which is certainly desirable.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.rubybestpractices.com/about/aaronp.html"&gt;Aaron Patterson&lt;/a&gt; got in the mix, pointing out the issues that can happen when you are too aggressive about adding methods to core Ruby.  When Sandi suggested that &lt;a href="http://en.wikipedia.org/wiki/Double_dispatch"&gt;Double Dispatch&lt;/a&gt; might be a way around this problem, Aaron responded with an &lt;a href="http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html"&gt;implementation using the visitor pattern&lt;/a&gt; to accomplish this sort of thing.&lt;/p&gt;
&lt;p&gt;I had not seen Aaron&amp;#8217;s initial work before setting out to solve the problem on my own, and ended up taking an entirely different path to get there.  I&amp;#8217;m not much of a patterns guy, but after I had a working implementation, it seems like the approach I took mostly represents a combination of &lt;a href="http://en.wikipedia.org/wiki/Delegation_pattern"&gt;Delegation&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Decorator_pattern"&gt;Decoration&lt;/a&gt; techniques.&lt;/p&gt;
&lt;h3&gt;A quick demo&lt;/h3&gt;
&lt;p&gt;I think this code will be easier to understand if I show how it is used right up front.  So here&amp;#8217;s a tiny slice to get started with:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module ActionView
    module Helpers 
       class Extensions
          extend Decoration
        
          decorator_for(Array) do
            def as_array
              self
            end
          end
        
          decorator_for(Object) do
            def as_array
              [self]
            end
          end
       end
     
       # totally incomplete, just returns decorated object
       def form_for(record_or_name_or_array, *args, &amp;amp;block)
         Extensions.decorate(record_or_name_or_array)
       end
    end
  end

  include ActionView::Helpers

  p form_for(:foo).as_array #=&amp;gt; [:foo]
  p form_for(Object.new).as_array #=&amp;gt; [#&amp;lt;Object:0x3f47ec&amp;gt;]
  p form_for([1,2,3]).as_array #=&amp;gt; [1,2,3]
&lt;/pre&gt;
&lt;p&gt;In the code above, I&amp;#8217;ve implemented Sandi&amp;#8217;s &lt;tt&gt;as_array&lt;/tt&gt; helper.  I left the actual &lt;tt&gt;form_for&lt;/tt&gt; implementation very incomplete, causing it just to return the decorated object.  This is for example purposes only, so you could see that we can indeed call &lt;tt&gt;as_array&lt;/tt&gt; successfully.&lt;/p&gt;
&lt;p&gt;Before we check out how this all works, here are two extra hints about what this approach is affording us.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  my_obj = [1,2,3]
  decorated = form_for(my_obj)
  
  p decorated.as_array #=&amp;gt; [1,2,3]
  
  # Raises NoMethodError
  [1,2,3].as_array
  
  # Also raises NoMethodError
  p my_obj.as_array 
&lt;/pre&gt;
&lt;p&gt;As you can see, if core extensions are like a meat cleaver, this approach is more like using a scalpel, no changes bleed out into unexpected places.  Now that we see how it is used, let&amp;#8217;s take a look under the hood of &lt;tt&gt;Decorate&lt;/tt&gt; to see how it is built.&lt;/p&gt;
&lt;h3&gt;The &lt;tt&gt;Decorate&lt;/tt&gt; module&lt;/h3&gt;
&lt;p&gt;Though fairly densely packed, the whole implementation of &lt;tt&gt;Decorate&lt;/tt&gt; is pretty tiny.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
require 'delegate'

# with minor tweaks from tjstankus
module Decoration
  def decorator_for(*types, &amp;amp;block)
    types.each do |type|
      decorators[type] = Module.new(&amp;amp;block)
    end
  end
 
  def decorators
    @decorators ||= {}
  end
 
  def decorate(target)
    obj = SimpleDelegator.new(target)
    
    # walk in reverse order so most specific patches get applied LAST
    target.class.ancestors.reverse.each do |a|
      if decorators[a]
        obj.extend(decorators[a])
      end
    end
    
    return obj
  end
end
&lt;/pre&gt;
&lt;p&gt;Here, we are taking advantage of &lt;tt&gt;SimpleDelegator&lt;/tt&gt;, a class provided from Ruby&amp;#8217;s &lt;i&gt;delegate&lt;/i&gt; standard library.  Here&amp;#8217;s a quick glimpse of how it works:&lt;/p&gt;
&lt;pre&gt;
&amp;gt;&amp;gt; require "delegate"
=&amp;gt; true

&amp;gt;&amp;gt; a = [1,2,3]
=&amp;gt; [1, 2, 3]

&amp;gt;&amp;gt; b = SimpleDelegator.new(a)
=&amp;gt; [1, 2, 3]
&amp;gt;&amp;gt; b &amp;lt;&amp;lt; 4
=&amp;gt; [1, 2, 3, 4]
&amp;gt;&amp;gt; b.delete_at(1)
=&amp;gt; 2

&amp;gt;&amp;gt; b
=&amp;gt; [1, 3, 4]
&amp;gt;&amp;gt; a
=&amp;gt; [1, 3, 4]

&amp;gt;&amp;gt; b.class
=&amp;gt; SimpleDelegator
&amp;gt;&amp;gt; a.class
=&amp;gt; Array
&lt;/pre&gt;
&lt;p&gt;Essentially, &lt;tt&gt;SimpleDelegator&lt;/tt&gt; provides an easy way to wrap an object within a proxy.  This gives us a convenient place to hang per-object behavior without mutating the original object.&lt;/p&gt;
&lt;pre&gt;
  &amp;gt;&amp;gt; def b.kitties
  &amp;gt;&amp;gt;   "MEEEOW"
  &amp;gt;&amp;gt; end
  &amp;gt;&amp;gt; b.kitties
  =&amp;gt; "MEEEOW"
  &amp;gt;&amp;gt; a.kitties
  NoMethodError: undefined method `kitties' for [1, 3, 4]:Array
  	from (irb):15
&lt;/pre&gt;
&lt;p&gt;You probably see where this is going now, so let&amp;#8217;s get back to &lt;tt&gt;Decorate&lt;/tt&gt; module.  If we look at &lt;tt&gt;decorator_for&lt;/tt&gt;, we can get a good sense of how all this magic comes together:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def decorator_for(*types, &amp;amp;block)
  types.each do |type|
    decorators[type] = Module.new(&amp;amp;block)
  end
end

def decorators
  @decorators ||= {}
end
&lt;/pre&gt;
&lt;p&gt;Here, we see that &lt;tt&gt;decorator_for&lt;/tt&gt; basically takes a type or list of types, and a block.  The block is then used to define the body of an anonymous module that gets stashed away in a hash for later use.  So going back to our example code, we see that the following definitions are actually module definitions.  They could have even been written this way:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Extensions
   extend Decoration
 
   module ArrayDecorator
     def as_array
       self
     end
   end
 
  module ObjectDecorator
     def as_array
       [self]
     end
  end
  
  decorators[Array]  = ArrayDecorator
  decorators[Object] = ObjectDecorator
end
&lt;/pre&gt;
&lt;p&gt;Of course, this lacks the necessary sugar shock, so I show it only to make the implementation clearer.  But now that we have a way to stack up modules with per-object behavior in them, and a place to hang that per-object behavior off of, we only need a mechanism to apply it. For this functionality, we turn to the &lt;tt&gt;decorate&lt;/tt&gt; method:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def decorate(target)
    obj = SimpleDelegator.new(target)
  
    # walk in reverse order so most specific patches get applied LAST
    target.class.ancestors.reverse.each do |a|
      if decorators[a]
        obj.extend(decorators[a])
      end
    end
  
    return obj
  end
&lt;/pre&gt;
&lt;p&gt;We want to be able to preserve the ability to use &lt;tt&gt;super&lt;/tt&gt; in our decorated method calls, and we definitely wanted to pick up extensions to objects higher in the inheritance chain without any duplication.  So this meant we needed to do something a little more complicated than key the target object&amp;#8217;s type directly to a decorator module.&lt;/p&gt;
&lt;p&gt;Rather than just picking the most recent ancestor, this code walks the chain in reverse order so that the modules can neatly stack on top of one another.  In short, this means that the decorator for &lt;tt&gt;Object&lt;/tt&gt; gets applied before the one for &lt;tt&gt;Array&lt;/tt&gt; so that you can emulate an inheritance relationship in your extensions.&lt;/p&gt;
&lt;p&gt;This pretty much sums up the whole implementation, so let&amp;#8217;s just take a look at one more example before evaluating the pros and cons of this approach.&lt;/p&gt;
&lt;h3&gt;An alternative to core extensions&lt;/h3&gt;
&lt;p&gt;Here is a bit of code that completely covers the &lt;a href="http://github.com/skmetz/rails/blob/cffbc4399288be2fb7e15f67680089dbb36a7152/actionpack/lib/action_view/helpers/form_helper_core_extensions.rb"&gt;core extensions&lt;/a&gt; that Sandi needed for her &lt;a href="http://github.com/skmetz/rails/commit/cffbc4399288be2fb7e15f67680089dbb36a7152"&gt;Rails patch&lt;/a&gt;, without the core extensions:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;   
  class Extensions

     extend Decoration
     
     decorator_for Symbol, String do
       def form_object_name
         self
       end

       def as_fields_for_form_object(args)
         args.first
       end

       def acts_like_model?
         false
       end
     end

     decorator_for Array do
       def as_form_object
         last
       end

       def as_array
         self
       end
     end

     decorator_for Object do
       def as_form_object
         self
       end

       def as_fields_for_form_object(args)
         as_form_object
       end

       def form_object_name
         ActionController::RecordIdentifier.singular_class_name(self)
       end

       def as_array
         [self]
       end

       def acts_like_model?
         true
       end
     end
     
  end
&lt;/pre&gt;
&lt;p&gt;You would use the same approach I suggested before to wire this up, something like &lt;tt&gt;Extensions.decorate(my_obj)&lt;/tt&gt;&lt;/p&gt;
&lt;h3&gt;Pros for this solution&lt;/h3&gt;
&lt;p&gt;There are definitely things about this technique that I like.  The obvious benefit is that it prevents core hackery, and even goes a step beyond something like &lt;tt&gt;my_object.extend(SomethingSpecial)&lt;/tt&gt;, since it only extends behavior into a throwaway proxy object.&lt;/p&gt;
&lt;p&gt;Another clear benefit is that defining extensions is about as easy as it is to do raw core extensions.  Because the blocks are used as module definitions, you can do pretty much anything you&amp;#8217;d ordinarily do when defining methods.  This lowers the amount of &amp;#8216;special stuff&amp;#8217; you need to remember.&lt;/p&gt;
&lt;p&gt;Perhaps the most interesting thing however, is that this approach can be used to apply customized behavior to several types of objects at once, and can also be used to apply behaviors based on what mixins are included in an object.  This means there is nothing stopping you from doing something like &lt;tt&gt;decorator_for(Enumerable)&lt;/tt&gt; or &lt;tt&gt;decorator_for(Comparable)&lt;/tt&gt;, which provides you a little extra flexibility beyond the traditional inheritance hierarchy.&lt;/p&gt;
&lt;p&gt;Another interesting aspect of this is that decorators can be implemented at a per-module (or per-class) level, which means that different libraries can have different extensions without interfering with each other.&lt;/p&gt;
&lt;p&gt;Keep in mind, it&amp;#8217;s not all roses.  Let&amp;#8217;s take a look at some of the pitfalls.&lt;/p&gt;
&lt;h3&gt;Cons for this solution&lt;/h3&gt;
&lt;p&gt;A major drawback here is that we&amp;#8217;re still relying on types.  Whether its a class or module, we still expect an object to be a certain thing, which sort of goes against traditional duck typing in which we&amp;#8217;d rather make assumptions based on what an object can do rather than what it is.  So it might be nicer to apply these decorators based on what the target object responds to, not what ancestors it has.&lt;/p&gt;
&lt;p&gt;There is also the performance overhead factor.  I have not benchmarked yet, but I suspect that the cost of both building up a &lt;tt&gt;SimpleDelegator&lt;/tt&gt; and doing proxy calls is non-negligible.  While this may not be an issue in many cases, for code that needs to run in tight loop or be scaled heavily, this approach may be too heavy for its benefits to outweigh its costs.  But of course, this is a huge &lt;span class="caps"&gt;YMMV&lt;/span&gt; situation, and without hard numbers it&amp;#8217;s tough to say to what extent this would be a huge issue.&lt;/p&gt;
&lt;p&gt;Perhaps the most fatal flaw with the current setup is that &lt;tt&gt;respond_to?&lt;/tt&gt; gets delegated to the target object, so with the current implementation, unless you define &lt;tt&gt;respond_to?&lt;/tt&gt; yourself, it will not pick up any of your new methods.  I imagine that this is something that can be fixed, I just have not looked into it yet.&lt;/p&gt;
&lt;p&gt;Finally, there is the legitimacy problem.  As Sandi said in the comments on Aaron&amp;#8217;s article, &lt;a href="http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html#comment-11553586"&gt;sometimes a case statement is just a case statement&lt;/a&gt;.  If we go around filling all our code with high-architecture bazookas when all that was needed was a pen-knife, there are bound to be consequences.  Is this overkill or awesome?  I don&amp;#8217;t really know, and I imagine it depends on the situation.&lt;/p&gt;
&lt;h3&gt;Conclusions&lt;/h3&gt;
&lt;p&gt;When Aaron and I compared our solutions to Sandi&amp;#8217;s problem, we basically concluded that both of our approaches might be useful for different things.  Aaron&amp;#8217;s shines when dealing with providing type-specific implementations of a particular behavior, which is mostly just the visitor pattern shining through.  My approach is probably better for situations in which you need to collect several behaviors in one place.&lt;/p&gt;
&lt;p&gt;Ultimately, this may be a matter of preference, depending on whether you want to abstract things based on the method level or the object level.  Of course, sometimes neither is necessary, and that may be an important fact to remember.&lt;/p&gt;
&lt;p&gt;I am very much interested in what readers have to say.  Please check out &lt;a href="http://sandimetz.com/2009/06/ruby-case-statements-and-kindof.html"&gt;Sandi&amp;#8217;s article&lt;/a&gt; , then &lt;a href="http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html"&gt;Aaron&amp;#8217;s&lt;/a&gt; , then let me know here which approaches you might take along with their context.  If you have your own ideas that are totally different than ours, I want to know about that too.&lt;/p&gt;
&lt;p&gt;We need more conversations like these in our community, so let&amp;#8217;s start here and see where it takes us.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Sat, 27 Jun 2009 16:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/008-decorator-delegator-disco.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/008-decorator-delegator-disco.html</guid></item><item><title>The Animal raises its head</title><description>&lt;p&gt;You can find the first &lt;a href="http://github.com/rklemme/muppet-laboratories/blob/16dc8851554bf29cee37a0dd75a7869c99b10c7d/bin/sample-animal.rb"&gt;sample-animal.rb&lt;/a&gt; over there at &lt;a href="http://github.com/rklemme/muppet-laboratories/tree/master"&gt;github&lt;/a&gt;.  Deficits of this version:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;No command line parsing,&lt;/li&gt;
	&lt;li&gt;No filtering,&lt;/li&gt;
	&lt;li&gt;Works only for moderately sized files,&lt;/li&gt;
	&lt;li&gt;No particular optimizations yet (well, apart from freezing of id Strings).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One remark about method &lt;code&gt;main&lt;/code&gt;: this is the result of asking myself &amp;#8220;What is the minimal interface I can provide for users of the Animal and who basically only need to define the parser class?&amp;#8221;  At first I found it a bit odd, but in terms of lines of code this is likely one of the leanest solutions.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ll have to call it a day now, but I invite you to have a look and comment.  Do you consider method &lt;code&gt;main&lt;/code&gt; a good idea?  I&amp;#8217;ll chime in with some more explanations later.&lt;/p&gt;
&lt;p&gt;&lt;ins&gt;[Update:_]&lt;/ins&gt; If you are looking for the entry point of the implementation for the sample log you need to look into file &lt;code&gt;sample-animal.rb&lt;/code&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
#!/usr/local/bin/ruby19 -w

# Implementation of the parser for the sample
# generator script test-gen.rb.
$: &amp;lt;&amp;lt; File.join(File.dirname(File.dirname($0)), "lib")

require 'time'
require 'animal'

# main defines the custom parser class!
Animal.main do

  TIME_FORMAT = '%Y-%m-%d %H:%M:%S.%N'.freeze

  attr_accessor :year
  attr_reader :interaction_id, :time_stamp

  def parse(line)
    if %r{
       ^
       ( \d{4}-\d{2}-\d{2} \s \d{2}:\d{2}:\d{2}(?:\.\d+)? )
       \s+
       (\S+) # interaction_id
       \s+
       }x =~ line
      @time_stamp = Time.strptime $1, TIME_FORMAT
      @interaction_id = $2
    else
      @time_stamp = nil
      @interaction_id = nil
    end
  end

  def initial_line?
    time_stamp
  end
end

# EOF
&lt;/pre&gt;
&lt;p&gt;The intersting thing is: this is complete already!  As long as the file format does not change we won&amp;#8217;t have to touch this file any more.  Basically we only provide information about the log file format through the parser whose class is defined with the code block passed to main.  The rest &amp;#8211; command line argument parsing, creating of all necessary objects etc. is done in &lt;code&gt;main&lt;/code&gt; which is not much longer either:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
require 'ostruct'

# Namespace for all the Animal related classes
# Animal is the project on Ruby Best Practices
# blog which demonstrates the thought process
# of writing an application
module Animal

  # Parse the given command line and return an option instance.
  # Options are removed from the argument so what is left in
  # there must be file names.
  def self.parse_command_line(argv = ::ARGV) 
    o = OpenStruct.new(:output_dir =&amp;gt; ".")
    # parse
    o
  end

  # This metho allows to write extremely short applications
  # because it accepts a block which is used to define the
  # parser class.  Alternatively users can provide a parser
  # instance.  The default command line is added implicitly
  # and will be option parsed and the whole processing will
  # start automatically.
  def self.main(parser = nil, argv = ::ARGV, &amp;amp;class_body)
    $stderr.puts 'WARNING: ignoring class body' if parser &amp;amp;&amp;amp; class_body
    parser ||= Class.new(&amp;amp;class_body).new
    options = parse_command_line(argv)
    coord = Coordinator.new
    coord.parser = parser
    coord.options = options
    coord.process_files argv
  end

  # autoload init
  %w{
    Coordinator
    ProcessingStorage
    FileStatistics
    InteractionProcessor
  }.each do |cl|
    autoload cl, "animal/#{cl.gsub(/([a-z])([A-Z])/, '\\1_\\2').downcase}"
  end

end
&lt;/pre&gt;
&lt;p&gt;There is really not much magic in &lt;code&gt;main&lt;/code&gt; apart from (ab)using the method block as class body.  (Btw, this is something you can do with &lt;code&gt;Struct&lt;/code&gt; as well.  I&amp;#8217;ll write about that in a future post.)  I can&amp;#8217;t think of a leaner interface to get the job done but maybe someone out there has another idea.&lt;/p&gt;
&lt;p&gt;I had thought of defining a single regular expression with capturing group indexes for timestamp and key.  But then we might also need a way to specify timestamp conversion.  And then there are also file formats which have timestamps separated in time and date and even binary formats&amp;#8230;  This looks like an area we should revisit after v1.0 &amp;#8211; maybe there is some room for improvement.  For now we&amp;#8217;ll stick with the line oriented formats which should cover a pretty wide range &amp;#8211; including the requirements.&lt;/p&gt;
&lt;p&gt;I am also not convinced that the &lt;code&gt;autoload&lt;/code&gt; part is really that great.  Initially it looked like a good idea but now I am not sure any more: writing out class and file names is probably better readable and as easy as the automated class name to file name conversion hack.&lt;/p&gt;
&lt;p&gt;Now, what do you guys say?&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Mon, 22 Jun 2009 22:36:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/010-The_Animal_raises_its_Head.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/010-The_Animal_raises_its_Head.html</guid></item><item><title>Shadow of the Animal</title><description>&lt;p&gt;Let&amp;#8217;s recapitulate where we have been for readers who are new to the blog and for the convenience of others.  I &lt;a href="005_Enter_the_Muppet_Laboratories.html"&gt;started this&lt;/a&gt; a while ago as an experiment trying to give some insights into my way of reasoning.  I choose processing of large log files as subject which should help me analyze problems on production systems.  I do believe that this might also help others as log file analysis is a fairly common task.  The key point here is to be able to efficiently sift through many large logfiles and give access to the relevant information (see also the &lt;a href="007-Requirements.html"&gt;list of requirements&lt;/a&gt; and the &lt;a href="006-The_Muppet_Project.html"&gt;initial description&lt;/a&gt; of the scope).&lt;/p&gt;
&lt;p&gt;I picked &amp;#8220;Animal&amp;#8221; as name of the logfile analyzer because that must sift through tons of log data in a similar way as the &lt;a href="http://muppet.wikia.com/wiki/Animal"&gt;like named character&lt;/a&gt; of a &lt;a href="http://muppet.wikia.com/wiki/The_Muppet_Show"&gt;TV show&lt;/a&gt; treated his instrument &amp;#8211; ferociously.&lt;/p&gt;
&lt;p&gt;In today&amp;#8217;s article I will present some major design decisions.  Some core components of the architecture have been mentioned in the &lt;a href="008-First_Design_Considerations.html"&gt;previous article&lt;/a&gt; already so I won&amp;#8217;t repeat them here.&lt;/p&gt;
&lt;h3&gt;Design Decisions&lt;/h3&gt;
&lt;p&gt;As I want to give insights into my way of reasoning about software and design in particular I will list some of the major design decisions along with my rationale.&lt;/p&gt;
&lt;h4&gt;No class for individual log entries&lt;/h4&gt;
&lt;p&gt;The reasoning has been presented in a &lt;a href="008-First_Design_Considerations.html"&gt;previous article&lt;/a&gt;: I want to avoid the overhead of allocating short lived objects.  You can play around with a &lt;a href="http://github.com/rklemme/muppet-laboratories/tree/master"&gt;toy Java project&lt;/a&gt; (Eclipse as well as ant) to see the effect I was talking about.  I had up to 9% time difference between the straight version and the version which puts data in a special record class.&lt;/p&gt;
&lt;h4&gt;No meta data&lt;/h4&gt;
&lt;p&gt;I had pondered the option to use a two step approach with an initial analysis step which will generate meta data which then is used by another program to efficiently extract relevant information.  The advantage clearly would have been that we can apply a lot of different filtering and selection criteria without having to go through the initial analysis phase.  I have decided against for these reasons:&lt;/p&gt;
&lt;dl&gt;
	&lt;dt&gt;Easier propagation of relevant data&lt;/dt&gt;
	&lt;dd&gt;Others do not need the extraction program and the original log files to look at interactions,&lt;/dd&gt;
	&lt;dt&gt;Simpler software structure&lt;/dt&gt;
	&lt;dd&gt;Only one program is needed, no writing and reading of meta data needed,&lt;/dd&gt;
	&lt;dt&gt;More robust&lt;/dt&gt;
	&lt;dd&gt;A change in the location of the original logs does not affect analysis.&lt;/dd&gt;
&lt;/dl&gt;
&lt;h4&gt;Efficient Processing&lt;/h4&gt;
&lt;p&gt;This is the part I personally find most interesting: how do we manage to stream process log data while still limiting memory usage?  We cannot simply aggregate all interactions in a huge Hash and dump the interesting bits at the end because this will burn too much memory (which costs speed through paging) or even make the whole process fail completely.  That would be especially bad since in a case of lacking memory we would loose all the work that has been done up to the point.&lt;/p&gt;
&lt;p&gt;My idea for solving this involves two components:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;A hash based storage with &lt;span class="caps"&gt;LRU&lt;/span&gt; semantics,&lt;/li&gt;
	&lt;li&gt;An interaction processor.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Basically the &lt;span class="caps"&gt;LRU&lt;/span&gt; storage is responsible for keeping only a limited number of interaction processors in memory while the interaction processor is responsible for dealing as efficiently as possible with a single interaction.  This means, the interaction processor will have to efficiently decide whether an interaction is included in the output and write out log lines as soon as possible (!) to a file in a given location.&lt;/p&gt;
&lt;h4&gt;Output Storage&lt;/h4&gt;
&lt;p&gt;Every interaction will be stored in its own file.  To avoid potential issues with file systems becoming inefficient with thousands of files we will use an output directory tree with these levels:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;date, formatted &lt;span class="caps"&gt;YYYY&lt;/span&gt;-MM-DD (example &amp;#8216;2006-06-21&amp;#8217;),&lt;/li&gt;
	&lt;li&gt;hour and minute, two digit 24 hour clock and minute (example &amp;#8216;19-11&amp;#8217;).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Interaction file names will include the timestamp of the first record.  The naming will be like this: &amp;#8220;SS.&lt;span class="caps"&gt;SSS&lt;/span&gt;-&lt;interaction id&gt;&amp;#8221; where &amp;#8220;SS&amp;#8221; are the seconds of the timestamp and &amp;#8220;&lt;span class="caps"&gt;SSS&lt;/span&gt;&amp;#8221; are milliseconds&amp;quot;.  A valid name might then look like this &lt;code&gt;2009-06-21/19-11/00.003-sdmyrsmmlbxodfd&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The advantage is that we will not face any filesystem issues because there will be only a few thousand entries per minute.  Plus, because of the hierarchical naming of directories and files we can easily use textual sorting of names and get chronological output.  If we discover that there are too many entries per minute we can still extend the schema pretty easily to include a directory level for seconds.&lt;/p&gt;
&lt;h3&gt;Structure&lt;/h3&gt;
&lt;p&gt;The structure of the application will look like this: there is an option parsing method which outputs options which contain a combination of all processing options.  These options will be hand off to the Coordinator which is the main driver of the processing.  The Coordinator also needs a Parser instance which is capable of parsing log lines and providing interaction_id as well as a time_stamp of the last parsed entry.  The coordinator will create InteractionProcessors as needed and hold them in a structure keyed by interaction_id.  Each InteractionProcessor will handle a single interaction only.  It knows the coordinator through which it gains access to options and a filter evaluator which determines whether an interaction is included; this filter works on the InteractionProcessor.&lt;/p&gt;
&lt;h3&gt;Thought Process&lt;/h3&gt;
&lt;p&gt;Now you might wonder how I arrived at these decisions.  Well, I wanted the resulting bit of software to get the job done simply and efficiently.  Generating a whole lot of meta data which helps in finding interactions efficiently would have created additional complexity as I have pointed out.  So it was logical to rather choose a grepish approach, i.e. read the input once and spit out everything that we are interested in.&lt;/p&gt;
&lt;p&gt;Since volume of input data is large we cannot expect to hold all the input in memory at some point in time.  So we would rather have to pick a streaming approach.  This means, we can only hold as many entities in memory at a time.  Luckily, log entries of a single interaction have high locality, i.e. whenever the first occurs follow up lines are not too far away and the interaction end is usually near as well.&lt;/p&gt;
&lt;p&gt;Now, I considered two approaches for aging out interactions from the processor&amp;#8217;s storage: timestamp based and access based.  I picked access based because in reality there are some interactions which take a bit longer than the usual interaction which would make picking a high latency necessary.  This in turn would keep short interactions longer in memory than necessary.  Also, with this approach you cannot put a hard numeric limit on the number of interactions in memory which could lead to failures for some logs while other logs are processed ok.  With a &lt;span class="caps"&gt;LRU&lt;/span&gt; based storage we can set a size limit and avoid this problem.  Of course, long interactions which also have many log entries could still cause memory issues but since these are comparatively rare the likelyhood of issues is small.&lt;/p&gt;
&lt;p&gt;I will now wander off hacking together a rough application which does not yet do much but should give you an idea of how all the pieces are supposed to work together.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Sun, 21 Jun 2009 19:36:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/009-Shadow_of_the_Animal.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/009-Shadow_of_the_Animal.html</guid></item><item><title>The Double Dispatch Dance</title><description>&lt;p&gt;&lt;i&gt;&lt;span class="caps"&gt;EDITORIAL&lt;/span&gt; &lt;span class="caps"&gt;NOTE&lt;/span&gt;: This is the first of hopefully many guest posts to the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog.  If you are interested in writing an article for us, contact any of the &lt;span class="caps"&gt;RBP&lt;/span&gt; bloggers for details on how to submit content.&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://sandimetz.com/"&gt;Sandi Metz&lt;/a&gt; recently blogged &lt;a href="http://sandimetz.com/2009/06/ruby-case-statements-and-kindof.html"&gt;about ruby case statements being similar to calling is_a?&lt;/a&gt; on a particular object, and how we should be using duck typing rather than inspecting the type of the class. Her solution was to add methods to some core classes so that they all &amp;#8220;quacked&amp;#8221; the same way.&lt;/p&gt;
&lt;p&gt;I completely agree with Sandi&amp;#8217;s sentiments, but at the same time, I don&amp;#8217;t like reopening core classes, so I wanted to see if I could accomplish the same task, but minimize my impact on any core classes. The way I chose to accomplish this task is with the &lt;a href="http://en.wikipedia.org/wiki/Double_dispatch"&gt;double dispatch&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Visitor_pattern"&gt;visitor pattern&lt;/a&gt; .&lt;/p&gt;
&lt;h3&gt;Double Dispatch&lt;/h3&gt;
&lt;p&gt;The way the double dispatch pattern works is by adding a method to each object that should know how to double dispatch. That method takes one argument, and calls a method on the argument passing itself in. In my solution, I called the method &amp;#8220;accept&amp;#8221;, and I want all objects to do double dispatch, so I&amp;#8217;ve added that method to Object:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  ##
  # The visitable module makes a class "visitable". It follows the double 
  # dispatch pattern and simply calls "visit" on the argument with itself.
  module Visitable
    def accept visitor
      visitor.visit self
    end
  end

  ##
  # For this example, we want to make *all* objects visitable, so we'll mix 
  # the Visitable module in to Object.
  class Object
    include Visitable
  end
&lt;/pre&gt;
&lt;p&gt;Excellent, but what does this buy me? It gives me an entry point and common interface for dispatching a method based on the object I am visiting. I just implement an object that responds to &amp;#8220;visit&amp;#8221; and that methods knows how to dispatch.&lt;/p&gt;
&lt;h3&gt;Our Dispatching Visitor&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;ve implemented a class that responds to &amp;#8220;visit&amp;#8221;, and based on the type of the object, dispatches to a particular method. If a string is passed in to the &amp;#8220;visit&amp;#8221; method, it will try to dispatch the object to &amp;#8220;visit_String&amp;#8221;. If &amp;#8220;visit_String&amp;#8221; is not defined, it will try look at the string&amp;#8217;s ancestor list trying to find a place to dispatch. If it can&amp;#8217;t dispatch, an exception is raised. My Visitor base class also has a helper method &amp;#8220;visitor_for&amp;#8221; to help define handlers.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
##
# The Visitor class is our base class for all visitors.  It implements the
# "visit" method which Object#accept will call.
class Visitor
  ###
  # Dynamically create a visitor method for each class in +klasses+
  def self.visitor_for *klasses, &amp;amp;block
    klasses.each do |klass|
      define_method(:"visit_#{klass.name}", block)
    end
  end

  ##
  # This method will examine the class and ancestors of +thing+. For each
  # class in the "ancestors" list, it will check to see if the visitor knows
  # how to handle that particular class. If it can't find a handler for the
  # +thing+ it will raise an exception.
  def visit thing
    thing.class.ancestors.each do |ancestor|
      method_name = :"visit_#{ancestor.name}"
      next unless respond_to? method_name
      return send method_name, thing
    end

    raise "Can't handle #{thing.class}"
  end
end
&lt;/pre&gt;
&lt;p&gt;My base Visitor class is not really of much use at this point. All it knows how to do is accept an object and try to send a method based on the type. Let&amp;#8217;s take a look at a visitor that will convert any object to an array.&lt;/p&gt;
&lt;h3&gt;Array Conversion Visitor&lt;/h3&gt;
&lt;p&gt;One of the tasks is to convert any object in to an array. I can write a Visitor class that has one responsibility; turning any object in to an Array. The rules for this conversion are easy. If the object is an array, return the array, if it&amp;#8217;s something else, return that thing inside an array:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require 'visitor'
 
  ##
  # This Visitor knows how to turn any object in to an Array
  class AsArray &amp;lt; Visitor
    visitor_for Array do |array|
      array
    end
 
    visitor_for Object do |o|
      [o]
    end
  end
&lt;/pre&gt;
&lt;p&gt;That was pretty easy. If the target of the &amp;#8220;accept&amp;#8221; method is an array, the visit_Array method will be called an the target object will be returned. If it&amp;#8217;s something else, visit_Object will be called and a new object will be created.&lt;/p&gt;
&lt;p&gt;I can use this style pattern for converting any object to pretty much any other.&lt;/p&gt;
&lt;h3&gt;Cleaning up our &lt;span class="caps"&gt;API&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;So far my &lt;span class="caps"&gt;API&lt;/span&gt; is kind of strange. I have to call &amp;#8220;accept&amp;#8221; on the target object and pass in new visitor of some sort. To clean this &lt;span class="caps"&gt;API&lt;/span&gt; up a bit, I&amp;#8217;ve written a proxy object that takes any object for it&amp;#8217;s constructor, then provides nice method names to abstract the visitor classes:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require 'visitable'
  require 'visitor'
  require 'as_form_object'
  require 'as_array'
  require 'as_fields_for_form_object'
 
 
  ###
  # This class sets up a proxy to +thing+. The purpose of this class is to let
  # us convert an object to something else without knowing what visitor is
  # required to do that conversion:
  #
  # p form_for([1, :two, [3]]).as_form_object
  #
  class ConversionProxy &amp;lt; Struct.new(:thing)
    def as_form_object
      thing.accept AsFormObject.new
    end
 
    def as_array
      thing.accept AsArray.new
    end
 
    def as_fields_for_form_object args
      thing.accept AsFieldsForFormObject.new(args)
    end
  end
 
  def form_for thing
    ConversionProxy.new(thing)
  end
 
  p form_for(:two).as_form_object
 
  p form_for(:two).as_array
  p form_for([:two]).as_array
 
  p form_for(:two).as_fields_for_form_object [:foo]
  p form_for(['hello world']).as_fields_for_form_object [:foo]
&lt;/pre&gt;
&lt;h3&gt;Pros for this solution&lt;/h3&gt;
&lt;p&gt;With one monkey patch to Object, I now have the ability to convert &lt;strong&gt;any&lt;/strong&gt; object in to any other object without needing to add new methods to core classes.&lt;/p&gt;
&lt;p&gt;Each visitor has one specific responsibility. My visitor classes are just normal classes, so if I find any repetition between them, I can refactor and inherit, or refactor and mix in.&lt;/p&gt;
&lt;h3&gt;Cons for this solution&lt;/h3&gt;
&lt;p&gt;I still had to monkey patch Object and add a method. The method I added was very generic and simple, but I still had to add it.&lt;/p&gt;
&lt;p&gt;Visitation rules may need to change. My current behavior of looking up the ancestor tree &lt;strong&gt;may&lt;/strong&gt; not be desired. Fortunately if I need to change that, my visitor subclass can just override visit.&lt;/p&gt;
&lt;p&gt;Double dispatch might be confusing. The code is very simple, but it took me a while to understand and harness it&amp;#8217;s power (I have the pooowwwweeerrr!).&lt;/p&gt;
&lt;p&gt;Is this any better than case/when statements? I&amp;#8217;m not sure. It still works based on object type, but it does nicely encapusulate the conversion logic.&lt;/p&gt;
&lt;h3&gt;Follow up notes&lt;/h3&gt;
&lt;p&gt;When I&amp;#8217;m implementing this pattern in &amp;#8220;the real world&amp;#8221; I&amp;#8217;ve never done it for core classes. I typically use this for converting my own objects in to some other object. Since I&amp;#8217;m performing these actions on my own objects, there is no monkey pathing involved (yay!).&lt;/p&gt;
&lt;p&gt;Also, its worth keeping in mind that babbies can form in many ways, and this is only one of them.  Tune in next week to watch Greg tackle the same problem using Decorators, to see the pros and cons from yet another angle.&lt;/p&gt;</description><author>aaron.patterson@gmail.com (Aaron Patterson)</author><pubDate>Fri, 19 Jun 2009 20:30:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html</link><guid>http://blog.rubybestpractices.com/posts/aaronp/001_double_dispatch_dance.html</guid></item><item><title>First Design Considerations</title><description>&lt;p&gt;Now the interesting part begins!  In an early phase like this I like to look at the problem I want to solve from different angles to get a feeling for implementation options.  The output will look like an unsorted collection of notes &amp;#8211; and that&amp;#8217;s what it is!  I don&amp;#8217;t claim that this is the best approach around but this helps me to get a better grip of the problem.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Side note&lt;/em&gt;: I believe that despite all the methodologies around the way you approach a new problem is highly influenced by your personal way of thinking and working.  There is no one size fits all approach and &amp;#8220;chaos&amp;#8221; at the beginning is nothing to be afraid of.  In fact it may well be that &amp;#8220;chaos&amp;#8221; gives birth to the best ideas.&lt;/p&gt;
&lt;h3&gt;Obtaining Information about individual Records&lt;/h3&gt;
&lt;p&gt;Requirement M3 makes it necessary that in some place we have a plug where we can insert something that does log file format specific things.  Basically for parsing a single line a block would be sufficient.  If the format parses ok, the interaction identifier is returned, if not, we have a continuation line.  However, it seems this solution is too simplistic: for time filtering (M6) and time gap detection (S3) we certainly also need the timestamp of the record.  M7, which I had forgotten initially, also makes it necessary that the year is somehow synthesized &amp;#8211; or inserted into the line parser from surrounding code.  So, we will likely end up with something that would be an interface in other programming languages, i.e. we need a parser class which speaks a certain protocol / has a certain &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s an alternative approach: we create a record class and write our parser in a way that it spits out instances of this record class all the time:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
Record = Struct.new :time_stamp, :interaction_id, :message

parser = ...

parser.each do |rec|
  interaction = find_interaction(rec.interaction_id)
  time_gap = rec.time_stamp - interaction.last_time_stamp
  ...
end
&lt;/pre&gt;
&lt;p&gt;From an object oriented point of view there&amp;#8217;s much which speaks in favour of this:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;A record is an entity in our description of the problem domain and as such it is naturally to have it represented in the application,&lt;/li&gt;
	&lt;li&gt;We can add record specific functionality to this class (e.g. get all potential keywords used for searching / filtering),&lt;/li&gt;
	&lt;li&gt;We do not have to care about multiline detection, this is completely encapsulated in the parser,&lt;/li&gt;
	&lt;li&gt;We can enforce class invariants (e.g. all fields must be non nil and &lt;code&gt;time_stamp&lt;/code&gt; must be a &lt;code&gt;Time&lt;/code&gt; instance).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, there&amp;#8217;s a price to pay in object allocations and collections.  Remember, we are talking about files with tons of records; if all these records are short lived (i.e. not used for storing them somewhere) we&amp;#8217;re generating a lot of overhead which the garbage collector has to get rid of again.  So I rather lean towards the &amp;#8220;parser interface&amp;#8221; approach mentioned above:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
parser = ...

parser.line = line

if parser.continuation_line?
  last_record &amp;lt;&amp;lt; "\n" &amp;lt;&amp;lt; line
else
  ...
  last_record = line
  diff = parser.time_stamp - last_time
  ...
end
&lt;/pre&gt;
&lt;p&gt;Now, it&amp;#8217;s debatable whether this falls into the category of &lt;a href="http://en.wikipedia.org/wiki/Premature_optimization#When_to_optimize"&gt;premature optimisation&lt;/a&gt;, but since we know that we are going to crunch a lot of data we should probably avoid this kind of overhead.&lt;/p&gt;
&lt;h3&gt;Filtering&lt;/h3&gt;
&lt;p&gt;From the requirements it is clear that we would like to have quite flexible filtering (M6, S3, S4).  We have two options:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;We apply the filtering during processing.&lt;/li&gt;
	&lt;li&gt;Processing gathers meta data about the data and we can efficiently query later with whatever filters we like.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hybrid approaches are also possible, e.g. time filtering during processing but searching for keywords later.  From the user&amp;#8217;s point of view option 2 is certainly more desirable because it gives greater flexibility.  On the other hand this must be balanced with processing overhead and disk space.  As usual, if we want great flexibility for queries after analysis we need more disk space for meta data (indexes).  In another hybrid approach the types of desired filters are provided as input into the processor so that only indexes for criteria are created which are actually queried later.  The &amp;#8220;flexible query&amp;#8221; approach certainly reminds me of relational database.&lt;/p&gt;
&lt;p&gt;When we do online filtering (option 1 above) we need to keep some aspects in mind.  For example, if we want to filter by text found in an interaction log message (the part after the interaction id in the sample generator output), that text might not appear in the first record of a particular interaction yet we would want to see all preceeding records as well (M1).  Similar for time range filtering: an interaction might have started before the range start but end after it.  It should be clear that if we choose this approach we need a way to keep some history of past records during processing.  Since we can&amp;#8217;t store everything we&amp;#8217;ve seen so far we need to decide what we need to keep and what we can discard.&lt;/p&gt;
&lt;p&gt;I need to ponder this a bit more but at the moment I would rather choose the online filtering approach for these reasons:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Less disk space used on output,&lt;/li&gt;
	&lt;li&gt;Potentially less write IO during processing, which would help performance since we are almost certainly IO bound,&lt;/li&gt;
	&lt;li&gt;Easier distribution to other staff &amp;#8211; if we need meta data to get at information efficiently this also means that someone needs to have the software to extract the information he wants (plus the index data and the original data set which is large).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Statistics&lt;/h3&gt;
&lt;p&gt;Collecting statistics like no. of records and no. of lines per file isn&amp;#8217;t too expensive so we probably create a statistics class which records just that.&lt;/p&gt;
&lt;h2&gt;Application Structure&lt;/h2&gt;
&lt;p&gt;If you do not know &lt;a href="http://en.wikipedia.org/wiki/Class-Responsibility-Collaboration_card"&gt;&lt;span class="caps"&gt;CRC&lt;/span&gt; Cards&lt;/a&gt; yet this is a good opportunity to look into this simple concept.  It does not have the power of an &lt;span class="caps"&gt;UML&lt;/span&gt; collaboration diagram but it helps identify classes and how they might play together.&lt;/p&gt;
&lt;p&gt;We can roughly identify some pieces already:&lt;/p&gt;
&lt;dl&gt;
	&lt;dt&gt;Parser&lt;/dt&gt;
	&lt;dd&gt;parse individual lines of the input, identify relevant information (timestamp, interaction id).&lt;/dd&gt;
	&lt;dt&gt;FileStatistics&lt;/dt&gt;
	&lt;dd&gt;collect various data points about a processed file (lines, time taken&amp;#8230;).&lt;/dd&gt;
	&lt;dt&gt;OptionProcessor&lt;/dt&gt;
	&lt;dd&gt;process command line options.&lt;/dd&gt;
	&lt;dt&gt;Coordinator&lt;/dt&gt;
	&lt;dd&gt;This is the &lt;a href="http://en.wikipedia.org/wiki/Master_Control_Program_(Tron)#Master_Control_Program"&gt;&lt;span class="caps"&gt;MCP&lt;/span&gt;&lt;/a&gt; which binds everything together and coordinates the processing.&lt;/dd&gt;
	&lt;dt&gt;ProcessingStorage&lt;/dt&gt;
	&lt;dd&gt;this is the foggiest entity so far; it will be responsible for storing information about processed interactions.  Since I haven&amp;#8217;t decided on the strategy yet, I&amp;#8217;ll leave it at this for now.  We&amp;#8217;ll have to make this more concrete later.  One thing is for sure: this will likely the most complex class &amp;#8211; or rather set of classes.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;So much for initial design considerations.  I&amp;#8217;ll stop here, to give us a break and allow for some discussion, which probably will turn up new aspects and new ideas.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Fri, 12 Jun 2009 20:36:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/008-First_Design_Considerations.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/008-First_Design_Considerations.html</guid></item><item><title>"And your Mom, too."  Ruby-talk best practices.</title><description>&lt;p&gt;Mailing lists (and bulletin boards and forums and so on) are important parts of becoming a better developers. Even the best programmers need help, and a mailing list such as &lt;a href="http://www.ruby-lang.org/en/community/mailing-lists"&gt;ruby-talk&lt;/a&gt;  (or the Usenet version, comp.lang.ruby) is the traditional place to go.&lt;/p&gt;
&lt;p&gt;Mailing lists are also a good place to get better at your craft; watch the list, and try to answer questions. Think of it as pop quizzes at Ruby U.&lt;/p&gt;
&lt;p&gt;Mailing lists are also good place to toss out ideas, conjecture about the future of Ruby, and have general Ruby-related discussions.&lt;/p&gt;
&lt;p&gt;There are, however, right and wrong ways to go about this.  The canonical source for what is termed &amp;#8220;Netiquette&amp;#8221; is Internet Engineering Task Force &lt;a href="http://tools.ietf.org/rfc/rfc1855.txt"&gt;&lt;span class="caps"&gt;RFC&lt;/span&gt; 1855&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You should read it.  However, it&amp;#8217;s somewhat lengthy, and some aspects dated.  Here, I&amp;#8217;d like to focus on a few key items as they relate to Ruby and ruby-talk.&lt;/p&gt;
&lt;h2&gt;&lt;span class="caps"&gt;RFC&lt;/span&gt; 1855 in a Nutshell&lt;/h2&gt;
&lt;p&gt;For the &lt;a href="http://www.urbandictionary.com/define.php?term=tl;dr"&gt;tl;dr&lt;/a&gt; crowd: Don&amp;#8217;t be a complete jerk.&lt;/p&gt;
&lt;p&gt;I can&amp;#8217;t suggest not being any kind of jerk at all in anyway, because it&amp;#8217;s impossible.  The Web is a big place.  No matter what you say or do, there is every chance that someone, somewhere, will take offence, or think you stupid, or in some way take you the wrong way.&lt;/p&gt;
&lt;p&gt;There&amp;#8217;s not much you can do about that, but you can be mindful of some general decency.  For Rubyists, the key is &lt;span class="caps"&gt;MINASWAN&lt;/span&gt;: Matz is nice, and so we are nice.&lt;/p&gt;
&lt;p&gt;This doesn&amp;#8217;t mean not being critical, or not pointing out mistakes, or not offering bold opinions.  It means directing your comments to ideas, not personalities.  It means understanding that being wrong doesn&amp;#8217;t make a person bad or stupid, just wrong.  And being wrong on one thing does make make  a person wrong on everything.&lt;/p&gt;
&lt;p&gt;It also means not jumping down someone&amp;#8217;s throat because their sense of humor doesn&amp;#8217;t jibe with yours.&lt;/p&gt;
&lt;p&gt;Discussions on ruby-talk can get heated, and the temptation can be strong to let loose with snark and bile.  Typically it ends up counter-productive, but it&amp;#8217;s understandable.&lt;/p&gt;
&lt;p&gt;Threads would likely be much less fun if everything was sanitized.  However, the line needs to be drawn at personal attacks and comments.&lt;/p&gt;
&lt;p&gt;Ideas can be foolish; people are not fools simply for expressing a foolish idea.  Code can be bad; people are not bad for writing such code.&lt;/p&gt;
&lt;h2&gt;It&amp;#8217;s About Code and Ideas&lt;/h2&gt;
&lt;p&gt;Few people post to ruby-talk to make personal attacks (barring trolls, who should never ever be fed), but it happens. Before letting loose that little bit of one-upmanship, consider what you are really trying to accomplish.  If the goal is hurt someone: Please remember &lt;span class="caps"&gt;MINASWAN&lt;/span&gt;. If you cannot, then please go elsewhere.&lt;/p&gt;
&lt;p&gt;If the goal is to see Ruby improve, or to express an idea, or to get help with some code, or to offer help, then stop and think.&lt;/p&gt;
&lt;p&gt;That brief moment of satisfaction will fade, and you will have failed in your larger intent.&lt;/p&gt;
&lt;p&gt;Ruby-talk has a tradition of being very welcoming to newcomers, with many people willing to help answer even the goofiest of questions.  I&amp;#8217;ve asked a fair number of those goofy questions, and the help I received encouraged me both to stick with Ruby and to try to return the favor. Please support that.&lt;/p&gt;
&lt;h2&gt;A Random Set of Guidelines&lt;/h2&gt;
&lt;p&gt;Assorted do&amp;#8217;s and don&amp;#8217;ts.  If you can think of more, please add them in the comments.&lt;/p&gt;
&lt;h3&gt;Don&amp;#8217;t top-post&lt;/h3&gt;
&lt;p&gt;See &lt;a href="http://www.caliburn.nl/topposting.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Before retorting with how this or that mail reader or client makes top-posting the default, consider this: the idea is to make things easy for the readers, not for you, the poster.&lt;/p&gt;
&lt;p&gt;If the goal is have people read, and understand, what you are posting, then place you reply in context, and trim away irrelevant text.&lt;/p&gt;
&lt;p&gt;If you are unpersuaded by arguments against top-posting (and many are), know that many people will simply not bother with what you post.&lt;/p&gt;
&lt;h3&gt;Do your homework&lt;/h3&gt;
&lt;p&gt;Ruby is a great language, fairly intuitive to many people, but sometimes you get stuck trying to figure something out. It may seem easy to dash off a note to ruby-talk asking, &amp;#8220;How do I do foo?&amp;#8221;, but first apply some due diligence.  Use Google.  Use ruby-doc.org (Handy tip: Ruby-doc.org uses a custom Google search focused on Ruby sites.  There&amp;#8217;s a special search &lt;span class="caps"&gt;URL&lt;/span&gt; as well: http://www.ruby-doc.org/q/your+search+terms+here.)&lt;/p&gt;
&lt;p&gt;Search the ruby-talk archives:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;http://groups.google.com/group/ruby-talk-google&lt;/li&gt;
	&lt;li&gt;http://www.nabble.com/ruby-talk-f13890.html&lt;/li&gt;
	&lt;li&gt;http://blade.nagaokaut.ac.jp/ruby/ruby-talk/index.shtml.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you do post, explain what steps you&amp;#8217;ve taken to solve the matter on your own.  This serves two purposes. First, it shows people you are diligent, making more people more likely to want to help you. It also avoids wasting time with people suggesting things you&amp;#8217;ve already done or know about.&lt;/p&gt;
&lt;p&gt;Whenever possible, show your code.  If you have more than a dozen lines or so, use a pastie site, such as &lt;a href="http://gist.github.com/"&gt;Gist&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Be specific&lt;/h3&gt;
&lt;p&gt;If you have a problem, give details about your environment.  What operating system? What version of Ruby?&lt;/p&gt;
&lt;p&gt;Know, too, that there are specialized mailing lists for many Ruby tools and applications. For example, if you have a problem with Rails or Ramaze, please ask on the Rails or Ramaze mailing lists. You are more likely to get a faster, more accurate response on the proper list.&lt;/p&gt;
&lt;p&gt;Ask concrete questions.  Explain what you are trying to do, what results you get, and how those results differ from what you want or expected.&lt;/p&gt;
&lt;h3&gt;Don&amp;#8217;t threadjack.&lt;/h3&gt;
&lt;p&gt;That is, do not reply to a post with starting a new topic.   If a thread starts to drift off-topic, please consider starting a new thread with a more appropriate topic.&lt;/p&gt;
&lt;h3&gt;Repetition is not an argument&lt;/h3&gt;
&lt;p&gt;Don&amp;#8217;t expect anyone to change their opinion because you&amp;#8217;ve repeated your same points over and over. Accept that sometimes people will never, ever, agree with you. I know, it&amp;#8217;s weird, but true.&lt;/p&gt;

&lt;h3&gt;Watch for perma-threads&lt;/h3&gt;
&lt;p&gt;There are some topics that come up at regular intervals. Adding static typing to Ruby.  Best &lt;span class="caps"&gt;GUI&lt;/span&gt;  toolkit.  Best &lt;span class="caps"&gt;IDE&lt;/span&gt;.  Adding significant indentation.&lt;/p&gt;
&lt;p&gt;Before posting, see if you are not simply repeating what has been said.  Check the archives.  If you really feel you have something new to add, post, but please show that you are familiar with prior discussion.&lt;/p&gt;
&lt;p&gt;Conversely, if you see a post that looks to be a perma-thread, don&amp;#8217;t assume it has been discussed to death (although that is possible). Certain topics, such as &lt;span class="caps"&gt;GUI&lt;/span&gt; tools or IDEs, see new additions and advancements over time.  It doesn&amp;#8217;t help to direct people to a thread from last year as the final word on evolving technology.&lt;/p&gt;
&lt;h3&gt;Walk the walk&lt;/h3&gt;
&lt;p&gt;People often ask for one or another change to the Ruby language or standard library. This is good, this is how languages evolve.&lt;/p&gt;
&lt;p&gt;Well-considered change requests should be posted to the ruby-core mailing list.&lt;/p&gt;
&lt;p&gt;Before proposing any change, see if someone hasn&amp;#8217;t already implemented it as a library.  There are a few libraries, such as &lt;a href="http://facets.rubyforge.org"&gt;Facets&lt;/a&gt;, that provide many extensions.&lt;/p&gt;
&lt;p&gt;If there is no existing code, see if you can first implement it yourself.&lt;/p&gt;
&lt;p&gt;For example, you may think it be would super cool awesome if the Array class could tell you what elements were of a certain size:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  a = %w{ foo bar bar thisoneisdiffernt }
  short_words = a.length_is 3
&lt;/pre&gt;
&lt;p&gt;Before arguing in the abstract just how magical this would make life, code it yourself:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Array
    def length_is length
      self.select{ |i| i.size == length }
    end
  end
&lt;/pre&gt;
&lt;p&gt;Make it a gem, or a gist pastie, or otherwise available for others to try.  Then explain why it needs to be added to the language rather than used as a gem.&lt;/p&gt;
&lt;p&gt;If, for whatever reason, you cannot implement it (even a weak version), explain why.&lt;/p&gt;
&lt;p&gt;The bottom line is this: Many, many suggestions have been made, many with the presumption that someone else is expected to do the heavy lifting, swayed only by rhetoric. That&amp;#8217;s unfair, and unproductive..&lt;/p&gt;
&lt;p&gt;When first attempting to code it yourself, certain results are likely:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;You discover that there is no need to build it into the language, since it is trivial to add (e.g. using a gem)&lt;/li&gt;
	&lt;li&gt;You discover that it is not so easy to add as-needed, but you now have the code for it, so adding it to the language would be that much easier&lt;/li&gt;
	&lt;li&gt;You discover that, now that you have a working version, you don&amp;#8217;t use it as you expected anyway&lt;/li&gt;
	&lt;li&gt;You find out that some things are hard to do&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Best of all, the effort should make you a better Ruby programmer.&lt;/p&gt;</description><author>james.britt@gmail.com (James Britt)</author><pubDate>Wed, 10 Jun 2009 21:59:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/jamesbritt/and_your_Mom_too.html</link><guid>http://blog.rubybestpractices.com/posts/jamesbritt/and_your_Mom_too.html</guid></item><item><title>Quack Attack: Making Your Code More Rubyish</title><description>&lt;p&gt;I&amp;#8217;ve been doing some &lt;span class="caps"&gt;FFI&lt;/span&gt; work recently, which means that I&amp;#8217;ve needed to  wrap underlying C libraries so that I can call them from Ruby.  While I won&amp;#8217;t get into how the low level wrappers work, I can show you what the raw &lt;span class="caps"&gt;API&lt;/span&gt; calls look like for just a few functions:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  trip = API.PCMSNewTrip(server_id)
  API.PCMSNumStops(trip)
  API.PCMSAddStop(trip, string)
  API.PCMSGetStop(trip, index, string_ptr, buffer_size)
  API.PCMSDeleteStop(trip, index)
  API.PCMSClearStop(trip)
&lt;/pre&gt;
&lt;p&gt;All things considered, this looks pretty good for a direct wrapper on top of a C library.  In fact, it&amp;#8217;s relatively simple to mirror this to a more normalized Ruby layout.  We can start by noticing that these calls are basically object oriented, focusing on the &lt;tt&gt;Trip&lt;/tt&gt; object.  While a &lt;tt&gt;Trip&lt;/tt&gt; has other responsibilities, among them is managing a list of stops.  With this in mind, we can flesh out a basic &lt;tt&gt;Trip&lt;/tt&gt; object:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Trip
  def initialize(server_id)
    @server_id = server_id
    @pointer = API.PCMSNewTrip(@server_id)
    @stops = StopList.new(self)
  end
  
  attr_reader :stops
  
  def call(*args)
    API.send("PCMS#{args.first}",  @pointer, *args[1..-1])
  end
end
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;Trip#call&lt;/tt&gt; helper removes some of the duplication for us, but it&amp;#8217;ll be easier to see how it works in just a moment.  For now, it&amp;#8217;s worth pondering what a &lt;tt&gt;StopList&lt;/tt&gt; should be.&lt;/p&gt;
&lt;p&gt;If you look at the functions listed for dealing with stops, you&amp;#8217;ll notice they map nicely to one of Ruby&amp;#8217;s structures.  We&amp;#8217;re dealing with an ordered list of objects that can be added to and removed from.  It can also be queried for its length, and deleted entirely.  These features sure sound a lot like Ruby&amp;#8217;s &lt;tt&gt;Array&lt;/tt&gt; object, don&amp;#8217;t they?&lt;/p&gt;
&lt;p&gt;With this in mind, let&amp;#8217;s do a quick experiment in interface design:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class StopList

  include Enumerable

  def initialize(trip)
    @trip = trip
  end

  def length
    @trip.call :NumStops
  end

  def &amp;lt;&amp;lt;(loc)
    @trip.call :AddStop, loc
  end

  def [](index)
    ptr = FFI::MemoryPointer.new(:char, 100)
    @trip.call :GetStop, index, ptr, 101
    ptr.read_string
  end

  def delete_at(index)
    @trip.call :DeleteStop, index
  end

  def each
    length.times do |i|
      yield self[i]
    end
  end

  def clear
    @trip.call :ClearStops
  end

end
&lt;/pre&gt;
&lt;p&gt;Without paying too much attention to the implementation details, let&amp;#8217;s take a look at what behaviors this new object supports:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  t = Trip.new(server_id)
  
  t.stops &amp;lt;&amp;lt; "New Haven, CT"
  t.stops &amp;lt;&amp;lt; "Naugatuck, CT"
  t.stops &amp;lt;&amp;lt; "Boston, MA"
  
  p t.stops.length #=&amp;gt; 3
  
  p t.stops[2] #=&amp;gt; "02205 Boston, MA, Suffolk"
  
  t.stops.delete_at(1)
  p t.stops[1] #=&amp;gt; "02205 Boston, MA, Suffolk"
  
  p t.stops.map { |e| e.upcase } #=&amp;gt; [ "06511 NEW HAVEN, CT, NEW HAVEN",
                                 #     "02205 BOSTON, MA, SUFFOLK" ]
  
  t.stops.clear
  p t.stops.length #=&amp;gt; 0
&lt;/pre&gt;
&lt;p&gt;If this sort of interaction looks familiar to you, it&amp;#8217;s because you&amp;#8217;ve likely already done things like this thousands of times.  But to make it blindingly obvious, let&amp;#8217;s replace Trip#stops with an Array.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
stops = []

stops &amp;lt;&amp;lt; "New Haven, CT"
stops &amp;lt;&amp;lt; "Naugatuck, CT"
stops &amp;lt;&amp;lt; "Boston, MA"

p stops.length #=&amp;gt; 3

p stops[2] #=&amp;gt; "Boston, MA"

stops.delete_at(1)
p stops[1] #=&amp;gt; "Boston, MA"

p stops.map { |e| e.upcase } #=&amp;gt; ["NEW HAVEN, CT", "BOSTON, MA"]

stops.clear
p stops.length #=&amp;gt; 0
&lt;/pre&gt;
&lt;p&gt;You&amp;#8217;ll notice that aside from lacking the location name normalization that our real code does implicitly, the key points we&amp;#8217;ve highlighted have exactly the same behavior, using exactly the same interface.  One benefit is immediately obvious after seeing this; the &lt;span class="caps"&gt;API&lt;/span&gt; for &lt;tt&gt;StopList&lt;/tt&gt; doesn&amp;#8217;t require you to learn anything new.&lt;/p&gt;
&lt;p&gt;A more subtle gain that comes with this approach is that so long as it is restricted to the subset which &lt;tt&gt;StopList&lt;/tt&gt; supports, code which expects an &lt;tt&gt;Array&lt;/tt&gt;-like thing does not need to change, either.&lt;/p&gt;
&lt;p&gt;For example, the following code will work just fine with either an &lt;tt&gt;Array&lt;/tt&gt; or a &lt;tt&gt;StopList&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def humanized(list)
  list.each_with_index do |e,i|
    puts "#{e} (#{i+1} / #{list.length})"
  end
end
&lt;/pre&gt;
&lt;p&gt;This makes things easier to test, and easier to be re-used for different purposes.  Both are solid reasons for using this technique.&lt;/p&gt;
&lt;p&gt;Of course, I&amp;#8217;ve been glossing over a semi-major issue in the original code here, which I am sure has frustrated our more pedantic readers.  The current &lt;tt&gt;StopList&lt;/tt&gt; code, while quite useful, does not quack perfectly with Array.  We needn&amp;#8217;t look far for signs of divergence.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
p t.stops &amp;lt;&amp;lt; "Chicago, IL" #=&amp;gt; 1
p t.stops.delete_at(2)     #=&amp;gt; 1
p t.stops.clear            #=&amp;gt; nil
&lt;/pre&gt;
&lt;p&gt;These side-effect bearing functions are returning their C based values, which are different than what you&amp;#8217;d expect from a Ruby &lt;tt&gt;Array&lt;/tt&gt;.  Luckily, each of these are easy to remedy.&lt;/p&gt;
&lt;p&gt;In the case of the append operator (&amp;lt;&amp;lt;), we should return the  &lt;tt&gt;StopList&lt;/tt&gt; itself, to permit chaining:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def &amp;lt;&amp;lt;(loc)
  @trip.call :AddStop, loc
  return self
end
&lt;/pre&gt;
&lt;p&gt;To play nice with &lt;tt&gt;Array&lt;/tt&gt;, our &lt;tt&gt;delete_at&lt;/tt&gt; method should return the deleted object:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def delete_at(index)
    obj = self[index]
    @trip.call :DeleteStop, index
    return obj
  end
&lt;/pre&gt;
&lt;p&gt;Finally, since &lt;tt&gt;clear&lt;/tt&gt; may also be chained, it should return the original object as well.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def clear
  @trip.call :ClearStops
  return self
end
&lt;/pre&gt;
&lt;p&gt;With these fixes in place, we can re-visit our previous example:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
p t.stops &amp;lt;&amp;lt; "Chicago, IL" #=&amp;gt; #&amp;lt;Trip::StopList:0x0fcac ...&amp;gt;
p t.stops.delete_at(2)     #=&amp;gt; "60607 Chicago, IL, Cook"
p t.stops.clear            #=&amp;gt; #&amp;lt;Trip::StopList:0x0fcac ...&amp;gt;
&lt;/pre&gt;
&lt;p&gt;There are probably some other minor details to catch, but now that our &lt;tt&gt;Array&lt;/tt&gt;-ish &lt;tt&gt;StopList&lt;/tt&gt; is &amp;#8220;Good Enough For Government Work&amp;#8221;, we have a nice stopping point.  Let&amp;#8217;s wrap things up with a little summary of things to remember.&lt;/p&gt;
&lt;h3&gt;Guidelines For Making Your Code More &amp;#8220;Rubyish&amp;#8221;&lt;/h3&gt;
&lt;p&gt;This is just one technique among many for improving your code, but I&amp;#8217;d argue its a fairly important one. If you have a structure that mimics a subset of a core Ruby object&amp;#8217;s capabilities, you can gain a lot by standardizing on a compatible interface.  While sometimes the similarities end at the &lt;tt&gt;Enumerable&lt;/tt&gt; and &lt;tt&gt;Comparable&lt;/tt&gt; mixins, it&amp;#8217;s reasonable to stretch things farther when it makes sense to do so.  If you go that route (as we did here), there are just a few things to keep in mind:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;You don&amp;#8217;t need to implement every last feature of a core Ruby object in order to use this technique.  So many functions rely on just a handful of available methods, that it makes sense to use this technique even when your problem domain is very small.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;For the features you do implement, take care to maintain the same interface both on input and output.  It&amp;#8217;s fine to not support certain use cases, or to add extensions for new ones, but you should not diverge in the behaviors you do implement unless you have a good reason to.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;Pay close attention to the return values of side-effect inducing functions, especially the ones mentioned in this article.  Many Ruby methods are designed to be chainable, and breaking that feature can create a mess.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
	&lt;li&gt;While this technique opens the door for using primitive objects for testing higher level functions, do not forget to adequately test the functionality of the actual objects you are implementing.  Basically, make sure your code really quacks like a duck before substituting it with a duck somewhere else.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;i&gt;To our readers:  Where have you seen good uses of this technique in action?  Have you tried it yourself and run into any problems?  Please give your answers to these questions, as well as any other discussion points in the comments.&lt;/i&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 09 Jun 2009 13:00:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/007-rubyish-code.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/007-rubyish-code.html</guid></item><item><title>Requirements Summary of the Laboratory Project</title><description>&lt;p&gt;I will now take on the role of project secretary and put all requirements into a form suitable for easier reference.  There will be the following groups:&lt;/p&gt;
&lt;dl&gt;
	&lt;dt&gt;must (M)&lt;/dt&gt;
	&lt;dd&gt;requirement must be fulfilled&lt;/dd&gt;
	&lt;dt&gt;should (S)&lt;/dt&gt;
	&lt;dd&gt;requirement should be fulfilled but is not a show stopper&lt;/dd&gt;
	&lt;dt&gt;nice to have (N)&lt;/dt&gt;
	&lt;dd&gt;this one is purely optional&lt;/dd&gt;
	&lt;dt&gt;future (F)&lt;/dt&gt;
	&lt;dd&gt;this might be a good idea for a later release but should not influence the current version&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;I will later reference requirements via letter and number, e.g. &amp;#8220;S4&amp;#8221; refers to &amp;#8220;filter by text&amp;#8221; requirement (and not a fast car from a German manufacturer).&lt;/p&gt;
&lt;p&gt;Until now there was not much reasoning about software although there were some ideas (and even prototypes) mentioned in the discussion thread of the &lt;a href="006-The_Muppet_Project.html"&gt;last article&lt;/a&gt;.  With the next article I will start to flesh out the architecture (or even some alternatives) along with the reasoning that led to different decisions.&lt;/p&gt;
&lt;h3&gt;Must have&lt;/h3&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;number&lt;/th&gt;
		&lt;th&gt;description&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 1&lt;/td&gt;
		&lt;td&gt;Provide efficient access to all entries of selected interactions&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 2&lt;/td&gt;
		&lt;td&gt;Retain ordering of input lines per interaction&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 3&lt;/td&gt;
		&lt;td&gt;Parsing needs to be able to identify multi line entries&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 4&lt;/td&gt;
		&lt;td&gt;Parsing of lines needs to be easily adjustable to different line formats&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 5&lt;/td&gt;
		&lt;td&gt;Analysis must not rely on any particular text to identify first and last lines of an interaction&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 6&lt;/td&gt;
		&lt;td&gt;Filter interactions by time range (between a and b, before a, after a)&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 7&lt;/td&gt;
		&lt;td&gt;If timestamps are parsed formats without year must be properly parsed&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h3&gt;Should have&lt;/h3&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;number&lt;/th&gt;
		&lt;th&gt;description&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 1&lt;/td&gt;
		&lt;td&gt;Input file names should be provided via command line arguments&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 2&lt;/td&gt;
		&lt;td&gt;Analysis should deal gracefully with partial interactions (at the beginning and end of a logfile)&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 3&lt;/td&gt;
		&lt;td&gt;Idenfity pauses in interactions with a configurable length and report them&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 4&lt;/td&gt;
		&lt;td&gt;Filter interactions by some text contained in messages, ideally via regexp matching&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 5&lt;/td&gt;
		&lt;td&gt;Make interactions available in their original formatting&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h3&gt;Nice to have&lt;/h3&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;number&lt;/th&gt;
		&lt;th&gt;description&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 1&lt;/td&gt;
		&lt;td&gt;Identification of the proper chronological order of files&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 2&lt;/td&gt;
		&lt;td&gt;Read from stdin&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 3&lt;/td&gt;
		&lt;td&gt;&lt;span class="caps"&gt;HTML&lt;/span&gt; output&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 4&lt;/td&gt;
		&lt;td&gt;Do not use more than 20% on top of a &lt;code&gt;cat &amp;gt;/dev/null&lt;/code&gt;&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 5&lt;/td&gt;
		&lt;td&gt;Statistics about the analysis such as time range, files read, lines read, interactions found etc.&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;h3&gt;Future&lt;/h3&gt;
&lt;table&gt;
	&lt;tr&gt;
		&lt;th&gt;number&lt;/th&gt;
		&lt;th&gt;description&lt;/th&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 1&lt;/td&gt;
		&lt;td&gt;Analysis data stored in a relational database for later analysis with &lt;span class="caps"&gt;SQL&lt;/span&gt; queries&lt;/td&gt;
	&lt;/tr&gt;
	&lt;tr&gt;
		&lt;td&gt; 2&lt;/td&gt;
		&lt;td&gt;Correlate data from different components with different log file naming schemes and formats&lt;/td&gt;
	&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Please let me know if I missed something or there are other mistakes (such as contradictory requirements).&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Mon, 08 Jun 2009 21:59:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/007-Requirements.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/007-Requirements.html</guid></item><item><title>Name that method: Symmetry</title><description>&lt;pre name="code" class="ruby"&gt;
class Users &amp;lt; Application
  provides :xml, :json

  def index
    @users = User.all
    display @users
  end
end
&lt;/pre&gt;
&lt;p&gt;Take a look at the snippet above. It&amp;#8217;s from Merb, and the &lt;code&gt;provides/display&lt;/code&gt; feature is something that will be implemented in Rails 3 after it was decided to merge the two projects. Don&amp;#8217;t think too much about what it does, the point is to see how it will look in Rails 3:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class UsersController &amp;lt; ApplicationController
  respond_to :html, :xml, :json

  def index
    @users = User.find(:all)
    respond_with(@users)
  end
end  
&lt;/pre&gt;
&lt;p&gt;A subtle difference. Let&amp;#8217;s have a look at another example, this time from Camping:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
module Blog::Controllers
  # Define routes using R()
  class Index &amp;lt; R '/'
  end
  
  class Posts &amp;lt; R '/posts'
  end
end   
  
module Blog::Views
  def index
    # Generate URLs using R()
    a :href =&amp;gt; R(Posts) { 'Show me the posts!' }
  end
end   
&lt;/pre&gt;
&lt;p&gt;Notice how you use the class method &lt;code&gt;R&lt;/code&gt; to define routes in the controllers, and the instance method &lt;code&gt;R&lt;/code&gt; to build URLs to those routes again.&lt;/p&gt;
&lt;h3&gt;What&amp;#8217;s the deal?&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;m not a very good designer, but I &lt;em&gt;have&lt;/em&gt; managed to get a hold of some of the principles. One of them is called the principle of &lt;em&gt;proximity&lt;/em&gt;, and says that &lt;strong&gt;related items should be grouped together&lt;/strong&gt;. We programmers already do this all the time: We group our code into classes and modules and separate them into different files and folders. However, this same principle can be applied when it comes to method names: &lt;strong&gt;related methods should have related names&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&amp;#8220;Provide&amp;#8221; and &amp;#8220;display&amp;#8221; are neither synonyms nor antonyms, nor do they share a common prefix/suffix. They are however closely related and obviously symmetric. &lt;strong&gt;That symmetry should be reflected in their names.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When you quickly glance over some code, your brain starts creating connections between different pieces and how they interact with each other. A well named method makes it far easier to understand the flow, while a poorly named one means you might have to start looking a completely different place while still be able to quickly jump back and continue interpreting the rest. By naming related methods alike, you make the connections more obvious and easier to spot.&lt;/p&gt;
&lt;p&gt;It may not seem like a big deal, but it certainly makes your code look cleaner and easier to understand.&lt;/p&gt;</description><author>judofyr@gmail.com (Magnus Holm)</author><pubDate>Fri, 05 Jun 2009 19:39:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/judofyr/symmetry.html</link><guid>http://blog.rubybestpractices.com/posts/judofyr/symmetry.html</guid></item><item><title>RubySpec as a Community Resource (Interview w. Brian Ford)</title><description>&lt;p&gt;Though I still need to collect the details, I&amp;#8217;m about to start on another major open source project, called &lt;a href="http://github.com/madriska/unity"&gt;Unity&lt;/a&gt; .  It will be a &lt;a href="http://pledgie.com/campaigns/4640"&gt;community driven effort&lt;/a&gt; to provide a nice web resource that builds on top of the &lt;a href="http://rubyspec.org/"&gt;RubySpec&lt;/a&gt; project with reporting and search capabilities.&lt;/p&gt;
&lt;p&gt;But readers might wonder what RubySpec has to do with them, if they are not language implementers.  Here&amp;#8217;s what &lt;a href="http://blog.brightredglow.com/"&gt;Brian Ford&lt;/a&gt; had to say.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;i&gt;&lt;h4&gt;In an ideal world, what would the RubySpec project do for the Ruby community?&lt;/h4&gt;&lt;/p&gt;
&lt;p&gt;1. Provide a reasonably precise definition of the Ruby programming language so that there can be a certain degree of uniformity among the implementations. The goal is for the Ruby user to not have to think about which implementation her code runs on until she needs to, rather than writing code that works on one implementation and porting it if necessary. All software has a life cycle and the needs of the software are not always constant. A Ruby programmer should be able to develop using &lt;span class="caps"&gt;MRI&lt;/span&gt; on their laptop and deploy on Rubinius or JRuby without missing a beat, for example. Note that I use &amp;#8220;Ruby user&amp;#8221; and &amp;#8220;Ruby programmer&amp;#8221; with a distinction. A Ruby user might be anyone who relies on or provides software written in Ruby, not just someone who writes software in Ruby. So I envision a uniform definition of Ruby benefiting every strata of the Ruby community.&lt;/p&gt;
&lt;p&gt;2. Provide quality assurance and regression notification for &lt;span class="caps"&gt;MRI&lt;/span&gt; and all implementations. People put a huge amount of trust in an implementation when they decide to invest large amounts of money in developing a software product. We&amp;#8217;d like them to get some assurance for the trust they put in. Programmers are human and make mistakes. Automating the detection of mistakes is a no-brainer.&lt;/p&gt;
&lt;p&gt;3. Improving the quality of Ruby as a language by discovering dusty corners and inconsistencies. Recently, a number of inconsistencies in bang methods (e.g. String#lstrip!) were discovered by one of the RubySpec contributors. Matz quickly fixed up the issues. (You can read the gory details here: http://redmine.ruby-lang.org/issues/show/1550). Ruby as a programming language certainly exists in Matz&amp;#8217;s brain. But Ruby as an implementation (&lt;span class="caps"&gt;MRI&lt;/span&gt;) exists in many developers&amp;#8217; brains. RubySpec is an attempt to expose all that knowledge and those assumptions in an objective manner.&lt;/p&gt;
&lt;p&gt;4. Experimentation with implementations and the Ruby language itself. I have recently implemented nearly a dozen variations of Hash for Rubinius to determine which algorithms perform best. In each case, I start by writing code that will pass the RubySpec Hash specs. The specs have been generalized to use a helper method rather than referencing the Hash class constant directly. This has been a huge benefit, especially in Rubinius where the core library Hash class is written entirely in Ruby. I can inherit from Hash and override any methods to write a completely new implementation that does not interfere with the existing Hash class. The RubySpecs also provide a huge safety net and testing ground for trying out new language features and seeing how they interact with existing features.&lt;/p&gt;
&lt;p&gt;5. A learning tool that provides Ruby programmers with concrete examples of code that demonstrates every single Ruby language feature. The Pickaxe book may have better prose, but when it comes to comprehensiveness, I want RubySpec to be number one. And while we have a lot of work to do to make the spec description strings better, you can already learn a lot about Ruby by reading the specdoc output.&lt;/p&gt;
&lt;h4&gt; With everything changing so fast, I imagine keeping the specs up to date is a constant struggle. How do implementers keep up with what&amp;#8217;s going on?&lt;/h4&gt;
&lt;p&gt;Some things are changing fast but when you look at how many distinct behaviors RubySpec covers, a lot isn&amp;#8217;t changing. It&amp;#8217;s hard keeping up with the 1.9 changes. So far in Rubinius, we haven&amp;#8217;t targeted 1.9 specifically, but we have a contributor, Marc-Andre Lafortune, who has added a ton of 1.8.7 and 1.9 features to the core libraries. As with anything, you do it one thing at a time. Having RubySpec available to tell you if you are doing it right is a big help.&lt;/p&gt;
&lt;h4&gt; I would really love to make RubySpec a household name in the general Ruby community. The project I&amp;#8217;m breaking ground on now (called Unity), will hopefully help do this. What sort of information do you think is most valuable to pull out from RubySpec, and who do you see benefiting from it? &lt;/h4&gt;
&lt;p&gt;Again, the primary goal of RubySpec is to provide a definition of the Ruby programming language along with a way to test that an implementation conforms to the definition. So primary pieces of information are which specs pass and which fail on a given implementation. Evan and I have discussed adding a scoring mechanism to MSpec that provides a single percentage number as a measure of an implementation&amp;#8217;s conformance to the standard set by RubySpec. This is something that can give users better information about an implementation&amp;#8217;s completeness when it goes bandying about benchmarking numbers. I&amp;#8217;ll be implementing this in MSpec shortly.&lt;/p&gt;
&lt;h4&gt; RubySpec spans a &lt;strong&gt;ton&lt;/strong&gt; of functionality. It&amp;#8217;s amazing to see how much work has already been done. However, there must be some dark spots still left. What areas of Ruby are still not adequately specified? &lt;/h4&gt;
&lt;p&gt;That is the 10 million dollar question. We can infer something about completeness based on implementations like JRuby that run applications the same as &lt;span class="caps"&gt;MRI&lt;/span&gt; and pass the vast majority of the RubySpec cases. When implementations discover bugs in their own code and enhance the RubySpec coverage, we get a nice closed feedback loop.&lt;/p&gt;
&lt;p&gt;A lot of the standard library still needs to be covered. There are also some little used methods in the core library that lack specs. The procedural-style methods in Kernel come to mind (e.g. using methods without receivers like #gets, #puts, #sub, etc. that operate on $_). We have a utility that creates the spec files for methods and leaves marker specs that we tag as incomplete. In Rubinius, for example, you can run &amp;#8216;bin/mspec tag &amp;#8212;list incomplete&amp;#8217; and get a printout of specs that need to be reviewed for completeness.&lt;/p&gt;
&lt;p&gt;Ultimately, we need a uniform methodology for auditing the completeness and accuracy of the specs. This is still a work in progress.&lt;/p&gt;
&lt;h4&gt; Charles Oliver Nutter (of JRuby) chimes in with some additional feedback on this question: &lt;/h4&gt;
&lt;p&gt;I would inject another small answer here:&lt;/p&gt;
&lt;p&gt;In my experience with RubySpec, the areas least covered are unfortunately often the areas least understood and therefore those most in need of coverage. For example, OpenSSL specs are practically nonexistent, and yet it&amp;#8217;s such a crucial bit of functionality for any app doing &lt;span class="caps"&gt;SSL&lt;/span&gt; (as a client or a server) or working with any &lt;span class="caps"&gt;PKI&lt;/span&gt; or certificate stuff. But it&amp;#8217;s also very hard to test&amp;#8230;most people have zero knowledge of crypto, and so finding people that can write those specs is about as easy as finding people that can write OpenSSL wrappers for new implementations. So there&amp;#8217;s definitely specific areas of RubySpec that need someone with domain knowledge to dive in.&lt;/i&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;As you can see, RubySpec is a vibrant, exciting project with a lot of challenges it needs to face.  My plans are to do my part by building up the Unity app to make this awesome body of work more accessible to the Ruby community at large.   But definitely don&amp;#8217;t wait on it before getting involved, check out RubySpec today and see if there is a way you can pitch in, especially if you think you can help with some of the projects mentioned here.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;To our readers: What sorts of things can you see RubySpec being used for?  What kind of data are you interested in seeing reports on?   Do you think Brian&amp;#8217;s goals for RubySpec are attainable?  Share your thoughts in the comments below.&lt;/b&gt;&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 04 Jun 2009 07:52:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/006-brian-ford-rubyspec.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/006-brian-ford-rubyspec.html</guid></item><item><title>The Laboratory Project</title><description>&lt;p&gt;The company I am with creates billing systems for telecom companies.  More precisely we call them &amp;#8220;convergent billing systems&amp;#8221; because billing is not limited to phone calls or &lt;span class="caps"&gt;SMS&lt;/span&gt;.  You can also bill multimedia content, internet traffic and whatnot.  Basically everything that runs through your telephone or IT infrastructure.  In our office we even have a solution where the billing system is used to charge money via our corporate id cards at the local vending machine.&lt;/p&gt;
&lt;p&gt;These billing systems have a tremendous amount of interesting features.  Listing them all would need an article of its own.  For the sake of our project it is important to remember that these systems are quite complex and have a high throughput.  We have a central component implemented as a &lt;a href="http://java.sun.com/javaee/"&gt;&lt;span class="caps"&gt;JEE&lt;/span&gt;&lt;/a&gt; application which front ends to customer care and other systems that may be present at a customer site.  (The term &amp;#8220;customer&amp;#8221; is really ambiguous: there are our customers, which are telco companies and their customers, i.e. everybody using their phone lines.  I will talk about &lt;em&gt;our&lt;/em&gt; customers only.)&lt;/p&gt;
&lt;p&gt;Now, this central application writes out logfiles using usual mechanisms (you can look at &lt;a href="http://logging.apache.org/log4j/"&gt;log4j&lt;/a&gt; in case you do not know Java logging and are interested in more details).  As you can imagine these log files grow from large to huge because they will contain several lines of per business interaction (basically this is a remote call from a client system).  Sometimes these interactions fail and our support staff need to look at these log files to find out what&amp;#8217;s wrong.  When it&amp;#8217;s a tricky issue we people from the development department need to do this as well.  Simplyfying this task is the goal of this toy project.&lt;/p&gt;
&lt;p&gt;Some things you need to know about these log files:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;all log entries belonging to the same interaction share a common identifier,&lt;/li&gt;
	&lt;li&gt;they are huge,&lt;/li&gt;
	&lt;li&gt;multiple interactions are interspersed,&lt;/li&gt;
	&lt;li&gt;some log entries span multiple consecutive lines,&lt;/li&gt;
	&lt;li&gt;log files are rotated, i.e. there are some incomplete interactions at the beginning and end.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have set up a &lt;a href="http://github.com/rklemme/muppet-laboratories/tree/master"&gt;git repository&lt;/a&gt; where I created a &lt;a href="http://github.com/rklemme/muppet-laboratories/blob/ef7a28d935ada03ff141ffee6f3b19e8dfc71875/bin/test-gen.rb"&gt;generator script&lt;/a&gt; which you can use to generate sample logs and get a rough idea how they look like.  Of course, there is no real data but the basic properties from above are present.  Try to run the script with &lt;code&gt;test-gen.rb -h&lt;/code&gt; to see supported parameters.  If you don&amp;#8217;t the script will throw a lot of text at you.  I included &amp;#8220;&lt;span class="caps"&gt;START&lt;/span&gt;&amp;#8221; and &amp;#8220;&lt;span class="caps"&gt;END&lt;/span&gt;&amp;#8221; messages per interaction only to simplify testing &amp;#8211; in practice we cannot rely on the presence of lines which unambiguously identify the first and last line of an interaction.&lt;/p&gt;
&lt;p&gt;What I like to have at the end of the project is a Ruby application which efficiently separates individual interactions thus they can easily be analyzed individually.  In order to get there, we will start collecting requirements.  Let&amp;#8217;s assume for the moment that I am your customer and you try to get a list of requirements.  I would like to invite you to query me via the comment system.  I am sure, together we will come up with a better list than if I would write it down alone.  In the next article of the series I will then present the summary of our efforts.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Wed, 03 Jun 2009 21:56:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/006-The_Muppet_Project.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/006-The_Muppet_Project.html</guid></item><item><title>Enter the Muppet Laboratories</title><description>&lt;p&gt;I have decided I will start an experiement.  I haven&amp;#8217;t done this before and I have no idea whether it will work as indended but I am sure we can pull this off together.  Here&amp;#8217;s the deal: I will try to let you participate in my thought process which hopefully will turn up some useful if not best practices.  I don&amp;#8217;t claim to be Don Knuth but hopefully you&amp;#8217;ll find it interesting and worthwhile nevertheless.  The tricky part will be to actually catch all the reasonings and record them in a format suitable for blogging.&lt;/p&gt;
&lt;p&gt;In this article I will give a brief overview of how I intend to proceed.  Of course a thing like this needs some form of project.  We will come to that in a minute.  The whole series of articles will roughly look like this:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Initial presentation (this article)&lt;/li&gt;
	&lt;li&gt;Description of the project goal&lt;/li&gt;
	&lt;li&gt;Summary of collected requirements&lt;/li&gt;
	&lt;li&gt;Several postings about actual code and decisions&lt;/li&gt;
	&lt;li&gt;Presentation of the final result&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After I present the goal you are invited to help distill requirements via the blog&amp;#8217;s &lt;a href="http://disqus.com/"&gt;comment system&lt;/a&gt;.  I will be the customer for the moment and I am sure with your active support we will get a list together with requirements that the project can meet.&lt;/p&gt;
&lt;p&gt;The whole thing is loosely related to my job but I think you can extract at least parts of it for your own purposes.  Of course we&amp;#8217;ll be doing everything nicely modularized so reuse won&amp;#8217;t be an issue.  :-) I any case the main benefit for us all should be the thought process and insight into decision making during software development.&lt;/p&gt;
&lt;p&gt;The project will be about analysis of large log files which contain high numbers of small business transactions.  In parallel with coming up with a more detailed description I will try to come up with a generator which we can use to create files for testing purposes.  This should help you get a better idea of what I am talking about.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://muppet.wikia.com/wiki/Veterinarian%27s_Hospital"&gt;Tune in next week when you&amp;#8217;ll hear Dr. Bob say&amp;#8230;&lt;/a&gt;&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Fri, 29 May 2009 17:54:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/005_Enter_the_Muppet_Laboratories.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/005_Enter_the_Muppet_Laboratories.html</guid></item><item><title>Reading Ruby's Standard Library for Fun and Profit</title><description>&lt;p&gt;&lt;b&gt;Note: This post is inspired by JEG2&amp;#8217;s excellent code reading talk at &lt;span class="caps"&gt;MWRC&lt;/span&gt; 2009, called &lt;a href="http://mwrc2009.confreaks.com/13-mar-2009-10-30-littlebigruby-james-edward-grey-ii.html"&gt;LittleBIGRuby&lt;/a&gt;  Go watch it if you have time, then come back and read this.  You might also want to check out the &lt;a href="http://on-ruby.blogspot.com/2009/05/questions-five-ways-code-reading.html"&gt;Question 5 Ways&lt;/a&gt; interview at Pat Eyler&amp;#8217;s &amp;#8220;On Ruby&amp;#8221; blog for more code reading goodness.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;We all need to hunt bugs and we all need to integrate our code with other systems. Some of us need to make use of undocumented libraries, and others need to examine code to perform security audits.  Why is it then, that so many developers suck at reading code?&lt;/p&gt;
&lt;p&gt;Almost a decade ago, Joel Spolsky would have told you it&amp;#8217;s harder to &lt;a href="http://www.joelonsoftware.com/articles/fog0000000069.html"&gt;read code than it is to write it&lt;/a&gt; , and that was probably true at one point.  But times have changed, and in a language like Ruby, this definitely does not have to be the case.  As an avid code reader, I&amp;#8217;ll let you in on a secret: All you need to do is practice!&lt;/p&gt;
&lt;p&gt;Beginners and even intermediate developers may need a lot of hand holding at first, that&amp;#8217;s only to be expected.  However, if you want to progress to higher levels of understanding, you must turn to the source.  The merits of higher level idioms and design strategies won&amp;#8217;t be very clear until you need to understand someone else&amp;#8217;s code.  Once you start digging around in someone else&amp;#8217;s code base, you&amp;#8217;ll learn a lot about your own strengths and weaknesses.&lt;/p&gt;
&lt;p&gt;But where should you start?  It&amp;#8217;s tempting to suggest that you should just follow your favorite projects on Github and keep an eye on the patches as they fly.  However, this can be a bit overwhelming at first, and it may be hard to keep up with the velocity and transient nature of active open source projects.  For this reason, I suggest picking a slower moving target that is still useful to you.  Ruby&amp;#8217;s Standard Library fits this description perfectly.&lt;/p&gt;
&lt;h3&gt;How I Read Code&lt;/h3&gt;
&lt;p&gt;I&amp;#8217;m going to walk through the process I generally follow when I&amp;#8217;m reading code for the purpose of understanding its implementation.  I sometimes change things up when I have a particular goal in mind, but most of what I&amp;#8217;m about to cover is generally applicable to digging into any new code base.  Keep in mind though, our goal here is mainly just to explore a bit and maybe learn a thing or to along the way.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve chosen the Observable library here because it is small, self-contained, and easy to understand.  There are many libraries like this in the stdlib, so if you feel motivated after reading this post, you might want to go searching for a few other low hanging fruit to test your skills on.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve done what I can to boil the process down to a few repeatable steps, so you&amp;#8217;re welcome to follow along at home if you&amp;#8217;d like.&lt;/p&gt;
&lt;h4&gt;Start with a simple example.&lt;/h4&gt;
&lt;p&gt;I don&amp;#8217;t like diving into code without at least a little bit of context.  So this means that before I go source diving, I&amp;#8217;ll typically use the &lt;span class="caps"&gt;API&lt;/span&gt; documentation (if it exists), to code up a simple example.   If I can&amp;#8217;t find documentation, I&amp;#8217;ll search the web for examples.   It&amp;#8217;s relatively rare to come up completely empty, and a bit of a warning sign if you do.  But since Observable is well &lt;a href="http://www.ruby-doc.org/stdlib/libdoc/observer/rdoc/index.html"&gt;documented&lt;/a&gt; , it&amp;#8217;s easy enough to come up with something.&lt;/p&gt;
&lt;p&gt;We&amp;#8217;re dealing with the Observer design pattern (also known as Pub-Sub), and the first idea that came to mind here for me was a simple chat model.  Users could subscribe to a room and the room would publish the messages that were processed to them.  I wanted the transcripts to be personalized, so that they looked something like this:&lt;/p&gt;
&lt;pre&gt;
  = Greg's Transcript =
  Me: Hi
  Jia: Hello
  Me: Fun, huh?
  Jia: Yeah!

  = Jia's Transcript =
  Gregory: Hi
  Me: Hello
  Gregory: Fun, huh?
  Me: Yeah!
&lt;/pre&gt;
&lt;p&gt;Thinking from the outside in, we can imagine the Ruby code used to generate this output:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  room = Room.new

  greg   = Person.new("Gregory", room)
  jia    = Person.new("Jia", room)

  greg.says "Hi"
  jia.says "Hello"

  greg.says "Fun, huh?"
  jia.says "Yeah!"

  puts "= Greg's Transcript ="
  puts greg.transcript + "\n"

  puts "= Jia's Transcript ="
  puts jia.transcript
&lt;/pre&gt;
&lt;p&gt;Ultimately, what the &lt;tt&gt;Observable&lt;/tt&gt; module buys us is the ability to track subscribers implicitly rather than explicitly.  While it&amp;#8217;d be pretty easy to roll your own code here, you can see in the following definition that &lt;tt&gt;Observable&lt;/tt&gt; provides a few shortcuts for us:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require "observer"

  class Room 
    include Observable

    def receive(message, sender)
      changed
      notify_observers(message, sender)
    end
  end

  class Person
    def initialize(name, room)
      @name, @room = name, room
      @transcript  = ""
      @room.add_observer(self)
    end

    attr_reader :transcript, :name

    def update(message, sender)
      if sender == self
        message = "Me: #{message}\n"
      else
        message = "#{sender.name}: #{message}\n"
      end
    
      @transcript &amp;lt;&amp;lt; message
    end

    def says(message)
      @room.receive(message, self)
    end
  end
&lt;/pre&gt;
&lt;p&gt;This is all the code you need to reproduce the desired output, so if you&amp;#8217;re&lt;br /&gt;
interested in tinkering with it a bit, go ahead and do that now.  The real purpose of doing this however was not to implement something useful.   Instead, it was to identify some entry points into &lt;tt&gt;Observable&lt;/tt&gt; that can be our first areas of focus.&lt;/p&gt;
&lt;p&gt;If you look over the code carefully, you find that &lt;tt&gt;changed&lt;/tt&gt;, &lt;tt&gt;notify_observers&lt;/tt&gt;, and &lt;tt&gt;add_observer&lt;/tt&gt; are the keys to what makes our code tick (And incidentally, the only parts that we didn&amp;#8217;t implement ourselves.)  Let&amp;#8217;s dig a little deeper with those targets in mind.&lt;/p&gt;
&lt;h4&gt;Hunt for tests, if they exist.&lt;/h4&gt;
&lt;p&gt;Many of Ruby&amp;#8217;s standard libraries have tests distributed with the source, some do not.  Unfortunately in the case of &lt;tt&gt;Observable&lt;/tt&gt;, I couldn&amp;#8217;t find any tests for it in the Ruby source distribution.  However, that didn&amp;#8217;t mean that it was time to give up.  In cases where &lt;span class="caps"&gt;MRI&lt;/span&gt;/&lt;span class="caps"&gt;YARV&lt;/span&gt; do not have tests, you can try to turn to the great &lt;a href="http://github.com/rubyspec/rubyspec"&gt;RubySpec project&lt;/a&gt;, which is attempting to codify the behavior of Ruby with executable RSpec-like tests.&lt;/p&gt;
&lt;p&gt;As it turns out, RubySpec has &amp;#8220;several tests&amp;#8221;: for &lt;tt&gt;Observable&lt;/tt&gt;.  They are split up by each individual function.  As an example, here are the specs for &lt;tt&gt;notify_observers&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  describe "Observer#notify_observers" do
 
    before(:each) do
      @observable = ObservableSpecs.new
      @observer = ObserverCallbackSpecs.new
      @observable.add_observer(@observer)
    end
 
    it "must call changed before notifying observers" do
      @observer.value.should == nil
      @observable.notify_observers("test")
      @observer.value.should == nil
    end
 
    it "verifies observer responds to update" do
      lambda {
        @observable.add_observer(@observable)
      }.should raise_error(NoMethodError)
    end
 
    it "receives the callback" do
      @observer.value.should == nil
      @observable.changed
      @observable.notify_observers("test")
      @observer.value.should == "test"
    end
 
  end
&lt;/pre&gt;
&lt;p&gt;This code uses some helper objects, which are defined as follows:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require 'observer'
 
  class ObserverCallbackSpecs
    attr_reader :value
 
    def initialize
      @value = nil
    end
 
    def update(value)
      @value = value
    end
  end
 
  class ObservableSpecs
    include Observable
  end
&lt;/pre&gt;
&lt;p&gt;You can see how the structure of these mirror our earlier example.  When you combined them with the specs, you learn quite a bit about this method.&lt;/p&gt;
&lt;p&gt;First of all, &lt;tt&gt;notify_observers&lt;/tt&gt; doesn&amp;#8217;t do anything if you don&amp;#8217;t first call the &lt;tt&gt;changed&lt;/tt&gt; method:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  it "must call changed before notifying observers" do
    @observer.value.should == nil
    @observable.notify_observers("test")
    @observer.value.should == nil
  end
&lt;/pre&gt;
&lt;p&gt;Also, we see that any of the observers used need to implement the &lt;tt&gt;update&lt;/tt&gt; callback, matching the signature of &lt;tt&gt;notify_observers&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  it "verifies observer responds to update" do
    lambda {
      @observable.add_observer(@observable)
    }.should raise_error(NoMethodError)
  end
&lt;/pre&gt;
&lt;p&gt;Of course, when the callback exists and the observable object has been marked as changed, we see a successful result:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  it "receives the callback" do
    @observer.value.should == nil
    @observable.changed
    @observable.notify_observers("test")
    @observer.value.should == "test"
  end
&lt;/pre&gt;
&lt;p&gt;While these specs aren&amp;#8217;t necessarily giving us every last detail, they provide a general outline of what to expect when we look directly at the source.  This will help us avoid getting overwhelmed when working through the actual implementation. I&amp;#8217;ll leave it to you to check out the rest of the  &lt;a href="http://github.com/rubyspec/rubyspec/tree/1250e42264782c860259046ff93719a3e6a9f03e/library/observer"&gt;Observable specs&lt;/a&gt; if you&amp;#8217;d like.  Doing so may help you understand the code in the following section.&lt;/p&gt;
&lt;h4&gt;Dig into the source with kindness and curiosity&lt;/h4&gt;
&lt;p&gt;The main purpose of reading over the tests first is that they give you a bit of insight into what behaviors the implementation code needs to satisfy.  Assuming you didn&amp;#8217;t skip the last section, it should be pretty clear what&amp;#8217;s going on in the following method definition:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def notify_observers(*arg)
    if defined? @observer_state and @observer_state
      if defined? @observer_peers
        @observer_peers.each { |k, v| k.send v, *arg }
      end
      @observer_state = false
    end
  end
&lt;/pre&gt;
&lt;p&gt;Of course, the &amp;#8216;why&amp;#8217; is as important as the &amp;#8216;how&amp;#8217; when you&amp;#8217;re exploring someone else&amp;#8217;s code. Without looking any farther, one thing that tripped me up was this line:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  if defined? @observer_state and @observer_state
&lt;/pre&gt;
&lt;p&gt;It was immediately clear to me what it did, but not why it was needed.  Upon further investigation, I remembered one of my bad habits.  The following code will issue a warning as written:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module A
    def foo
      @foo
    end
  end

  class B
    include A
  end

  B.new.foo
&lt;/pre&gt;
&lt;p&gt;However, we can avoid this warning using the exact same approach used in &lt;tt&gt;Observable&lt;/tt&gt;, simply by checking whether the instance variable is defined before accessing it:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module A
    def foo
      @foo if defined?(@foo)
    end
  end
&lt;/pre&gt;
&lt;p&gt;Yes, this is more verbose, and seems a bit redundant.  But writing code this way does have a real benefit.   If you follow this convention of checking whether an instance variable is defined whenever you aren&amp;#8217;t sure it will be, this warning can be used to easily catch typos.  The following example, when run with warnings enabled, will illustrate how:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class A
    def foo
      @foo = 10
      bar
    end

    def bar
      @bar = @fooo
    end
  end

  A.new.foo
&lt;/pre&gt;
&lt;p&gt;At this point, I already found a helpful reminder by walking through this code.  While the rest of the source was an interesting read, this was my takeaway.  Please go ahead and read the &lt;a href="http://pastie.org/488486"&gt;full source&lt;/a&gt; and let me know in the comments if you found anything of interest.&lt;/p&gt;
&lt;p&gt;In fact, I have a question for our readers.  Can you find any reason why the following code is written as it is?&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # Query the changed state of this object.
  #
  def changed?
    if defined? @observer_state and @observer_state
      true
    else
      false
    end
  end
&lt;/pre&gt;
&lt;p&gt;This looks a bit like a wart to me, and if anything, seems like a long way to go in order to avoid &lt;tt&gt;!!obj&lt;/tt&gt;.   But maybe someone else sees it in a different light?  Actually, that reminds me&amp;#8230;&lt;/p&gt;
&lt;h3&gt;Caveats about the Standard Library&lt;/h3&gt;
&lt;p&gt;While Ruby&amp;#8217;s stdlib is a great place to learn new things, not everything in it is downright beautiful.   Some things are older than others, some reflecting the rust that comes when code is not updated to reflect the latest techniques.&lt;/p&gt;
&lt;p&gt;Furthermore, standard library code tends to be less clever than the sort of stuff we might write for our scripts and gems, by design.  You&amp;#8217;ll find that in many places, explicit and simple code is favored over tricky stuff.  I imagine this is for maintainability purposes.&lt;/p&gt;
&lt;p&gt;Like anything else, you&amp;#8217;ll need to do a bit of hunting to find the right code to learn from.   This practice in and of itself will prove to be useful, so don&amp;#8217;t be afraid if you run across some cruft now and again.&lt;/p&gt;
&lt;p&gt;Of course, another good thing about reading code is that it often inspires us to write code.  While looking through the standard library, consider putting together documentation patches, adding tests, and fixing things you don&amp;#8217;t like.  I&amp;#8217;m sure the folks on &lt;a href="http://www.ruby-lang.org/en/community/mailing-lists/"&gt;ruby-core&lt;/a&gt; would be happy to look at your contributions, and it&amp;#8217;s another great way to learn.&lt;/p&gt;
&lt;h3&gt;Key Things To Remember&lt;/h3&gt;
&lt;p&gt;Code reading is just as important as code writing.  The standard library has about 100 places for you to look for inspiration, and its more likely than not that you&amp;#8217;ll find something of interest if you pick one at random.  If you repeat this process, you&amp;#8217;ll get a better understanding of how Ruby itself works, and be able to carry this experience into your own work.&lt;/p&gt;
&lt;p&gt;Start by playing with some examples, then look for tests, either in the source or in the RubySpec project.  Once you feel like you understand how to use a feature, investigate how it works, and then ask yourself why it is written the way it is.  Don&amp;#8217;t expect to understand the whole thing all at once, and don&amp;#8217;t worry if it takes some time to adjust to someone else&amp;#8217;s style.&lt;/p&gt;
&lt;p&gt;If you do this often enough, you&amp;#8217;ll gain a valuable skill that&amp;#8217;ll pay off like crazy, especially if you work on open source software.  You&amp;#8217;ll notice both patterns and anti-patterns, and this will influence the code you write.  In the end, your fellow code readers will thank you :)&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Sun, 24 May 2009 18:25:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/005-code-reading-stdlib.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/005-code-reading-stdlib.html</guid></item><item><title>Control flow features and readability</title><description>&lt;p&gt;First of all I would like to thank our readers who participate in discussions so actively!  These discussions provide interesting food for thought as well as inspirations for new blog entries.  Today&amp;#8217;s article was partly inspired by the question that surfaced recently: &amp;#8220;Why is &lt;code&gt;catch .. throw&lt;/code&gt; seen so infrequently?&amp;#8221;&lt;/p&gt;
&lt;p&gt;In this article I will explore how the choice of &lt;a href="http://en.wikipedia.org/wiki/Control_flow"&gt;control flow&lt;/a&gt; constructs and their usage affects readability and maintainability of code.  For the purpose of this investigation I will provide a definition, partly because the Wikipedia article seems a bit inconsistent and partly because it may change.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A control flow construct is a language feature which disrupts the normal progression to the next statement and conditionally or unconditionally branches to another location in source code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This definition includes the usual &lt;code&gt;if ... then&lt;/code&gt; but also method invocation and &lt;code&gt;return&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Classes of control flow statements&lt;/h3&gt;
&lt;p&gt;Following a sequence of regular (i.e. non control flow) statements is easy.  Things get only slightly more complicated for the reader in case of &lt;code&gt;if ... then ... else ... end&lt;/code&gt; as long as proper indentation is used and we do not have to scroll multiple pages to see the other branch(es).&lt;/p&gt;
&lt;p&gt;But it is a different story altogether if the stack frame changes and we as readers have to &lt;strong&gt;jump&lt;/strong&gt; to a completely different location &amp;#8212; maybe even in a different file!  Hence I will classify control flow constructs depending on the distance measured in stack frames:&lt;/p&gt;
&lt;dl&gt;
	&lt;dt&gt;level-0&lt;/dt&gt;
	&lt;dd&gt;There is no change in stack frame at all.&lt;/dd&gt;
	&lt;dt&gt;level-1&lt;/dt&gt;
	&lt;dd&gt;Code moves one stack frame up or down.&lt;/dd&gt;
	&lt;dt&gt;level-n&lt;/dt&gt;
	&lt;dd&gt;An arbitrary amount of stack frames can be added or removed.&lt;/dd&gt;
	&lt;dt&gt;level-x&lt;/dt&gt;
	&lt;dd&gt;The stack is completely exchanged.&lt;/dd&gt;
	&lt;dt&gt;level-1n&lt;/dt&gt;
	&lt;dd&gt;This is a hybrid where &amp;#8220;technical&amp;#8221; and &amp;#8220;visual&amp;#8221; jumps differ.&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;I am sure those first three categories do not bear any surprises for you.  The last two probably need a bit of explanation.  Category &lt;em&gt;level-x&lt;/em&gt; contains Ruby&amp;#8217;s continuations.  I won&amp;#8217;t cover them here because I am not too familiar with them, they are rarely used in &amp;#8220;ordinary&amp;#8221; code and they are so complex that they probably deserve an article of their own.  It should be obvious that this complexity does not really help understanding code.&lt;/p&gt;
&lt;h3&gt;level-0&lt;/h3&gt;
&lt;p&gt;This category includes&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;if ... then ... elsif ... else ... end&lt;/code&gt; as well as &lt;code&gt;unless ...&lt;/code&gt;,&lt;/li&gt;
	&lt;li&gt;ternary operator &lt;code&gt;... ? ... : ...&lt;/code&gt;,&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt; and &lt;code&gt;until&lt;/code&gt; loops,&lt;/li&gt;
	&lt;li&gt;both forms of &lt;code&gt;case&lt;/code&gt; statements,&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;and&lt;/code&gt; and &lt;code&gt;or&lt;/code&gt;,&lt;/li&gt;
	&lt;li&gt;all statement modifiers (&lt;code&gt;if&lt;/code&gt; etc. at the end of a statement).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All these provide for easy following of code and can &amp;#8212; when chosen wisely &amp;#8212; even form Ruby code which almost reads like English.  There are really only two things that can make them hard to follow&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;Not indenting code properly.&lt;/li&gt;
	&lt;li&gt;Putting too much lines of code between different keywords belonging to the same construct.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;As long as you follow these basic rules, the reader of your code will be able to follow the flow easily.&lt;/p&gt;
&lt;h3&gt;level-1&lt;/h3&gt;
&lt;p&gt;In this category we have&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;method invocation,&lt;/li&gt;
	&lt;li&gt;method return.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note, that I did not place &lt;code&gt;return&lt;/code&gt; in this category &amp;#8212; we will see it in &lt;em&gt;level-1n&lt;/em&gt; below.&lt;/p&gt;
&lt;p&gt;The readability of a method invocation depends mostly on how good it conveys what the method does.  A Ruby programmer who reads &lt;code&gt;x.to_s&lt;/code&gt; immediately knows that this expression returns a string representation of &lt;code&gt;x&lt;/code&gt;.  (Strictly speaking there is of course no guarantee that this method actually returns a String instance but for all practical purposes we can safely assume this.)&lt;/p&gt;
&lt;p&gt;For unknown methods the name is crucial for our understanding &amp;#8212; or at least rough idea &amp;#8212; of what happens during the method call.  This is important because only if we have this understanding we can continue reading and understand what the current method does.  This shows how maintainability not only depends on proper modularization but also on well chosen method names.  In fact it might be more important to get a method&amp;#8217;s name right than to have documentation which covers all aspects of the method&amp;#8217;s semantics.  Don&amp;#8217;t get me wrong, I do not want you to neglect your documentation!  But a proper chosen name goes a long way in telling the reader of the code that &lt;em&gt;uses&lt;/em&gt; this method what it does.&lt;/p&gt;
&lt;h3&gt;level-n&lt;/h3&gt;
&lt;p&gt;Again, there are two contenders:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;raise ... rescue&lt;/code&gt;,&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;catch ... throw&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although these two may seem to only differ in syntax on first sight, there are fundamental differences.  I believe that these are ultimately the reason why we see exceptions quite frequently while we rarely discover a &lt;code&gt;catch&lt;/code&gt; statement in code.  Let&amp;#8217;s first look at exceptions:&lt;/p&gt;
&lt;p&gt;The power of exceptions comes from decoupling the signalling of an error and its handling.  The meaning of the error condition is engraved in the exception class (via inheritance and documentation).  We know that &lt;code&gt;Errno::ENOENT&lt;/code&gt; denotes a non existing file and we can write an exception handler for this.  When we &lt;code&gt;raise&lt;/code&gt; this exception we do not know how many stack frames upwards there will be a handler for it &amp;#8212; and we do not need to.  If there is none ultimately the interpreter will exit with an error message and an exit code != 0.&lt;/p&gt;
&lt;p&gt;Contrast this with &lt;code&gt;catch ... throw&lt;/code&gt; &amp;#8212; everything seems to be the opposite here:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;This combination is for &lt;em&gt;regular&lt;/em&gt; control flow and not for dealing with &lt;em&gt;error&lt;/em&gt; situations.&lt;/li&gt;
	&lt;li&gt;You&amp;#8217;ll first see the &lt;code&gt;catch&lt;/code&gt; and then &lt;code&gt;throw&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;There is strong coupling between the &lt;code&gt;catch&lt;/code&gt; location and the &lt;code&gt;throw&lt;/code&gt; location in code via the symbol used; and both statements can be in different methods altogether.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, if you indeed place &lt;code&gt;catch&lt;/code&gt; and &lt;code&gt;throw&lt;/code&gt; in different methods you have established a strong link between the two: in order for the program to work properly both need to use the same symbol and both must be aware of the returned object (if any) so the result of &lt;code&gt;catch&lt;/code&gt; can be processed in any meaningful way.  You also need to take care about the last statement in the block attached to the &lt;code&gt;catch&lt;/code&gt; in order to not accidentally return something which will be interpreted as thrown return value.&lt;/p&gt;
&lt;p&gt;It&amp;#8217;s fairly easy to complicate things even more by placing &lt;code&gt;catch&lt;/code&gt; and &lt;code&gt;throw&lt;/code&gt; methods in different classes or by nesting two or more &lt;code&gt;catch&lt;/code&gt; constructs.  It&amp;#8217;s fairly safe to say that these obfuscating effects are best avoided by using &lt;code&gt;catch ... throw&lt;/code&gt; in a single method only &amp;#8212; and in that case there are other control flow constructs that we can usually use.  In fact I am still searching for more convincing examples of &lt;code&gt;catch ... throw&lt;/code&gt; usage; so far the best contender has been a jump out of multiple nested loops.  Although, to me the &amp;#8220;multiple nested loops&amp;#8221; item has a slight &lt;a href="http://c2.com/xp/CodeSmell.html"&gt;code smell&lt;/a&gt; of its own.  But, read on&amp;#8230;&lt;/p&gt;
&lt;p&gt;&lt;ins&gt;&lt;em&gt;Addition:&lt;/em&gt;&lt;/ins&gt; Actually, you can &lt;a href="http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_9_1/lib/find.rb?view=markup"&gt;find&lt;/a&gt; a good application of &lt;code&gt;catch ... throw&lt;/code&gt; in Ruby&amp;#8217;s standard library.  In this case it is elegant and &lt;code&gt;catch ... throw&lt;/code&gt; has the advantage of not interfering with exception handling: assume more complex code in the block which is passed to &lt;code&gt;Find.find&lt;/code&gt; which has a &lt;code&gt;rescue&lt;/code&gt; internally then using exceptions behind the scene might have surprising effects.&lt;/p&gt;
&lt;h3&gt;level-1n&lt;/h3&gt;
&lt;p&gt;You might be curious why I came up with this category.  Let&amp;#8217;s first look at an example: assume there is a method that yields all Ruby files which are found below any number of directories and we use that to write another method which returns the first of those files that we own:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def find_my_ruby_file(*dirs)
  find_ruby_files *dirs do |f|
    return f if File.stat(f).owned?
  end
  nil
end
&lt;/pre&gt;
&lt;p&gt;Now, if &lt;code&gt;return&lt;/code&gt; is executed &lt;code&gt;find_my_ruby_file&lt;/code&gt; exits and returns &lt;code&gt;f&lt;/code&gt;, we go up one stack frame.  Visually this is true, but in reality, when &lt;code&gt;return&lt;/code&gt; is executed, the stack is several levels deeper than it appears to be.  You can easily check that by inserting something like &lt;code&gt;puts caller(0)&lt;/code&gt; before the &lt;code&gt;return&lt;/code&gt; &amp;#8211; here&amp;#8217;s a complete version that you can use to experiment:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
require 'find'

def find_ruby_files(*dirs)
  Find.find *dirs do |file|
    yield file if test ?f, file and /\.rb\z/i =~ file
  end
ensure
  puts 'exit find_ruby_files'
end

def find_my_ruby_file(*dirs)
  find_ruby_files *dirs do |f|
    if File.stat(f).owned?
      puts 'found!', 'stack &amp;lt;&amp;lt;&amp;lt;', caller(0), '&amp;gt;&amp;gt;&amp;gt; stack'
      return f
    end
  end
  nil
ensure
  puts 'exit find_my_ruby_file'
end

p find_my_ruby_file(*ARGV)
&lt;/pre&gt;
&lt;p&gt;You&amp;#8217;ll find some surprising entries there and as a side effect I now know one more example where &lt;code&gt;catch ... throw&lt;/code&gt; does seem like the best tool for the job&amp;#8230;&lt;/p&gt;
&lt;p&gt;This property of being able to exit more stack frames than visible on first sight is shared by &lt;code&gt;break&lt;/code&gt; which can be used to exit multiple stack levels in a similar way.  It won&amp;#8217;t leave the current method (i.e. the method in which it is &lt;a href="http://en.wikipedia.org/wiki/Lexical_scope#Static_scoping_.28also_known_as_lexical_scoping.29"&gt;lexically scoped&lt;/a&gt;) but via invoked methods with blocks the unnesting can include any number of stack frames.  This reinforces what we have said &lt;a href="002_Writing_Block_Methods.html"&gt;before&lt;/a&gt; since we now clearly see that there are more ways that a block of code can be left &amp;#8220;not normally&amp;#8221; besides &lt;code&gt;raise&lt;/code&gt; and &lt;code&gt;throw&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;What do we learn?&lt;/h3&gt;
&lt;p&gt;Looking at control flow constructs from an execution stack perspective has provided some interesting insights (at least to me).  While general rules for readability (proper indentation, limit the amount someone has to read etc.) do apply here as well, some of those constructs can have surprising effects on program behavior and should be used carefully.  This is especially true for the &amp;#8220;far reaching&amp;#8221; constructs which can actually make the stack unwind multiple levels &amp;#8212; or even change completely as in the case of &lt;code&gt;callcc&lt;/code&gt;.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Tue, 19 May 2009 20:46:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/004-Control_Flow.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/004-Control_Flow.html</guid></item><item><title>Hello World (Literally)</title><description>&lt;p&gt;If Google Analytics is right, we&amp;#8217;ve reached 68 countries in the last three days.  Although I guess this doesn&amp;#8217;t mean much at all on the internet, I think it still makes for a pretty map:&lt;/p&gt;
&lt;table style="width:auto;"&gt;&lt;tr&gt;&lt;td&gt;&lt;a href="http://picasaweb.google.com/lh/photo/-OyFgPdlht14elpNP9-G8A?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_hoiny8_4IEY/Sf_dRKHgzcI/AAAAAAAAALM/yFs0gVNO1To/s800/blog-rbp.png" width="600" /&gt;&lt;/a&gt;&lt;/td&gt;&lt;p&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td style="font-family:arial,sans-serif; font-size:11px; text-align:right"&gt;From &lt;a href="http://picasaweb.google.com/gregory.t.brown/RBP?feat=embedwebsite"&gt;&lt;span class="caps"&gt;RBP&lt;/span&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/p&gt;
&lt;p&gt;Of course, I&amp;#8217;d like to back up these statistics with some direct data, so I&amp;#8217;ve got three questions for our readers:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;Where are you from?&lt;/li&gt;
	&lt;li&gt;What is the Ruby scene like where you live?&lt;/li&gt;
	&lt;li&gt;What would you like to see on the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Please join in the conversation and let us know who you are.  So far, the discussions on this blog have been great and I want to get to know more of our readers.  We&amp;#8217;ll resume regularly scheduled deep tech content soon, but hopefully this small diversion will prove to be interesting.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 05 May 2009 06:42:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/hello_world.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/hello_world.html</guid></item><item><title>The Universe between begin and end</title><description>&lt;p&gt;This time we&amp;#8217;ll explore the space between &lt;code&gt;begin&lt;/code&gt; and &lt;code&gt;end&lt;/code&gt;.  Today&amp;#8217;s article won&amp;#8217;t be as much about individual best practices but rather I will try to explore various aspects of &lt;code&gt;begin ... end&lt;/code&gt; blocks so you can decide how to make best use of this tool.  In fact, there are so many aspects that this construct sometimes reminds me of a swiss army knife &amp;#8211; not so much because you can do everything with it but rather because it has so many features that you can use.  When it comes to control structuring elements &lt;code&gt;begin ... end&lt;/code&gt; is probably the most complex thing found in Ruby.&lt;/p&gt;
&lt;p&gt;One final introductory remark: although I am pretty sure that Ruby hasn&amp;#8217;t changed between 1.8 and 1.9 with regard to &lt;code&gt;begin ... end&lt;/code&gt; I did my tests with 1.9.1 only.  So if you find something to be wrong, please comment!&lt;/p&gt;
&lt;h3&gt;Starting the Investigation&lt;/h3&gt;
&lt;p&gt;For easier reference here&amp;#8217;s a block which contains all the options:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
begin
  # do our work
rescue
  # standard oops!
rescue SomeException =&amp;gt; e
  # oops!
rescue Exception =&amp;gt; e
  # deal with other errors
else
  # good, no exception surfaced!
ensure
  # good or bad, this needs to be done
end
&lt;/pre&gt;
&lt;p&gt;Note that you can replace &lt;code&gt;begin&lt;/code&gt; with &lt;code&gt;def meth...&lt;/code&gt; to define a method with &amp;#8220;integrated&amp;#8221; exception handling.  That way you can avoid one level of nesting.&lt;/p&gt;
&lt;p&gt;There are various interesting aspects to each section:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;control flow (most particularly, how is the section left?),&lt;/li&gt;
	&lt;li&gt;result (if any),&lt;/li&gt;
	&lt;li&gt;documentation (what does it tell me that code is in a particular section?).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We&amp;#8217;ll keep these in the back of our heads when exploring section after section.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;begin&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This is the main section where you place the code that does the work you want to get done.  If evaluation reaches the end of this section normally the result of the last expression evaluated is also the result of this section.  In the absence of &lt;code&gt;rescue&lt;/code&gt; or &lt;code&gt;else&lt;/code&gt; that value is propagated to the surrounding context.&lt;/p&gt;
&lt;p&gt;If we look at control flow things start to get a bit more involved.  First, you should note that there are these additional ways this section (actually &lt;em&gt;any&lt;/em&gt; section of code) can be terminated:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;code&gt;return&lt;/code&gt; is executed,&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;break&lt;/code&gt; is executed in a &lt;code&gt;do&lt;/code&gt; block invoked,&lt;/li&gt;
	&lt;li&gt;an exception is triggered via &lt;code&gt;raise&lt;/code&gt;,&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;throw&lt;/code&gt; is invoked.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;How many of those did you think of?  (Did I miss another one?)  All these have one thing in common: the end of the section is not reached normally and the code produces a different result.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;rescue&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This can have an optional &lt;code&gt;ExceptionType =&amp;gt; variable&lt;/code&gt; in which case exceptions of this class and subclasses (if there are no preceeding rescue clauses with them) are caught.  If that optional part is missing only &lt;code&gt;StandardError&lt;/code&gt; and subclasses are caught.&lt;/p&gt;
&lt;p&gt;If there are multiple &lt;code&gt;rescue&lt;/code&gt; clauses, order matters.  You must rescue most specific errors first and less specificerrors later because otherwise a super class &lt;code&gt;rescue&lt;/code&gt; clause will shadow a sub class clause which comes later.  Only one rescue clause of a group is ever executed.&lt;/p&gt;
&lt;p&gt;In case a rescue clause is executed the result of the whole block is that of the code in the rescue clause.  In other words: when catching exceptions the exception code replaces the block&amp;#8217;s result.  Unless, that is, you invoke &lt;code&gt;raise&lt;/code&gt; or &lt;code&gt;retry&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The tricky part about &lt;code&gt;rescue&lt;/code&gt; is which exceptions to catch.  If you cannot handle an exception, you should not catch it because otherwise you will prevent other code that is capable of handling it to work.  Actually, as long as you do not &lt;code&gt;raise&lt;/code&gt; again, nobody outside will notice that there was an error in the first place.  A special case is &lt;code&gt;raise&lt;/code&gt; without arguments: sometimes it is reasonable to catch all exceptions, log the event and rethrow:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
def f
  do_work
rescue Exception =&amp;gt; e
  log.error "There was an error: #{e.message}"
  raise
end
&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;else&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This section does make sense only if there is a &lt;code&gt;rescue&lt;/code&gt; as well.  (You&amp;#8217;ll get a warning if you use it without it.)  If the main section completes regularly and an &lt;code&gt;else&lt;/code&gt; section is present it is executed.&lt;/p&gt;
&lt;p&gt;Now, some of the &lt;a href="http://blog.rubybestpractices.com/posts/rklemme/002_Writing_Block_Methods.html#dsq-cite-8500023"&gt;discussion&lt;/a&gt; revolved around the utility of this section and whether code placed here is equivalent to code placed in other places.  While at first sight it may seem that you can just place it at the end of the main section a closer look reveals some subtleties, some of which have been mentioned already in the discussion.  I&amp;#8217;ll list them here anyway for completeness reasons:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;If the code raises an exception, it might be rescued when placed in the main section but it won&amp;#8217;t be rescued when placed in &lt;code&gt;else&lt;/code&gt; section.  This might also lead to unnecessary retries if there is a &lt;code&gt;retry&lt;/code&gt; in the &lt;code&gt;rescue&lt;/code&gt; clause.&lt;/li&gt;
	&lt;li&gt;Placing the code after &lt;code&gt;end&lt;/code&gt; generally has a similar effect as putting it in an &lt;code&gt;else&lt;/code&gt; section but if there is an &lt;code&gt;ensure&lt;/code&gt; section order of execution between the two code bits is reversed.  This can make a serious difference if the &lt;code&gt;else&lt;/code&gt; code uses a resource which is cleaned up in &lt;code&gt;ensure&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;When using the version of &lt;code&gt;begin ... end&lt;/code&gt; in a method definition there is no place &amp;#8220;after end&amp;#8221; which is part of the method invocation:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre name="code" class="ruby"&gt;
def do_the_work
  some_code_which_may_throw
rescue ArgumentError
  $stderr.puts "Ooops! Passed the wrong argument."
else
  puts "Job done."
end
&lt;/pre&gt;
&lt;h3&gt;&lt;code&gt;ensure&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This section is the last one before the final &lt;code&gt;end&lt;/code&gt;.  Code in this section will be executed regardless of how the main section is left, i.e. even in case of &lt;code&gt;raise&lt;/code&gt;, &lt;code&gt;throw&lt;/code&gt;, &lt;code&gt;return&lt;/code&gt; and &lt;code&gt;break&lt;/code&gt;!  The result of the section is ignored unless you choose to explicitly &lt;code&gt;return&lt;/code&gt; it or raise an exception.  While raising exceptions might be reasonable in some cases, it should generally be avoided because those exceptions will shadow errors coming from the main section or from &lt;code&gt;rescue&lt;/code&gt; clauses:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):007:0&amp;gt; def f
irb(main):008:1&amp;gt; raise "Foo"
irb(main):009:1&amp;gt; ensure
irb(main):010:1* raise "Bar"
irb(main):011:1&amp;gt; end
=&amp;gt; nil
irb(main):012:0&amp;gt; f
RuntimeError: Bar
        from (irb):10:in `ensure in f'
        from (irb):10:in `f'
        from (irb):12
        from /usr/local/bin/irb19:12:in `&amp;lt;main&amp;gt;'
irb(main):013:0&amp;gt;
&lt;/pre&gt;
&lt;p&gt;Another thing you should definitively avoid is a &lt;code&gt;return&lt;/code&gt; statement in &lt;code&gt;ensure&lt;/code&gt; because this will shadow the result from the &amp;#8220;business logic&amp;#8221; code in the main section:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
irb(main):013:0&amp;gt; def f
irb(main):014:1&amp;gt; 1
irb(main):015:1&amp;gt; ensure
irb(main):016:1* 2
irb(main):017:1&amp;gt; end
=&amp;gt; nil
irb(main):018:0&amp;gt; f
=&amp;gt; 1
irb(main):019:0&amp;gt; def g
irb(main):020:1&amp;gt; 1
irb(main):021:1&amp;gt; ensure
irb(main):022:1* return 2
irb(main):023:1&amp;gt; end
=&amp;gt; nil
irb(main):024:0&amp;gt; g
=&amp;gt; 2
irb(main):025:0&amp;gt;
&lt;/pre&gt;
&lt;p&gt;There&amp;#8217;s a reason why the result of executing &lt;code&gt;ensure&lt;/code&gt; section is ignored: this code has nothing to do with the &amp;#8220;business logic&amp;#8221; which should go into the main section but is solely for cleaning up.  Assume you open a file with &lt;code&gt;io = File.open&lt;/code&gt; (which I hope you won&amp;#8217;t do after reading a &lt;a href="001-Using_blocks_for_Robustness.html"&gt;previous post&lt;/a&gt;), have search code in the main section and place &lt;code&gt;io.close&lt;/code&gt; in an &lt;code&gt;ensure&lt;/code&gt; section.  Then you would not want to shadow the result of the search by the result from the close operation.&lt;/p&gt;
&lt;p&gt;Although ehsanul &lt;a href="http://blog.rubybestpractices.com/posts/rklemme/002_Writing_Block_Methods.html#dsq-cite-8562863"&gt;questioned the utility&lt;/a&gt; of &lt;code&gt;ensure&lt;/code&gt; I certainly use it more often than &lt;code&gt;else&lt;/code&gt;.  While &lt;code&gt;else&lt;/code&gt; section code can be put somewhere else in some cases, there is no other place of code which can easily replace an &lt;code&gt;ensure&lt;/code&gt; clause and guarantee the same robustness of the code at the same time.  This is nicely demonstrated by his suggested alternative which uses only &lt;code&gt;rescue&lt;/code&gt; without &lt;code&gt;Exception&lt;/code&gt; &amp;#8212; this does not catch all exceptions!  &amp;#8220;Robustness&amp;#8221; in this case refers not only to runtime robustness but also robustness of the code against maintenance (i.e. changes).&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s assume you have caught all exceptions via &lt;code&gt;rescue&lt;/code&gt; clauses which do not raise and placed your cleanup code after &lt;code&gt;end&lt;/code&gt; as it was suggested.  Code works as expected and everything is fine.  You might have to use a local variable to make sure the proper value is returned from your method but this is just a nuisance.  Now all these changes will put execution of your cleanup code at danger:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;A &lt;code&gt;rescue&lt;/code&gt; clause is removed.&lt;/li&gt;
	&lt;li&gt;A previously uncaught exception type is thrown from the main section (the change need not be in your piece of code).&lt;/li&gt;
	&lt;li&gt;A &lt;code&gt;rescue&lt;/code&gt; clause is changed to raise an exception.&lt;/li&gt;
	&lt;li&gt;An &lt;code&gt;else&lt;/code&gt; section is introduced and code might throw.&lt;/li&gt;
	&lt;li&gt;Code in &lt;code&gt;else&lt;/code&gt; section is changed to raise an exception.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And lastly, do not underestimate readability!  Placing code in an &lt;code&gt;ensure&lt;/code&gt; section tells the reader immediately that he can ignore it when trying to understand what the main purpose of the code is.  This is &amp;#8220;only&amp;#8221; cleanup which makes sure some resources that were used for the calculation are not kept longer than needed.  Whereas, if you place that code after &lt;code&gt;end&lt;/code&gt; it could belong to the normal flow of the core business logic.&lt;/p&gt;
&lt;h3&gt;Guidelines&lt;/h3&gt;
&lt;p&gt;So after all the detail here are some rules which I hope will guide you in making the most appropriate use of &lt;code&gt;begin ... end&lt;/code&gt; blocks.&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;If you have cleanup code that must be executed under all circumstances, put it in &lt;code&gt;ensure&lt;/code&gt;.&lt;/li&gt;
	&lt;li&gt;Do not place &lt;code&gt;return&lt;/code&gt; or &lt;code&gt;break&lt;/code&gt; in &lt;code&gt;ensure&lt;/code&gt; sections and try to avoid throwing exceptions from them.&lt;/li&gt;
	&lt;li&gt;Place &lt;code&gt;rescue&lt;/code&gt; clauses for more specific exceptions (sub classes) before those for less specific ones (super classes).&lt;/li&gt;
	&lt;li&gt;&lt;code&gt;rescue&lt;/code&gt; the most specific exception you can handle.&lt;/li&gt;
	&lt;li&gt;Do not &lt;code&gt;rescue&lt;/code&gt; exceptions that you cannot or do not want to handle.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Keep in mind that these are just guidelines and you have to check on a case by case basis which is the most appropriate solution.  As Buddha says: verify the teaching with your own mind.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Fri, 01 May 2009 10:05:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/003-The_Universe_between_begin_and_end.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/003-The_Universe_between_begin_and_end.html</guid></item><item><title>Fun with Class.new</title><description>&lt;p&gt;&lt;i&gt;Update: I came across an inlink to this page that was layering in advertisements in a frame. Luckily, there are &lt;a href="http://github.com/sandal/rbp-blog/commit/97df49430262beb8ddbb067fba5f1756efd4aac5"&gt;technical solutions&lt;/a&gt; to at least some social problems, and you may now browse again in peace :)&lt;/i&gt;&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;ve worked with Ruby for at least a little while, you might already know that classes in Ruby are objects themselves, in particular, instances of &lt;tt&gt;Class&lt;/tt&gt;.  Before I get into the fun stuff, let&amp;#8217;s quickly recap what that means.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s the ordinary way we define classes, as you all have seen.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Point
    def initialize(x,y)
      @x, @y = x,y
    end
    
    attr_reader :x, :y
    
    def distance(point)
      Math.hypot(point.x - x, point.y - y)
    end
  end 
&lt;/pre&gt;
&lt;p&gt;The interesting thing is that the previous definition is essentially functionally equivalent to the following:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  Point = Class.new do
    def initialize(x,y)
      @x, @y = x,y
    end
  
    attr_reader :x, :y
  
    def distance(point)
      Math.hypot(point.x - x, point.y - y)
    end
  end
&lt;/pre&gt;
&lt;p&gt;This always struck me as a beautiful design decision in Ruby, because it reflects the inherent simplicity of the object model while exposing useful low level hooks for us to use.  Building on this neat concept of anonymously defined classes, I&amp;#8217;ll share a few tricks that have been useful to me in real projects.&lt;/p&gt;
&lt;h3&gt;Cleaner Exception Definitions&lt;/h3&gt;
&lt;p&gt;This sort of code has always bugged me:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module Prawn
    module Errors
     
       class FailedObjectConversion &amp;lt; StandardError; end
     
       class InvalidPageLayout &amp;lt; StandardError; end        
     
       class NotOnPage &amp;lt; StandardError; end

       class UnknownFont &amp;lt; StandardError; end   

       class IncompatibleStringEncoding &amp;lt; StandardError; end     

       class UnknownOption &amp;lt; StandardError; end

    end
  end
&lt;/pre&gt;
&lt;p&gt;Although there are valid reasons for subclassing a &lt;tt&gt;StandardError&lt;/tt&gt;, typically the only reason I am doing it is to get a named exception to rescue.  I don&amp;#8217;t plan to ever add any functionality to its subclass beyond a named constant.  However, if we notice that &lt;tt&gt;Class.new&lt;/tt&gt; can be used to create subclasses, you can write something that more clearly reflects this intention:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  module Prawn
    module Errors
       FailedObjectConversion = Class.new(StandardError)
            
       InvalidPageLayout = Class.new(StandardError)     
     
       NotOnPage = Class.new(StandardError)

       UnknownFont = Class.new(StandardError)

       IncompatibleStringEncoding = Class.new(StandardError)     

       UnknownOption = Class.new(StandardError) 

    end
  end
&lt;/pre&gt;
&lt;p&gt;This feels a bit nicer to me, because although it&amp;#8217;s somewhat clear that these are still subclasses, I don&amp;#8217;t have an ugly empty class definition that will never be filled.  Of course, we could make this more &lt;span class="caps"&gt;DRY&lt;/span&gt; if we mix in a little &lt;tt&gt;const_set&lt;/tt&gt; hackery:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
module Prawn
  module Errors
  
    exceptions = %w[ FailedObjectConversion InvalidPageLayout NotOnPage
                    UnknownFont IncompatibleStringEncoding UnknownOption ]

    exceptions.each { |e| const_set(e, Class.new(StandardError)) }

  end
end
&lt;/pre&gt;
&lt;p&gt;Even with this concise definition, you&amp;#8217;ll still get the functionality you&amp;#8217;d expect:&lt;/p&gt;
&lt;pre&gt;
&amp;gt;&amp;gt; Prawn::Errors::IncompatibleStringEncoding.ancestors
=&amp;gt; [Prawn::Errors::IncompatibleStringEncoding, StandardError, Exception, Object, Kernel]
&amp;gt;&amp;gt; raise Prawn::Errors::IncompatibleStringEncoding, "Bad string encoding"
Prawn::Errors::IncompatibleStringEncoding: Bad string encoding
	from (irb):33
	from :0
&lt;/pre&gt;
&lt;p&gt;You can even take it farther than this, dynamically building up error classes by a naming convention.  If that sounds interesting to you and you don&amp;#8217;t mind the fuzziness of a &lt;tt&gt;const_missing&lt;/tt&gt; hook, you&amp;#8217;ll want to check out James Gray&amp;#8217;s blog post &lt;a href="http://blog.grayproductions.net/articles/summoning_error_classes_as_needed"&gt;&amp;#8220;Summoning Error Classes As Needed&amp;#8221;&lt;/a&gt;.  Though I tend to be a bit more conservative, there are definitely certain places where a hack like this can come in handy.&lt;/p&gt;
&lt;p&gt;The drawback of using any of these methods discussed here is that they don&amp;#8217;t really play well with RDoc.   However, there are easy ways to work around this, and James details some of them in his post.   In general, it&amp;#8217;s a small price to pay for greater clarity and less work in your code.&lt;/p&gt;
&lt;p&gt;Continuing on the theme of dynamically building up subclasses, we can move on to the next trick.&lt;/p&gt;
&lt;h3&gt;Safer Class Level Unit Testing&lt;/h3&gt;
&lt;p&gt;In my experience, it&amp;#8217;s a little bit tricky to test code that maintains state at the class level.  I&amp;#8217;ve tried everything from mocking out calls, to creating a bunch of explicit subclasses, and even have done something like &lt;tt&gt;klass = SomeClass.dup&lt;/tt&gt; in my unit tests.  While all of these solutions may do the trick depending on the context, there is a simple and elegant way that involves (you guessed it) &lt;tt&gt;Class.new&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;#8217;s a quick example from a patch I submitted to the &lt;em&gt;builder&lt;/em&gt; library that verifies a fix I made to the &lt;tt&gt;BlankSlate&lt;/tt&gt; class:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def test_reveal_should_not_bind_to_an_instance
    with_object_id = Class.new(BlankSlate) do
      reveal(:object_id)
    end

    obj1 = with_object_id.new
    obj2 = with_object_id.new

    assert obj1.object_id != obj2.object_id,
       "Revealed methods should not be bound to a particular instance"
  end
&lt;/pre&gt;
&lt;p&gt;Notice here that although we are doing class level logic, this test is still atomic and does not leave a mess behind in its wake.  We get to use the real &lt;tt&gt;reveal()&lt;/tt&gt; method, which means we don&amp;#8217;t need to think up the mocking interface.  Because we only store this anonymous subclass in a local variable, we know that our other tests won&amp;#8217;t be adversely affected by it, it&amp;#8217;ll just disappear when the code falls out of scope.  The code is clear and expressive, which is a key factor in tests.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re looking for more examples like this, you&amp;#8217;ll want to look over the rest of the &lt;tt&gt;BlankSlate&lt;/tt&gt; &lt;a href="http://github.com/jimweirich/builder/blob/c41c8914bec84f0009869e96ad6ebb39987896d3/test/test_blankslate.rb"&gt;test case&lt;/a&gt; .  I just followed Jim Weirich&amp;#8217;s lead here, so you&amp;#8217;ll see a few other examples that use a similar trick.&lt;/p&gt;
&lt;p&gt;For those interested, the thing that sparked my interest in writing this article today was a tiny bit of domain specific code I had cooked up for my day to day work, which needed to implement a nice interface for filtering search queries at the class level before they were executed.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class FreightOffer::Rail &amp;lt; FreightOffer
    hard_constraint do |query|
      query[:delivery] - query[:pickup] &amp;gt; 5.days
    end

    soft_constraint do |query|
      query[:asking_price] &amp;lt; 5000.to_money
    end
  end
&lt;/pre&gt;
&lt;p&gt;While it&amp;#8217;s easy to test these constraints once they&amp;#8217;re set up for a particular model, I wanted to be able to test drive the constraint interface itself at the abstract level. The best way I could come up with was to write tests that used &lt;tt&gt;Class.new&lt;/tt&gt; to generate subclasses of &lt;tt&gt;FreightOffer&lt;/tt&gt; to test against, which worked well.  While I won&amp;#8217;t post those tests here, it&amp;#8217;s a good exercise if you want to get the feel for this technique.&lt;/p&gt;
&lt;p&gt;The next trick is a little bit different than the first two, but can really come in handy when you want to inject a little syntactic diabetes into the mix.&lt;/p&gt;
&lt;h3&gt;Parameterized Subclassing&lt;/h3&gt;
&lt;p&gt;You might recognize the following example, since it is part of the &lt;a href="http://cachefly.oreilly.com/catalogs/Mastering_the_Dynamic_Toolkit.pdf"&gt;sample chapter&lt;/a&gt; of &lt;a href="http://rubybestpractices.com"&gt;Ruby Best Practices&lt;/a&gt; .  More than just a shameless plug though, I think this particular example shows off an interesting technique for dynamically building up subclasses in a low level system.&lt;/p&gt;
&lt;p&gt;Let&amp;#8217;s start with some vanilla code and see how we can clean it up, then we&amp;#8217;ll finally take a look under the hood.  What follows is a &lt;tt&gt;Fatty::Formatter&lt;/tt&gt;, which abstracts the task of producing output in a number of different formats.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class MyReport &amp;lt; Fatty::Formatter 
  
    module Helpers 
      def full_name 
        "#{params[:first_name]} #{params[:last_name]}" 
      end 
    end 
    
    class Txt &amp;lt; Fatty::Format 
      include MyReport::Helpers 
       def render 
        "Hello #{full_name} from plain text" 
       end 
    end 
    
    # use a custom Fatty::Format subclass for extra features 
    class PDF &amp;lt; Prawn::FattyFormat 
      include MyReport::Helpers 
      def render 
        doc.text "Hello #{full_name} from PDF" 
        doc.render 
      end 
    end 
    
    formats.update(:txt =&amp;gt; Txt, :pdf =&amp;gt; PDF) 
  end
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;MyReport&lt;/tt&gt; class in the previous code sample is little more than a glorified &amp;#8220;Hello World&amp;#8221; example that outputs text and &lt;span class="caps"&gt;PDF&lt;/span&gt;.   It is pretty easy to follow and doesn&amp;#8217;t really do anything fancy.  However, we can certainly clean it up and make it look better:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class MyReport &amp;lt; Fatty::Formatter 
    
    helpers do 
      def full_name 
        "#{params[:first_name]} #{params[:last_name]}" 
      end 
    end 
    
    format :txt do 
      def render 
        "Hello #{full_name} from plain text" 
      end 
    end 
    
    format :pdf, :base =&amp;gt; Prawn::FattyFormat do 
      def render 
        doc.text "Hello #{full_name} from PDF" 
        doc.render 
      end 
    end 
    
  end
&lt;/pre&gt;
&lt;p&gt;I think you&amp;#8217;ll agree that this second sample induces the kind of familiar sugar shock that Ruby coders know and love.  It accomplishes the same goals and actually wraps the lower level code rather than replacing it.  But is there some sort of dark magic behind this?  Let&amp;#8217;s peek behind the curtain:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def format(name, options={}, &amp;amp;block) 
    formats[name] = Class.new(options[:base] || Fatty::Format, &amp;amp;block) 
  end
&lt;/pre&gt;
&lt;p&gt;As you can see, it is nothing more than a hash of &lt;tt&gt;formats&lt;/tt&gt; maintained at the class level, combined with a call to &lt;tt&gt;Class.new&lt;/tt&gt; to generate the subclass.  No smoke and mirrors, just the same old Ruby tricks we&amp;#8217;ve been using throughout this article.  The curious may wonder how &lt;tt&gt;helpers()&lt;/tt&gt; works here, and though it&amp;#8217;s slightly tangential, you&amp;#8217;ll see it is similarly simple.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def helpers(helper_module=nil, &amp;amp;block) 
    @helpers = helper_module || Module.new(&amp;amp;block) 
  end 
&lt;/pre&gt;
&lt;p&gt;Though I won&amp;#8217;t get into it here, fun tricks can be done with anonymous modules as well.  Can you think of any that are particularly interesting?  If so, let me know in the comments.&lt;/p&gt;
&lt;p&gt;Although I only showed a part of the picture, you might want to check out the rest of &lt;a href="http://github.com/sandal/fatty/blob/392d65ee9b4be167cfe568f0669b64694ef2bbff/lib/fatty.rb"&gt;Fatty&amp;#8217;s source&lt;/a&gt;.  I call it a &amp;#8216;67 line replacement for &lt;a href="http://rubyreports.org"&gt;Ruport&lt;/a&gt;&amp;#8217;, which is a major exaggeration, but it is really surprising how much you can get out of a few dynamic Ruby tricks when you combine them together properly.  A lot of these ideas were actually inspired by the &lt;a href="http://www.sinatrarb.com/"&gt;Sinatra&lt;/a&gt; web framework, so that&amp;#8217;s another project to add to your code reading list if you&amp;#8217;re looking to learn new tricks.&lt;/p&gt;
&lt;p&gt;Anyway, I&amp;#8217;m getting off topic now, and it&amp;#8217;s about time to wrap up anyway.  I&amp;#8217;ll go on one more tiny tangent, and then send you on your way.&lt;/p&gt;
&lt;h3&gt;Shortcutting with Struct&lt;/h3&gt;
&lt;p&gt;With all this talk about using anonymous sub-classes, I can&amp;#8217;t help but recap one of the &lt;a href="http://blog.grayproductions.net/articles/all_about_struct"&gt;oldest tricks in the book&lt;/a&gt;.  The method &lt;tt&gt;Struct.new&lt;/tt&gt; can be handy for shortcutting class creation.  Using it, the very first example in this post could be simplified down to:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Point &amp;lt; Struct.new(:x, :y)
  def distance(point)
    Math.hypot(point.x - x, point.y - y)
  end
end
&lt;/pre&gt;
&lt;p&gt;The constructor and accessors are provided for free by &lt;tt&gt;Struct&lt;/tt&gt; here.  Of course, the real reason I mentioned this was to get you thinking.  If &lt;tt&gt;Struct.new&lt;/tt&gt; can work this way, and we know that &lt;tt&gt;Class.new&lt;/tt&gt; can accept a block definition that provides a closure, what other cool uses of parameterized subclasses can we cook up?&lt;/p&gt;
&lt;h3&gt;Please Share Your Thoughts&lt;/h3&gt;
&lt;p&gt;I wrote this article in hopes that it&amp;#8217;ll be a jumping off point for discussion on more cool tricks I haven&amp;#8217;t seen before, or failing that, ones that other readers haven&amp;#8217;t seen before.  While there certainly is a lot of nasty, scary looking &amp;#8220;meta-programming&amp;#8221; out there that makes people feel like this stuff is hard and esoteric, there are many techniques that lead to simple, elegant, and beautiful dynamic code.  Please let me know what you think of these techniques, and definitely share one of your own if you&amp;#8217;d like.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 30 Apr 2009 17:55:00 +0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/anonymous_class_hacks.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/anonymous_class_hacks.html</guid></item><item><title>Writing Block Methods with automatic Resource Cleanup</title><description>&lt;p&gt;After we have seen how &lt;tt&gt;File.open&lt;/tt&gt; with a block is safer than without we will look into how such methods are created today.&lt;/p&gt;
&lt;h3&gt;Ingredients&lt;/h3&gt;
&lt;p&gt;We need two ingredients:&lt;/p&gt;
&lt;ol&gt;
	&lt;li&gt;&lt;tt&gt;yield&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;A &lt;tt&gt;begin &amp;#8230; end&lt;/tt&gt; block with &lt;tt&gt;ensure&lt;/tt&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;tt&gt;yield&lt;/tt&gt; is a keyword and invokes the block which is passed to a method. If the caller did not provide a block he&amp;#8217;ll earn a &lt;tt&gt;LocalJumpError&lt;/tt&gt;. Result of evaluating &lt;tt&gt;yield&lt;/tt&gt; is the value of the block (remember, we also called them &amp;#8220;anonymous functions&amp;#8221;).&lt;/p&gt;
&lt;p&gt;As you will probably know &lt;tt&gt;begin &amp;#8230; end&lt;/tt&gt; blocks can be used to catch exceptions and handle them properly. But this construct has two more features apart from &lt;tt&gt;rescue&lt;/tt&gt;; a full blown block might look like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
begin
  # do our work
rescue SomeException =&amp;gt; e
  # oops!
rescue Exception =&amp;gt; e
  # deal with other errors
else
  # good, no exception surfaced!
ensure
  # good or bad, this needs to be done
end
&lt;/pre&gt;
&lt;p&gt;Code in an &lt;tt&gt;else&lt;/tt&gt; clause after &lt;tt&gt;rescue&lt;/tt&gt; is executed when the block is left normally, i.e. without an exception being thrown. Note that in case of an exception it is irrelevant whether it is caught in this &lt;tt&gt;begin &amp;#8230; end&lt;/tt&gt; block or not &amp;#8212; &lt;tt&gt;else&lt;/tt&gt; will not be executed. Code after &lt;tt&gt;ensure&lt;/tt&gt; is executed under all circumstances &amp;#8212; regardless whether an exception is thrown or not. This is the feature that we&amp;#8217;ll exploit for our cleanup.&lt;/p&gt;
&lt;p&gt;An important thing to know is that the result of the &amp;#8220;ensure&amp;#8221; code does not affect the block&amp;#8217;s result which is normally the value of the last expression evaluated between &lt;tt&gt;begin&lt;/tt&gt; and the first &lt;tt&gt;rescue&lt;/tt&gt;. So anything the cleanup code returns is invisible to the caller (which makes perfect sense if you think about it). Results of &lt;tt&gt;rescue&lt;/tt&gt; and &lt;tt&gt;else&lt;/tt&gt; clauses &lt;em&gt;are&lt;/em&gt; retained when they are executed.&lt;/p&gt;
&lt;h3&gt;Cooking&lt;/h3&gt;
&lt;p&gt;Assume we have a class that distributes stdin to a set of files much the same as the &lt;a href="http://en.wikipedia.org/wiki/Tee_(command)"&gt;&amp;#8216;tee&amp;#8217; command line utility&lt;/a&gt; does. This class features a method &lt;tt&gt;open&lt;/tt&gt; which opens files and another method &lt;tt&gt;close&lt;/tt&gt; which closes all file descriptors. Then we can create a class method similar to &lt;tt&gt;File.open()&lt;/tt&gt; which does the automatic cleanup via an &lt;tt&gt;ensure&lt;/tt&gt; section:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
class Tee
  def self.open(file_names, mode = "w")
    tee = new(file_names, mode)
    tee.open

    if block_given?
      begin
        yield tee
      ensure
        tee.close
      end
    else
      tee
    end
  end
end
&lt;/pre&gt;
&lt;p&gt;This code does actually work similar to &lt;tt&gt;File.open&lt;/tt&gt; because it acts differently depending on the presence of a block:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;If there is no block, then the &amp;#8220;tee&amp;#8221; is created and opened. It is the return value of the method.&lt;/li&gt;
	&lt;li&gt;If there is a block, then that is called with the opened &amp;#8220;tee&amp;#8221; instance and after termination this is closed.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;#8217;s really all there is to it. A final remark: in order to ensure that this pattern works properly you need to make sure the initialization is done &lt;em&gt;before&lt;/em&gt; the &lt;tt&gt;begin&lt;/tt&gt;. Otherwise any exceptions thrown during initialization will trigger the cleanup code which then will act on an incomplete or completely different object altogether (chances are that you will get &lt;tt&gt;NoMethodError&lt;/tt&gt; from &lt;tt&gt;nil&lt;/tt&gt; in this case).&lt;/p&gt;
&lt;p&gt;You can also look at the &lt;a href="http://gist.github.com/98693"&gt;full code&lt;/a&gt; if you want to see the complete story.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Mon, 20 Apr 2009 19:47:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/002_Writing_Block_Methods.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/002_Writing_Block_Methods.html</guid></item><item><title>Rails Modularity for Lazy Bastards</title><description>&lt;p&gt;When we develop standalone systems or work on libraries and frameworks, modularity seems to come naturally.  When something seems to gain a life of its own, we pull it off into its own package or subsystem to keep things clean.  This is a natural extension of the sorts of design decisions we make at the object level in our software, and helps us work on complicated problems, often working alongside other hackers, without losing our wits.&lt;/p&gt;
&lt;p&gt;It seems a bit surprising that these helpful guiding principals can often evaporate when we bring our software to the web.  Sure, we may make use of plugins and gems for foundational support, but if you take a good look at a Rails application that has more than 50 models or so, you&amp;#8217;ll be hard pressed to find a unified purpose behind all that logic.&lt;/p&gt;
&lt;p&gt;However, if you try to break things down into core sets of functionality, you may find that certain vertical slices can be made that allow you to break out bits of functionality into their own separate focus areas. For example, you may discover that part of your application is actually a mini &lt;span class="caps"&gt;CRM&lt;/span&gt; system.  Or maybe you&amp;#8217;ve snuck in a small reporting system without noticing it consciously.   The list goes on, but the underlying idea here is that the larger a system gets, the harder it is to define its core purpose.&lt;/p&gt;
&lt;p&gt;While splitting out these subsystems may seem like the obvious choice in a standalone application, there seems to be a certain amount of &lt;span class="caps"&gt;FUD&lt;/span&gt; about this strategy when it comes to the web.  This probably originates from a time before &lt;span class="caps"&gt;REST&lt;/span&gt;, in which interaction between web applications was overly complex,making the costs of fragmentation higher than the benefits of a modular architecture.  These days, we live in better times and work with better frameworks, and should reap the benefits that come along with it.&lt;/p&gt;
&lt;p&gt;But actions speak louder than words, so let&amp;#8217;s take a look at some of the underlying tech and how to use it.  Building on the &lt;span class="caps"&gt;CRM&lt;/span&gt; scenario, I&amp;#8217;ll start by showing how to access a Customer model from another application using ActiveResource.&lt;/p&gt;
&lt;h3&gt;Sharing Model Data via ActiveResource&lt;/h3&gt;
&lt;p&gt;Suppose that we&amp;#8217;ve got a &lt;span class="caps"&gt;CRM&lt;/span&gt; system that has a Customer model that has a schema that looks something like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  create_table :customers do |t|
    t.string :first_name
    t.string :last_name
    t.string :email
    t.string :daytime_phone
    t.string :evening_phone
    t.timestamps
  end
&lt;/pre&gt;
&lt;p&gt;With this, we can do all the ordinary &lt;span class="caps"&gt;CRUD&lt;/span&gt; operations within our application, so I won&amp;#8217;t bore you with the details.  What we&amp;#8217;re interested in is how to accomplish these same goals from an external application.  So within our &lt;span class="caps"&gt;CRM&lt;/span&gt; system, this essentially boils down to simply providing a RESTful interface to our Customer resource.  After adding &lt;tt&gt;map.resources :customers&lt;/tt&gt; to our &lt;em&gt;config/routes.rb&lt;/em&gt; file, we code up a &lt;tt&gt;CustomersController&lt;/tt&gt; that looks something like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class CustomersController &amp;lt; ApplicationController
  
    def index
      @customers = Customer.find(:all)
      respond_to do |format|
        format.xml { render :xml =&amp;gt; @customers }
        format.html
      end
    end
 
    def show
      customer = Customer.find(params[:id])
      respond_to do |format|
        format.xml { render :xml =&amp;gt; customer.to_xml }
        format.html
      end
    end
 
    def create
      customer = Customer.create(params[:customer])
      respond_to do |format|
        format.html { redirect_to entry }
        format.xml { render :xml =&amp;gt; customer, :status   =&amp;gt; :created, 
                                              :location =&amp;gt; customer }
      end
    end
 
    def update
      customer = Customer.update(params[:id], params[:customer])
      respond_to do |format|
        format.xml { render :xml =&amp;gt; customer.to_xml }
        format.html
      end
    end
 
    def destroy
      Customer.destroy(params[:id])
      respond_to do |format|
        format.xml { render :xml =&amp;gt; "", :status =&amp;gt; 200 }
        format.html
      end
    end
 
  end
&lt;/pre&gt;
&lt;p&gt;This may look familiar even if you haven&amp;#8217;t worked with ActiveResource previously, as it&amp;#8217;s basically the same boiler plate you&amp;#8217;ll find in a lot of Rails documentation.  In the &lt;tt&gt;respond_to&lt;/tt&gt; block, &lt;tt&gt;format.xml&lt;/tt&gt; is what matters here, as it is what connects our resource to the services which consume it.  The good news is we won&amp;#8217;t have to actually work with the &lt;span class="caps"&gt;XML&lt;/span&gt; data, as you&amp;#8217;ll see in a moment.&lt;/p&gt;
&lt;p&gt;While there are a few things left to do to make this code usable in a real application, we can already test basic interactions with a secondary application.  Using any other rails app we&amp;#8217;d like, we can add an &lt;tt&gt;ActiveResource&lt;/tt&gt; model by creating a file called &lt;em&gt;app/models/customer.rb&lt;/em&gt; and setting it up like this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Customer &amp;lt; ActiveResource::Base
    self.site = "http://localhost:3000/"
  end
&lt;/pre&gt;
&lt;p&gt;Now here comes the interesting part.  If you fire up &lt;tt&gt;script/console&lt;/tt&gt; on the client side application that is interfacing with the &lt;span class="caps"&gt;CRM&lt;/span&gt; system, you can see the same familiar &lt;span class="caps"&gt;CRUD&lt;/span&gt; operations, but taking place from a completely separate application:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  &amp;gt;&amp;gt; Customer.create(:first_name =&amp;gt; "Gregory", :last_name =&amp;gt; "Brown")
  =&amp;gt; #&amp;lt;Customer:0x20d2120 @prefix_options={}, @attributes={"evening_phone"=&amp;gt;nil, "updated_at"=&amp;gt;Thu Apr 16 03:53:59 UTC 2009, "daytime_phone"=&amp;gt;nil, "id"=&amp;gt;1, "first_name"=&amp;gt;"Gregory", "last_name"=&amp;gt;"Brown", "created_at"=&amp;gt;Thu Apr 16 03:53:59 UTC 2009, "email"=&amp;gt;nil}&amp;gt;
 
  &amp;gt;&amp;gt; Customer.find(:all)
  =&amp;gt; [#&amp;lt;Customer:0x20a939c @prefix_options={}, @attributes={"evening_phone"=&amp;gt;nil, "updated_at"=&amp;gt;Thu Apr 16 03:53:59 UTC 2009, "daytime_phone"=&amp;gt;nil, "id"=&amp;gt;1, "first_name"=&amp;gt;"Gregory", "last_name"=&amp;gt;"Brown", "created_at"=&amp;gt;Thu Apr 16 03:53:59 UTC 2009, "email"=&amp;gt;nil}&amp;gt;]
 
  &amp;gt;&amp;gt; Customer.find(1).first_name
  =&amp;gt; "Gregory"
 
  &amp;gt;&amp;gt; Customer.delete(1)
  =&amp;gt; #&amp;lt;Net::HTTPOK 200 OK readbody=true&amp;gt;
 
  &amp;gt;&amp;gt; Customer.find(:all)
  =&amp;gt; []
&lt;/pre&gt;
&lt;p&gt;While the interface and behavior isn&amp;#8217;t downright identical to &lt;tt&gt;ActiveRecord&lt;/tt&gt;, it bears a striking resemblance and allows you to retain much of the functionality that is needed for basic data manipulation.&lt;/p&gt;
&lt;p&gt;Now that we can see the basic functionality in action, let&amp;#8217;s go back and fix a few key issues.  We definitely want to add some sort of authentication to this system, as it is currently allowing any third party application to modify and destroy records.  We also will most likely want a more flexible option for locating services than just hard coding a server address in each model file.  Once these two things are in place, we&amp;#8217;ll have the beginnings of a decentralized Rails based application.&lt;/p&gt;
&lt;h3&gt;&lt;span class="caps"&gt;API&lt;/span&gt; Keys with &lt;span class="caps"&gt;HTTP&lt;/span&gt; Basic Authentication&lt;/h3&gt;
&lt;p&gt;I want to preface this section by saying I&amp;#8217;m typically not the one responsible for any sort of security hardening in the applications I work on.   That means that I&amp;#8217;m by no means an expert in how to make your applications safe from the malignant forces of the interweb.   That having been said, what follows is a simple technique that seems to work for me when it comes to slapping a simple authentication model in place.&lt;/p&gt;
&lt;p&gt;First, in the app that is providing the service, in this case, our fictional &lt;span class="caps"&gt;CRM&lt;/span&gt; system, you&amp;#8217;ll want something like this in your &lt;tt&gt;ApplicationController&lt;/tt&gt;:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  def basic_http_auth
    authenticated = false
    authenticate_with_http_basic do |login, password|
      if login == "api" &amp;amp;&amp;amp; password == API_KEY
        authenticated = true
      end
    end
 
    raise "Authentication failed" unless authenticated
  end
&lt;/pre&gt;
&lt;p&gt;Here, &lt;tt&gt;API_KEY&lt;/tt&gt; is some shared secret that is known by both your service providing application, and any client that wishes to use your service.  In this blog post, I&amp;#8217;ll be using the string &lt;tt&gt;&amp;#8220;kittens&amp;#8221;&lt;/tt&gt;, but you&amp;#8217;ll obviously want to pick something longer, and with significantly more entropy.&lt;/p&gt;
&lt;p&gt;After dropping a &lt;tt&gt;before_filter&lt;/tt&gt; in your &lt;tt&gt;CustomersController&lt;/tt&gt; that points to &lt;tt&gt;basic_http_auth&lt;/tt&gt;, you&amp;#8217;ll need to update your ActiveResource model definition.&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Customer &amp;lt; ActiveResource::Base
    self.site = "http://localhost:3000/"
    self.user = "api"
    self.password = "kittens"
  end
&lt;/pre&gt;
&lt;p&gt;If you forget to do this, you won&amp;#8217;t be able to retrieve or modify any of the customer data.  This means that any application that does not know the shared secret may not use the resource.  Although this is hardly a fancy solution, it gets the job done.   Now, let&amp;#8217;s take a look at how to make integration even easier and get rid of some of these hard coded values at the per-model level.&lt;/p&gt;
&lt;h3&gt;Simplifying Integration&lt;/h3&gt;
&lt;p&gt;So far, the work has been pretty simple, but it&amp;#8217;s important to keep in mind that if we really want to break up our applications into small, manageable subsystems, we might need to deal with a lot of remote resources.&lt;/p&gt;
&lt;p&gt;Pulled directly from some commercial work I&amp;#8217;ve been doing with Brad Ediger of Madriska Media Group (and of &lt;a href="http://oreilly.com/catalog/9780596510329/"&gt;Advanced Rails&lt;/a&gt; fame), what follows is a helper file that provides two useful features for working with remote resources via ActiveResource:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  require 'yaml'
  require 'activeresource'
 
  class ServiceLocator
 
    API_KEY = "kittens"
 
    def self.services
      return @services if @services
      config_file = File.join(RAILS_ROOT, %w[config services.yml])
      config = YAML.load_file(config_file)
      @services = config[RAILS_ENV]
    end
 
    def self.[](name)
      services[name.to_s]
    end
  end
 
  def Service(name)
    Class.new(ActiveResource::Base) do
      self.site = "http://#{ServiceLocator[name]}"
      self.user = "api"
      self.password = ServiceLocator::API_KEY
    end
  end
&lt;/pre&gt;
&lt;p&gt;The &lt;tt&gt;ServiceLocator&lt;/tt&gt; part was Brad&amp;#8217;s idea, and it represents a simple way to map the URLs of different services to a label based on what environment you are currently running in.  A basic &lt;em&gt;config/services.yml&lt;/em&gt; file might look something like this:&lt;/p&gt;
&lt;pre name="code"&gt;
  development:
    crm: localhost:3000
    reports: localhost:3001

  production:
    crm: crm.example.com
    reports: reports.example.com
&lt;/pre&gt;
&lt;p&gt;This is nice, because it allows us to configure the locations of our various services all in one place.  The interface is very simple and straightforward:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  &amp;gt;&amp;gt; ServiceLocator[:crm]
  =&amp;gt; "localhost:3000"
&lt;/pre&gt;
&lt;p&gt;However, upon seeing this feature, I decided to take it a step farther.  Though it might sacrifice a bit of purity, the &lt;tt&gt;Service()&lt;/tt&gt; method is actually a parameterized class constructor that builds up a subclass filling out the &lt;span class="caps"&gt;API&lt;/span&gt; key and service address for you. What that means is that you can replace your initial &lt;tt&gt;Customer&lt;/tt&gt; definition with this:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  class Customer &amp;lt; Service(:crm)
    # my custom methods here.
  end
&lt;/pre&gt;
&lt;p&gt;Since Rails handles the mapping of resource names to class names for you, you can easily support as many remote classes from a single service as you&amp;#8217;d like this way.   When I read this aloud in my head, I tend to think of &lt;tt&gt;SomeClass &amp;lt; Service(:some_service)&lt;/tt&gt; as &amp;#8220;SomeClass is a resource provided by some_service&amp;#8221;.   Feel free to forego the magic here if this concerns you, but I personally find it pleasing to the eyes.&lt;/p&gt;
&lt;h3&gt;Just Starting a Conversation&lt;/h3&gt;
&lt;p&gt;I didn&amp;#8217;t go into great detail about how to use the various technologies I&amp;#8217;ve touched on here, but I&amp;#8217;ve hopefully provided a glimpse into what is possible to those who are uninitiated, as well as provided some food for thought to those who already have some experience in building decentralized Rails apps.&lt;/p&gt;
&lt;p&gt;To provide some extra insight into the approach I&amp;#8217;ve been using on my latest project, we basically keep everything in one big git repository, with separate folders for each application.  At the root, there is a &lt;em&gt;shared/&lt;/em&gt; folder in which we keep some shared library files, including some support infrastructure for things like a simple &lt;span class="caps"&gt;SSO&lt;/span&gt; mechanism and a database backed cross-application logging system.   We also vendor one copy of Rails there and simply symlink &lt;em&gt;vendor/rails&lt;/em&gt; in our individual apps, except for when we need a specific version for a particular service.&lt;/p&gt;
&lt;p&gt;The overarching idea is that there is a foundational support library that our individual apps sit on top of, and that they communicate with each other only through the service interfaces we expose.  We&amp;#8217;ve obviously got more complicated needs, and thus finer grained controls than what I&amp;#8217;ve covered in this article, but the basic ActiveResource functionality seems to be serving us well.&lt;/p&gt;
&lt;p&gt;What I&amp;#8217;d like to know is what other folks have been doing to help manage the complexity of their larger Rails apps.  Do you think the rough sketch of ideas I&amp;#8217;ve laid out here sounds promising?  Do you foresee potential pitfalls that I haven&amp;#8217;t considered?  Leave a comment and let me know.&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Thu, 16 Apr 2009 04:31:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/rails_modularity_1.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/rails_modularity_1.html</guid></item><item><title>Solve the problem, not just a problem</title><description>&lt;p&gt;So you decide you want a way for a number of people to post short articles to a Web site, and maybe allow for other people to leave comments. What do you do?  That&amp;#8217;s easy: jump to the white board and start sketching out a vast array of boxes, blobs, and arrows that define a sophisticated content management system with multi-level admin roles, content versioning, threaded discussion boards, syntax highlighting, the works.&lt;/p&gt;
&lt;p&gt;Right?&lt;/p&gt;
&lt;p&gt;Don&amp;#8217;t be too quick to judge.  It&amp;#8217;s easy to fall into the trap of defining the wrong requirements for a project.&lt;/p&gt;
&lt;p&gt;Part of the reason is that building software is (or should be) fun, and often bigger projects are more fun. There is also the tendency to think about &amp;#8220;what if&amp;#8221;, imagining all the things that maybe one day who knows you never can tell might be needed.&lt;/p&gt;
&lt;p&gt;People also tend to think in terms of what&amp;#8217;s familiar, of how things have been done in the past or by others.&lt;/p&gt;
&lt;p&gt;There are many ways to satisfy the needs described in the first paragraph.  Some don&amp;#8217;t require writing any software at all.&lt;/p&gt;
&lt;p&gt;For the Ruby Best Practices blog, the general goals were modest.  Allow a core set of people to easily add new content.  Allow other people to contribute content as well, but only with the OK from someone in that core group. (&lt;span class="caps"&gt;BTW&lt;/span&gt;, there are eight of us in the &lt;span class="caps"&gt;RBP&lt;/span&gt; blog team.  See &lt;a href="http://img509.imageshack.us/img509/2944/rbpdharmainitiative.jpg"&gt;here&lt;/a&gt; for my take on the &lt;span class="caps"&gt;RBP&lt;/span&gt; team logo)&lt;/p&gt;
&lt;p&gt;We wanted to allow the use of Textile, and not make people use a browser for editing.  Basically, turn simple flat files into a Web site with minimal fuss.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://github.com/sandal/korma/tree/master"&gt;Korma&lt;/a&gt; takes an interesting approach to building Web sites.  The whole app is ~230 lines of Ruby. Its key function is to take content from a Git repository, run it through some templating, and write out the site files.&lt;/p&gt;
&lt;p&gt;Relying on Git for that back end is stunningly perfect. Git provides versioning, access control, and distributed contributions.&lt;/p&gt;
&lt;p&gt;It becomes the database layer common to most blogging tools. For free.  Right off the bat, no need to write any admin tools or content versioning code  .&lt;/p&gt;
&lt;p&gt;At the heart of Korma is the &lt;a href="http://github.com/mojombo/grit/tree/master"&gt;grit&lt;/a&gt; gem. As the project blurb says, &amp;#8220;Grit gives you object oriented read/write access to Git repositories via Ruby.&amp;#8221;  Very sweet.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;korma.rb&lt;/code&gt; file takes two arguments.  The first is required, and is the path to a git repository.  The second argument is optional; it tells Korma what directory to use for the generated content, and defaults to &amp;#8216;www&amp;#8217;, relative to where you invoke the program.&lt;/p&gt;
&lt;p&gt;The app uses grit to reach into the current contents of the repo and parse the needed files. Files have to be committed to be accessible to Korma.&lt;/p&gt;
&lt;p&gt;There is a configuration file that describes some basic site metadata, such as the base &lt;span class="caps"&gt;URL&lt;/span&gt;, the site title, and the author list.  When called, &lt;code&gt;korma.rb&lt;/code&gt; grabs this config file, sets some &lt;code&gt;Korma::Blog&lt;/code&gt; properties, and then writes out the static files.&lt;/p&gt;
&lt;p&gt;An early version of Korma used &lt;a href="http://www.sinatrarb.com/"&gt;Sinatra&lt;/a&gt;; basically, Korma was a lightweight Web app to serve the blog posts. But as simple as it was, it was overkill, since there was no real dynamic content.  It made no sense to have the Web app regenerate the &lt;span class="caps"&gt;HTML&lt;/span&gt; on each request, since it changed so infrequently.&lt;/p&gt;
&lt;p&gt;A next version replaced the Web app part with static files, making it a straightforward command-line program.   This solved another problem: how to automate the regeneration of files. The answer: use Git&amp;#8217;s post-commit hook to invoke the program.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;pre&gt;
   #!/bin/sh
   # File .git/hooks/post-commit   
   /usr/local/bin/ruby /home/james/data/vendor/korma/korma.rb /home/james/data/vendor/rbp-blog /home/james/data/vendor/korma/www
&lt;/pre&gt;
&lt;p&gt;Early versions also used Haml for site-wide templates.  Not being a fan of Haml, I added in a configurable option to use Erb.  It was nice and all, but it was a feature without a requirement. No one was asking for configurable templating, so that option was dropped and Erb replaced Haml as the default.&lt;/p&gt;
&lt;p&gt;If you are wondering why working code was removed, consider that any code you have is something you have to maintain. As bug-free and robust as you may like to think it, no code is easier to maintain than &lt;em&gt;no&lt;/em&gt; code.  Configurable templating was simply not a problem we were needed to solve, and a smaller, simpler code base is more valuable than a maybe &amp;#8220;nice to have.&amp;#8221;&lt;/p&gt;
&lt;p&gt;There was some discussion about the need or value of allowing comments.  In the end they were deemed good, but there was no good argument for hosting them as part of the blog site itself.  That meant a 3rd-party solution (in this case, &lt;a href="http://disqus.com/"&gt;Disqus&lt;/a&gt;) was perfectly acceptable. Again, a goal was to have comments, not to write a commenting system (as entertaining as that may be).&lt;/p&gt;
&lt;p&gt;Using Git allows for yet another feature for free: easy one-off  contributions.  In many systems, allowing anyone to contribute means creating an account, granting some sort of access, managing all the new user annoyances. Or, an existing user has to play proxy, accepting content and entering it into the system on behalf of the real author.  That&amp;#8217;s work!  With git, one can clone the repo, add new content, and issue a pull request back to the master branch.  Anyone with commit rights to the master can then merge it in (or politely decline).   No-code features &lt;span class="caps"&gt;FTW&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;None of the blog design requirements are written in stone, and they may change tomorrow, but by identifying the real needs, addressing what was deemed essential, offloading what we could, and skipping the feature bling, we have a system that is easy to understand, easy to maintain, and easy to change.&lt;/p&gt;</description><author>james.britt@gmail.com (James Britt)</author><pubDate>Mon, 13 Apr 2009 20:11:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/jamesbritt/2009-04-13-solving-the-problem.rc.html</link><guid>http://blog.rubybestpractices.com/posts/jamesbritt/2009-04-13-solving-the-problem.rc.html</guid></item><item><title>Using Blocks for Robustness</title><description>&lt;p&gt;Ruby&amp;#8217;s blocks can be used for many purposes &amp;#8212; in fact, they might well be the most used feature of the language. Today we will start looking at a frequently-used idiom, analyze its implications for robustness and demonstrate how blocks can greatly improve it.&lt;/p&gt;
&lt;h3&gt;Robustness&lt;/h3&gt;
&lt;p&gt;When talking about robustness of software&lt;sup class="footnote"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; we mean the degree to which it is able to function properly under changed circumstances.  Those changes could be internal (i.e. introduced by a code change) or external (e.g. by changed input data).  Sometimes achieving robustness is a hard task especially for complex software like operating systems.  In this article we&amp;#8217;ll look at robustness at a smaller scale.&lt;/p&gt;
&lt;h3&gt;A common file handling idiom&lt;/h3&gt;
&lt;p&gt;When you read through ruby-talk you will find code that looks like &lt;a href="http://groups.google.com/group/comp.lang.ruby/msg/168977b073d02ad7"&gt;this&lt;/a&gt; (I just did some minimal adjustments to formatting and corrected obvious errors):&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # read file into an array
  f = File.open("mylogfile.log")
  saved = File.open("archive.log", "a")
  results = f.readlines
  # Is there a way to remove everything that's been read here?
  f.close

  results.each_line do |sending|
    conn_to_db.print("data #{sending}")
    # Make sure we keep a backup
    saved.puts("#{sending}")
  end

  # Close the archive file
  saved.close
&lt;/pre&gt;
&lt;p&gt;The logic is straightforward: a file is opened, all its lines are read and then it is closed again. Similarly, the second file is opened for appending, then written to and finally closed. Sure, the second file could be opened later, but this is not where I want to draw your attention to.&lt;/p&gt;
&lt;p&gt;Rather, please notice that &lt;tt&gt;File.open&lt;/tt&gt; is used together with an explicit &lt;tt&gt;close&lt;/tt&gt;. Closing the file IO object ensures that all pending output is written to the file and operating system resources associated with the underlying file handle are freed. While not closing a read only file &lt;em&gt;usually&lt;/em&gt; does not have dramatic consequences, not closing a file opened for writing likely &lt;em&gt;has&lt;/em&gt; dramatic consequences. You can see it by running this bit of code through Ruby 1.8.*:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  NAME = "foo"

  f1 = File.open NAME, "w"
  f1.puts "text 1"
  # forgot to close f1
  f2 = File.open NAME, "a"
  f2.puts "text 2"
  # forgot to close f2
&lt;/pre&gt;
&lt;p&gt;On my system (CentOS 5.3, Ruby 1.8.5) I see only the first line in the file but the second &lt;tt&gt;puts&lt;/tt&gt; has no effect.  Even if you add a &lt;tt&gt;f2.close&lt;/tt&gt; at the end of the script you won&amp;#8217;t see any difference.  You need to add the &lt;tt&gt;f1.close&lt;/tt&gt; before you open &lt;tt&gt;f2&lt;/tt&gt; to actually see two lines in the output file.&lt;/p&gt;
&lt;h3&gt;File.close is the solution, or is it?&lt;/h3&gt;
&lt;p&gt;We just remember to always add a &lt;tt&gt;f.close&lt;/tt&gt; whenever we have opened a file and be done. Everything written to the IO object will reach the file and we do not need to worry about anything any more.  Or do we?  Unfortunately, this is not the case.  Especially in situations like the one shown above where exceptions can happen (we do not know what &lt;tt&gt;conn_to_db.print&lt;/tt&gt; does, but it looks like another IO operation which could fail) we need to take additional measures to &lt;em&gt;ensure&lt;/em&gt; the file is really closed.&lt;/p&gt;
&lt;p&gt;We can use &lt;tt&gt;begin &amp;#8230; rescue &amp;#8230; end&lt;/tt&gt; to do proper exception handling and make sure file descriptors are closed properly.  But this tends to get verbose.  Fortunately there is another option: &lt;tt&gt;File.open&lt;/tt&gt; accepts a block and ensures that the file descriptor is closed regardless how the block is left.&lt;/p&gt;
&lt;h3&gt;Large files&lt;/h3&gt;
&lt;p&gt;When dealing with files as shown in the code example above there is another potential source of trouble: if files can grow arbitrarily large they will burn a lot of memory when read as a whole or even terminate the program because there is not enough memory available.&lt;/p&gt;
&lt;p&gt;For reading files there is an even better alternative: &lt;tt&gt;File.foreach&lt;/tt&gt; will read a file line by line (or using a different separator given as second argument) and hand each string to the block that is provided.  This saves an additional &lt;tt&gt;io.each {|line| &amp;#8230;}&lt;/tt&gt; inside &lt;tt&gt;the File.open&lt;/tt&gt; block &amp;#8212; less typing and one level of indentation less.  Also, as an added benefit we can efficiently process large files because we do not have to hold the complete file in memory when using iterative solutions.&lt;/p&gt;
&lt;h3&gt;Example rewritten&lt;/h3&gt;
&lt;p&gt;With these tools equipped we are now ready to rewrite the original bit to a more robust version:&lt;/p&gt;
&lt;pre name="code" class="ruby"&gt;
  # read file and write to archive
  File.open("archive.log", "a") do |saved|
    File.foreach("mylogfile.log") do |sending|
      conn_to_db.print("data #{sending}")
      # Make sure we keep a backup
      saved.puts(sending) # removed superfluous string interpolation
    end
  end
&lt;/pre&gt;
&lt;p&gt;Note, that if the timing of the original script is critical we might want to use &lt;tt&gt;File.readlines&lt;/tt&gt; in order to read in all lines of &amp;#8220;mylogfile.log&amp;#8221; before starting to write to the &amp;#8220;archive.log&amp;#8221; as the original code does.&lt;/p&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;Using Ruby&amp;#8217;s blocks goes a long way to making programs and scripts that deal with file IO more robust with regard to&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;exceptions occurring somewhere along the way,&lt;/li&gt;
	&lt;li&gt;large files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, whenever you do file IO in a Ruby program, remember you can use&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;the block form of &lt;tt&gt;File.open&lt;/tt&gt; or&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;File.foreach&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;to make your code more robust without paying a significant price.&lt;/p&gt;
&lt;p&gt;You can even resort to &lt;tt&gt;File.readlines&lt;/tt&gt; if you have to read the whole file into memory and at least save a bit of typing.  If you make it a habit to always use these idioms chances are that you&amp;#8217;ll save a lot file IO related bug hunting in the future.&lt;/p&gt;
&lt;p&gt;Next time I will look into how to create a method like &lt;tt&gt;File.open&lt;/tt&gt; which uses a block to ensure automatic resource deallocation.&lt;/p&gt;
&lt;p class="footnote" id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Here is a &lt;a href="http://www.linfo.org/robust.html"&gt;definition of robust&lt;/a&gt; and a &lt;a href="http://en.wikipedia.org/wiki/Robustness_Principle"&gt;Wikipedia Article about Robustness Principle&lt;/a&gt;.&lt;/p&gt;</description><author>shortcutter@googlemail.com (Robert Klemme)</author><pubDate>Thu, 09 Apr 2009 14:25:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/rklemme/001-Using_blocks_for_Robustness.html</link><guid>http://blog.rubybestpractices.com/posts/rklemme/001-Using_blocks_for_Robustness.html</guid></item><item><title>Welcome to the RBP blog</title><description>&lt;p&gt;Hello, and welcome to the Ruby Best Practices blog.  I am happy to announce this new collaborative writing project, along with the great team that&amp;#8217;ll be running it.  A couple weeks ago I put out a call for volunteers to help me provide a new community resource for discovering and discussing best practices in Ruby, and now, we&amp;#8217;re ready to get rolling.&lt;/p&gt;
&lt;p&gt;In addition to myself: &lt;a href="/about/jamesbritt.html"&gt;James Britt&lt;/a&gt;, &lt;a href="/about/wyhaines.html"&gt;Kirk Haines&lt;/a&gt;, &lt;a href="/about/rklemme.html"&gt;Robert Klemme&lt;/a&gt;, &lt;a href="/about/jm.html"&gt;Jeremy McAnally&lt;/a&gt;, &lt;a href="/about/seanohalpin.html"&gt;Sean O&amp;#8217;Halpin&lt;/a&gt;, &lt;a href="/about/judofyr.html"&gt;Magnus Holm&lt;/a&gt; and &lt;a href="/about/laktek.html"&gt;Lakshan Perera&lt;/a&gt; round out the team.  I am absolutely thrilled to have such a diverse and talented group to work with, and I can&amp;#8217;t wait to see the content that we&amp;#8217;ll produce together.&lt;/p&gt;
&lt;p&gt;The general theme we&amp;#8217;ve agreed upon for this blog is that each post should exhibit Ruby code that we can be proud of.  We want to expose best practices through practical examples, so you will surely see a lot of open source code being discussed here.  We want to give you less of &amp;#8220;Here&amp;#8217;s six great Rails plugins&amp;#8221; and more of &amp;#8220;Examples of Connascense in ActiveRecord&amp;#8221;, or &amp;#8220;Common Pitfalls in &lt;span class="caps"&gt;DSL&lt;/span&gt; Design, and How to Avoid Them&amp;#8221;.  Not every single post will be focused directly on best practices and idioms, but all will contain them.&lt;/p&gt;
&lt;p&gt;This will be a code and high-level design heavy blog.  We don&amp;#8217;t plan to bore you with war stories or skimp on the technical value of our content to promote our latest cute but useless hack.  That having been said, we plan to have fun while we write, and the occasional diversion will happen as a result.  However, it&amp;#8217;s safe to say that our content will be geared more towards the motivated developer looking to improve her craft rather than the general &amp;#8220;plzgivemethecodes&amp;#8221; crowd.  If that sounds like your kind of thing, I think you&amp;#8217;ll really enjoy this blog.&lt;/p&gt;
&lt;p&gt;The blog engine we&amp;#8217;ve decided to use is &lt;a href="http://github.com/sandal/korma"&gt;Korma&lt;/a&gt; which I&amp;#8217;m sure you&amp;#8217;ll hear more about in the near future.  It was designed specifically to run this blog, is git based, and gives us a lot of cool features that we wanted to make sure to have in place before launch.  Because we want to provide both the authors and the readers freedom to choose which content they are interested in, it is possible to subscribe to individual author feeds on this blog.  This means that if you like 6 of us, the two you don&amp;#8217;t like won&amp;#8217;t bother you.   Of course, we hope you like us all.&lt;/p&gt;
&lt;p&gt;Over time, we&amp;#8217;ll eventually begin accepting outside contributions to this blog, likely through something as simple as a fork and pull request on github.  This means if you have an idea for an article that you&amp;#8217;d like to see here, we may be accepting new content from third party contributors soon.  However, before we can do that, we need to wait for the dust to settle, so look for an announcement in a few weeks.&lt;/p&gt;
&lt;p&gt;It may take us a little while to work out the kinks in our blogging software.  We want to keep things simple, but there still might be a few bugs here or there.  If you run into problems using this blog, please email gregory.t.brown at gmail.com and let me know.&lt;/p&gt;
&lt;p&gt;I think that pretty much wraps up the welcome letter.  New posts should be cycling in within the next couple days, and we hope to remain active moving forward.  Thanks for checking out this new blog, and happy hacking!&lt;/p&gt;</description><author>gregory.t.brown@gmail.com (Gregory Brown)</author><pubDate>Tue, 07 Apr 2009 17:02:00 -0000</pubDate><link>http://blog.rubybestpractices.com/posts/gregory/welcome.html</link><guid>http://blog.rubybestpractices.com/posts/gregory/welcome.html</guid></item></channel></rss>